短信ui--會話編輯界面(三)歷史記錄

會話編輯界面(三)歷史記錄

1、前言

      前文對接收者ui有一個簡單的瞭解,下面來看看短信歷史記錄的加載以及界面更新。例如當我們發送一條短信,界面上顯示“正在發送”,發送完後變成“已發送”,以及接收的短信時顯示接收時間等等功能,只所以用單獨的篇幅來講解,主要考慮到該ui的重要性。

2、功能分析

2.1 初始化

      短信歷史記錄界面的初始仍然是在ComposeMessageActivity的onCreate方法中通過調用initMessageList方法:
    private void initMessageList() {
        if (mMsgListAdapter != null) {
            return;
        }
        String highlightString = getIntent().getStringExtra("highlight");
        Pattern highlight = highlightString == null
            ? null
            : Pattern.compile("\\b" + Pattern.quote(highlightString), Pattern.CASE_INSENSITIVE);

        // Initialize the list adapter with a null cursor.
        mMsgListAdapter = new MessageListAdapter(this, null, mMsgListView, true, highlight);
        mMsgListAdapter.setOnDataSetChangedListener(mDataSetChangedListener);
        mMsgListAdapter.setMsgListItemHandler(mMessageListItemHandler);
        mMsgListView.setAdapter(mMsgListAdapter);
        mMsgListView.setItemsCanFocus(false);
        mMsgListView.setVisibility(View.VISIBLE);
        mMsgListView.setOnCreateContextMenuListener(mMsgListMenuCreateListener);
        mMsgListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (view != null) {
                    ((MessageListItem) view).onMessageListItemClick();
                }
            }
        });
    }
該方法初始化用於顯示歷史記錄列表地的Listview,以及用於填充listView的adapter,並設置監聽器和長按menu。

2.2  UI分析

2.2.1 UI 簡介

       下面就來看看這個歷史記錄是什麼樣的,有哪些界面元素組成,來初步認識一下這個界面。下圖爲短信歷史記錄的ui,

歷史記錄
從上圖可以看出歷史記錄的ui至少包含以下ui組件:聯繫人頭像、聯繫人號碼或者姓名、內容、接收和發送時間,如果是彩信有對應附件、主題的顯示。當然除了這些還有一些錯誤顯示ui等等。

2.2.2 ui佈局分析

   要窺探該界面怎麼佈局,首先來看看MessageListAdapter類是如何綁定ui的?該類有兩個重要的方法來完成ui和數據的綁定bindView、newView;
其中newView用於加載佈局文件,定義一個短信ui,bindview用於將從短信數據庫獲取的數據設置到newView上的ui上。這裏來看看系統怎麼定義這個ui的
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return mInflater.inflate(R.layout.message_list_item, parent, false);
    }
那該ui定義在佈局文件裏面,這裏簡短閒扯android ui的高明,之前有做過J2ME開發的同學可能對android的xml佈局印象深刻,估計有很多同學疑問了J2ME爲啥不引進這個xml佈局,J2ME的ui實現完全靠一行一行的代碼,且複雜冗長,一言難盡哈。這裏來看看神祕的佈局文件。
<com.android.mms.ui.MessageListItem
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/msg_list_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/listitem_background"
    android:orientation="horizontal">
    <LinearLayout android:id="@+id/mms_layout_view_parent"
        android:paddingLeft="5dip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical" >
        <ViewStub android:id="@+id/mms_layout_view_stub"
            android:layout="@layout/mms_layout_view"         mms 附件ui,其還有自己的佈局文件,大家都可以查看彩信附件的ui,該ui包含一個iamgeview
            android:layout_width="match_parent"              另外就是一個playbutton   
            android:layout_height="wrap_content"/>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <android.widget.QuickContactBadge
                android:layout_marginLeft="0dip"
                android:layout_marginRight="5dip"
                android:layout_marginTop="5dip"              
                android:layout_marginBottom="5dip"
                android:id="@+id/avatar"
                style="?android:attr/quickContactBadgeStyleWindowSmall" /> 用於顯示聯繫人圖標
            <View
                android:layout_width="match_parent"
                android:layout_height="0dip"
                android:layout_below="@id/avatar" />
            <LinearLayout android:id="@+id/status_icons"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBottom="@id/text_view"         短信內容包含、主題、時間
                android:layout_alignParentRight="true"
                android:layout_marginBottom="8dip"
                android:orientation="horizontal" >
                <ImageView
                    android:id="@+id/locked_indicator"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/ic_lock_message_sms"    鎖定短信的image,鎖的圖標,該功能就是當你鎖定一條短信後,刪除該會話,該會話的
                    android:paddingRight="3dip"                    其他短信都刪除,但是加鎖的短信不被刪除,這樣可以防止誤刪
                    android:visibility="gone" />
                <ImageView
                    android:id="@+id/delivered_indicator"             
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"          短信傳送報告,有可能是fail的圖標、以及打開傳送報告後有一個傳送圖標
                    android:paddingRight="3dip"
                    android:visibility="gone" />

                <ImageView
                    android:id="@+id/details_indicator"
                    android:layout_width="wrap_content"            暫時不清楚
                    android:layout_height="wrap_content"            
                    android:src="@drawable/ic_sms_mms_details"
                    android:visibility="gone" />
                </LinearLayout>
            </RelativeLayout>
        </LinearLayout>
    <ViewStub android:id="@+id/mms_downloading_view_stub"
        android:layout="@layout/mms_downloading_view"          如果彩信未下載會顯示該ui,該ui有一個下載button,一個textview,當點擊button
        android:layout_gravity="center_vertical"               狀態更新爲正在下載
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</com.android.mms.ui.MessageListItem>
基本上一條短彩信包含的ui就是上述,會根據當前短彩信的狀態來設置來設置對應UI 的值,顯示給用戶,至於如何設置,下回分解。

2.2.3  數據的綁定

綁定數據bindView方法來實現,核心的代碼如下
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        if (view instanceof MessageListItem) {
            String type = cursor.getString(mColumnsMap.mColumnMsgType);
            long msgId = cursor.getLong(mColumnsMap.mColumnMsgId);
            MessageItem msgItem = getCachedMessageItem(type, msgId, cursor);
            if (msgItem != null) {
                MessageListItem mli = (MessageListItem) view;
                MessageItem oldMessageItem = mli.getMessageItem();
                if (oldMessageItem != null) {
                    String oldAddress = oldMessageItem.mAddress;
                    if (oldAddress != null) {
                        HashSet<MessageListItem> set = mAddressToMessageListItems.get(oldAddress);
                        if (set != null) {
                            set.remove(mli);
                        }
                    }
                }
                mli.bind(mAvatarCache, msgItem); 重要

上面的代碼做的事情很簡單,將查詢到的短信綁定到ui,這裏的綁定涉藉助於MessageListItem的bind方法。對於每個字段怎麼設置的這裏不做解析,有興趣的大家可以看看代碼,很簡單。

2.4 長按按鈕

對於每條短信,這裏給他們設置了一個長按事件,給用戶提供了以下功能。

這裏沒有完全顯示,但我們可以通過代碼知道其具體有哪些功能。mMsgListMenuCreateListener該變量用於創建menu,menu的監聽的監聽事件處理MsgListMenuClickListener來完成。以下代碼是對每個menu的處理
    private final class MsgListMenuClickListener implements MenuItem.OnMenuItemClickListener {
        public boolean onMenuItemClick(MenuItem item) {
            if (!isCursorValid()) {
                return false;
            }
            Cursor cursor = mMsgListAdapter.getCursor();
            String type = cursor.getString(COLUMN_MSG_TYPE);
            long msgId = cursor.getLong(COLUMN_ID);
            MessageItem msgItem = getMessageItem(type, msgId, true);
            if (msgItem == null) {
                return false;
            }
            switch (item.getItemId()) {
                case MENU_EDIT_MESSAGE:       編輯短信
                    editMessageItem(msgItem);
                    drawBottomPanel();
                    return true;

                case MENU_COPY_MESSAGE_TEXT:  複製短信文本
                    copyToClipboard(msgItem.mBody);
                    return true;

                case MENU_FORWARD_MESSAGE:     轉發短信
                    forwardMessage(msgItem);
                    return true;

                case MENU_VIEW_SLIDESHOW:     查看幻燈片
                    MessageUtils.viewMmsMessageAttachment(ComposeMessageActivity.this,
                            ContentUris.withAppendedId(Mms.CONTENT_URI, msgId), null);
                    return true;

                case MENU_VIEW_MESSAGE_DETAILS: { 查看短信信息:包含短信大小、發送和接收的時間
                    String messageDetails = MessageUtils.getMessageDetails(
                            ComposeMessageActivity.this, cursor, msgItem.mMessageSize);
                    new AlertDialog.Builder(ComposeMessageActivity.this)
                            .setTitle(R.string.message_details_title)
                            .setMessage(messageDetails)
                            .setPositiveButton(android.R.string.ok, null)
                            .setCancelable(true)
                            .show();
                    return true;
                }
                case MENU_DELETE_MESSAGE: {刪除短信
                    DeleteMessageListener l = new DeleteMessageListener(
                            msgItem.mMessageUri, msgItem.mLocked);
                    confirmDeleteDialog(l, msgItem.mLocked);
                    return true;
                }
                case MENU_DELIVERY_REPORT: 短信傳送報告
                    showDeliveryReport(msgId, type);
                    return true;

                case MENU_COPY_TO_SDCARD: { 複製短信到sdcard
                    String successMessage = getResources().getString(R.string.copy_to_sdcard_success, SAVED_ATTACHMENT_DIR);
                    String resultMessage = copyMedia(msgId) ? successMessage : getResources()
                            .getString(R.string.copy_to_sdcard_fail);
                    Toast.makeText(ComposeMessageActivity.this, resultMessage, Toast.LENGTH_SHORT).show();
                    return true;
                }

                case MENU_COPY_TO_DRM_PROVIDER: {
                    int resId = getDrmMimeSavedStringRsrc(msgId, copyToDrmProvider(msgId));
                    Toast.makeText(ComposeMessageActivity.this, resId, Toast.LENGTH_SHORT).show();
                    return true;
                }

                case MENU_LOCK_MESSAGE: {  鎖短信
                    lockMessage(msgItem, true);
                    return true;
                }

                case MENU_UNLOCK_MESSAGE: {解鎖
                    lockMessage(msgItem, false);
                    return true;
                }

                case MENU_COPY_TO_SIM: { 複製短信到sim卡
                    if (hasIccCardCount() > 1) {
                        String[] items = new String[TelephonyManager.getPhoneCount()];
                        for (int i = 0; i < items.length; i++) {
                            items[i] = getMultiSimName(i);
                        }
                        CopyToSimSelectListener listener = new CopyToSimSelectListener(msgItem);
                        new AlertDialog.Builder(ComposeMessageActivity.this)
                            .setTitle(R.string.copy_to_sim)
                            .setIcon(android.R.drawable.ic_dialog_info)
                            .setPositiveButton(android.R.string.ok, listener)
                            .setSingleChoiceItems(items, 0, listener)
                            .setCancelable(true)
                            .show();
                    } else {
                        copyToSimWithToast(msgItem);
                    }
                    return true;
                }

                default:
                    return false;
            }
        }
    }

3、總結


   這裏對該ui做了一個簡單的介紹,至於其中一些具體的小細節,可以看一下代碼就明白了。




  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章