Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 4.4.3上面,聯系人的頭像默認顯示首字母,但是不支持中文字符,修改支持中文

android 4.4.3上面,聯系人的頭像默認顯示首字母,但是不支持中文字符,修改支持中文

編輯:關於Android編程

在android 4.4.3上面,聯系人的頭像默認顯示首字母,但是不支持中文字符,如下圖:

\

如果聯系人名字的第一位是英文字符(a-z "| A-Z),則默認頭像將顯示該首字母。

如果支持中文時顯示第一個漢字,那就happy了。

那就看看如何通過修改源代碼來實現這一小功能吧~

我們還是先了解下聯系人頭像加載的流程吧~

聯系人頭像加載這個問題還是很有意思的,在Contacts中使用ContactPhotoManager類(嚴格來講是這個類的子類)來實現頭像的異步加載。

這個類還使用了LruCache來緩存圖片,相當的強大,對圖像的異步加載和緩存有興趣的同志們可以看看。

以主頁面的聯系人列表加載頭像為例。大致的調用流程為(只針對沒有設置頭像的聯系人,即photoUri是null):

DefaultContactListAdapter->bindView()
  ContactEntryListAdapter->buildQuickContact()
    ContactEntryListAdapter->getDefaultImageRequestFromCursor()
      ContactPhotoManagerImpl->loadPhoto()->provider:LetterTileDefaultImageProvider // 注意,使用的是DEFAULT_AVATAR對象
        LetterTileDefaultImageProvider->applyDefaultImage()
          LetterTileDefaultImageProvider->getDefaultImageForContact()
            LetterTileDrawable->drawLetterTile()->firsr char:高

在drawLetterTile函數執行drawText之前會調用isEnglishLetter來判斷字符串的首字符是否為英文字符,如果是,則將首字母畫上去;


\

否則,使用默認頭像

    private static boolean isEnglishLetter(final char c) {
        return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
    }

通過上面的流程解析,我們可以確定,是isEnglishLetter函數導致在中文字符不被描畫。

嗯,那我們就改造一下這個函數吧。不廢話,直接上代碼~

    private static boolean isEnglishLetter(final char c) {
        return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || isChineseLetter(c);
    }
    private static boolean isChineseLetter(final char c) {
        return isChinese(String.valueOf(c));
    }

至於isChinese函數的實現,代碼就不貼了,有興趣的可以參考我的一篇判斷字符為中文、日文、韓文的文章(http://www.cnblogs.com/Lefter/p/3804051.html)

經過這個改造後,我們就可以讓默認頭像顯示中文名字的第一個漢字了!

\

具體修改如下。嚴重OK
private static boolean isEnglishLetter(final char c) {
return ("A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}

private static boolean isChineseLetter(final char c) {
return isChinese(c);
}

private static boolean isChinese(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
return true;
}
return false;
}

//具體路徑 com.android.contacts.common.lettertiles; LetterTileDrawable.java

private void drawLetterTile(final Canvas canvas) {

// Draw background color.
sPaint.setColor(pickColor(mIdentifier));

sPaint.setAlpha(mPaint.getAlpha());
canvas.drawRect(getBounds(), sPaint);

// Draw letter/digit only if the first character is an english letter
if (mDisplayName != null && (isEnglishLetter(mDisplayName.charAt(0)) || isChineseLetter(mDisplayName.charAt(0)))) {
// Draw letter or digit.
sFirstChar[0] = Character.toUpperCase(mDisplayName.charAt(0));

// Scale text by canvas bounds and user selected scaling factor
final int minDimension = Math.min(getBounds().width(), getBounds().height());
sPaint.setTextSize(mScale * sLetterToTileRatio * minDimension);
//sPaint.setTextSize(sTileLetterFontSize);
sPaint.getTextBounds(sFirstChar, 0, 1, sRect);
sPaint.setColor(sTileFontColor);
final Rect bounds = getBounds();

// Draw the letter in the canvas, vertically shifted up or down by the user-defined
// offset
canvas.drawText(sFirstChar, 0, 1, bounds.centerX(),
bounds.centerY() + mOffset * bounds.height() + sRect.height() / 2,
sPaint);
}else {
// Draw the default image if there is no letter/digit to be drawn
final Bitmap bitmap = getBitmapForContactType(mContactType);
drawBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(),
canvas);
}

}

//為什麼頭像的背景會有8種顏色


#33b679
#536173
#855e86
#df5948
#aeb857
#547bca
#ae6b23
#e5ae4f


/** This should match the total number of colors defined in colors.xml for letter_tile_color */
private static final int NUM_OF_TILE_COLORS = 8; //八種顏色隨機生成

//獲取顏色
private int pickColor(final String identifier) {
if (TextUtils.isEmpty(identifier) || mContactType == TYPE_VOICEMAIL) {
return sDefaultColor;
}
// String.hashCode() implementation is not supposed to change across java versions, so
// this should guarantee the same email address always maps to the same color.
// The email should already have been normalized by the ContactRequest.
//隨機取得顏色值
final int color = Math.abs(identifier.hashCode()) % NUM_OF_TILE_COLORS;
return sColors.getColor(color, sDefaultColor);
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved