閱讀724 返回首頁    go 阿裏雲 go 技術社區[雲棲]


android 短信字符轉表情顯示過程

android 的短信實現方式普通用戶適應的話需要長時間的使用才能習慣,將andorid的短信模式設置成我們常用的(一般人用戶)的習慣。在查看字符轉圖片的過程中可以猜測出騰訊的QQ表情的原理應該是一樣的

隻是在傳送非常用的表情時是將byte數據轉換為image.

/***
     * 
         * 此方法描述的是:   注意此方法在做表情轉換的準備了
         * @author:wujun@cqghong.com,ppwuyi@sohu.com
         * @version: 2010-5-13 下午03:31:13
     */
    private void bindCommonMessage(final MessageItem msgItem) {
        if (mDownloadButton != null) {
            mDownloadButton.setVisibility(View.GONE);
            mDownloadingLabel.setVisibility(View.GONE);
        }
        // Since the message text should be concatenated with the sender's
        // address(or name), I have to display it here instead of
        // displaying it by the Presenter.
        mBodyTextView.setTransformationMethod(HideReturnsTransformationMethod.getInstance());

        // Get and/or lazily set the formatted message from/on the
        // MessageItem. Because the MessageItem instances come from a
        // cache (currently of size ~50), the hit rate on avoiding the
        // expensive formatMessage() call is very high.
        CharSequence formattedMessage = msgItem.getCachedFormattedMessage();
        if (formattedMessage == null) { //肯定為null應為msgItem.formattedMessage從誕生來就沒被注意過一次
            formattedMessage = formatMessage(msgItem.mContact, msgItem.mBody,   //重點到了
                                             msgItem.mSubject, msgItem.mTimestamp,
                                             msgItem.mHighlight);
            msgItem.setCachedFormattedMessage(formattedMessage);
        }
        mBodyTextView.setText(formattedMessage);

        if (msgItem.isSms()) {
            hideMmsViewIfNeeded();
        } else {
            Presenter presenter = PresenterFactory.getPresenter(
                    "MmsThumbnailPresenter", mContext,
                    this, msgItem.mSlideshow);
            presenter.present();

            if (msgItem.mAttachmentType != WorkingMessage.TEXT) {
                inflateMmsView();
                mMmsView.setVisibility(View.VISIBLE);
                setOnClickListener(msgItem);
                drawPlaybackButton(msgItem);
            } else {
                hideMmsViewIfNeeded();
            }
        }

        drawLeftStatusIndicator(msgItem.mBoxId);
        drawRightStatusIndicator(msgItem);
    }
//------------------------------------------------------------------------------

/***
     * 
         * 此方法描述的是:   開始轉換了哦
         * @author:wujun@cqghong.com,ppwuyi@sohu.com
         * @version: 2010-5-13 下午03:32:52
     */
    private CharSequence formatMessage(String contact, String body, String subject,
                                       String timestamp, String highlight) {
        CharSequence template = mContext.getResources().getText(R.string.name_colon); //遇到鬼了     <主題:<xliff:g >%s</xliff:g>>"
        SpannableStringBuilder buf =                   //把他當作StringBuffer隻是它可以放的不是 String 而已他能放跟多類型的東西
            new SpannableStringBuilder(TextUtils.replace(template,
                new String[] { "%s" },
                new CharSequence[] { contact })); //替換成聯係人

        boolean hasSubject = !TextUtils.isEmpty(subject); //主題
        if (hasSubject) {
            buf.append(mContext.getResources().getString(R.string.inline_subject, subject)); //buff先在是 聯係人 主題 XXXX      eg wuyi <主題:dsadasdsa> 我愛我家
        }

        if (!TextUtils.isEmpty(body)) {
            if (hasSubject) {
                buf.append(" - "); //如果內容有主題有就+ " - "    eg wuyi <主題:sdsadsadsa> - 
            }
            SmileyParser parser = SmileyParser.getInstance(); //獲得表情類了哦
            buf.append(parser.addSmileySpans(body)); //追查 急切關注中
        }
        if (!TextUtils.isEmpty(timestamp)) {
            buf.append("\n");
            int startOffset = buf.length();

            // put a one pixel high spacer line between the message and the time stamp as requested
            // by the spec.
            //把之間的信息和時間戳的要求間隔一個像素的高線
            //由規範
            buf.append("\n");
            buf.setSpan(new AbsoluteSizeSpan(3), startOffset, buf.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            startOffset = buf.length();
            buf.append(timestamp);
            buf.setSpan(new AbsoluteSizeSpan(12), startOffset, buf.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            // Make the timestamp text not as dark 改變某區域顏色   時間的地方為特殊顏色
            int color = mContext.getResources().getColor(R.color.timestamp_color);
            buf.setSpan(new ForegroundColorSpan(color), startOffset, buf.length(),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        if (highlight != null) {
            int highlightLen = highlight.length();

            String s = buf.toString().toLowerCase();
            int prev = 0;
            while (true) {
                int index = s.indexOf(highlight, prev);
                if (index == -1) {
                    break;
                }
                buf.setSpan(new StyleSpan(Typeface.BOLD), index, index + highlightLen, 0);
                prev = index + highlightLen;
            }
        }
        return buf;
    }

//------------------------------------------------------------

/**
     * Adds ImageSpans to a CharSequence that replace textual emoticons such
     * as :-) with a graphical version.
     * 
     * @param text A CharSequence possibly containing emoticons
     * @return A CharSequence annotated with ImageSpans covering any
     *         recognized emoticons.
     * 添加ImageSpans一個CharSequence的表情符號代替文字等     *如用圖形版本:-)。
     * 核心是把表情字符替換成ImageSpans的對象
     */
    public CharSequence addSmileySpans(CharSequence text) {
        SpannableStringBuilder builder = new SpannableStringBuilder(text);

        Matcher matcher = mPattern.matcher(text);
        while (matcher.find()) {
            int resId = mSmileyToRes.get(matcher.group());
            //注意下麵的一塊有點不好理解哦 但是是核心
            builder.setSpan(new ImageSpan(mContext, resId), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        return builder;
    }

總結:

android 在將字符轉化為表情圖像其核心代碼為

builder.setSpan(new ImageSpan(mContext, resId), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

原理過程是先匹配到表情字符然後通過new ImageSpan(上下文,表情地址)繪製出一個ImageView然後替換掉表情字符。

最後更新:2017-04-04 07:03:53

  上一篇:go Oracle監聽器啟動出錯:本地計算機上的OracleOraDb10g_home1TNSListener服務啟動後又停止了解決方案
  下一篇:go 與“雞”對話的時代孤獨