android 4.4.3上面,联系人的头像默认显示首字母,但是不支持中文字符,修改支持中文

在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种颜色

<!-- Make sure to also update LetterTileProvider#NUM_OF_TILE_COLORS when adding or removing

colors -->

<array name="letter_tile_colors">

<item>#33b679</item>

<item>#536173</item>

<item>#855e86</item>

<item>#df5948</item>

<item>#aeb857</item>

<item>#547bca</item>

<item>#ae6b23</item>

<item>#e5ae4f</item>

</array>

/** 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);

}

时间: 2024-10-13 06:38:24

android 4.4.3上面,联系人的头像默认显示首字母,但是不支持中文字符,修改支持中文的相关文章

Android使用READ_CONTACTS读取手机联系人

实例代码: package com.example.readcontacts; import java.io.InputStream; import java.util.ArrayList; import android.app.ListActivity; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import androi

Android通讯录管理(获取联系人、通话记录、短信消息)(二)

http://blog.csdn.net/wwj_748/article/details/19970271 Android通讯录管理(获取联系人.通话记录.短信消息)(二) 2014-02-26 11:40 9076人阅读 评论(11) 收藏 举报  分类: [Android通讯录模块开发](10)  版权声明:本文为博主原创文章,未经博主允许不得转载. Android通讯录管理(获取联系人.通话记录.短信消息)(二) 前言:上一篇博客介绍的是获取联系人的实现,本篇博客将介绍通话记录的实现. 同

Android通讯录模糊查询搜索(号码,姓名,首字母简拼,全拼),批量选取联系人

Android通讯录模糊查询搜索(号码,姓名,首字母简拼,全拼),批量选取联系人 公司最近的项目中遇到一个需求需要读取通讯录联系人,并需要支持对联系人的模糊查询及批量选取,网上找了好几个例子,模糊查询这块处理的都有点小瑕疵,最终自己在各位网友的辛勤贡献基础之上进行了优化,最终做出了联系人模糊查询. 支持以下功能: 1.按 号码 , 姓名 , 首字母简拼 , 全拼 模糊查询 2.支持[A-Z]快速导航 3.支持联系人按首字母分类 4.支持联系人批量选取. 具体github地址:  https://

android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的Android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体上来说,左边是一个ListView,右边是一个自定义View,但是左边的ListView和我们平常使用的ListView还有一点点不同,就是在ListView中我对所有的联系人进行了分组,那么这种效果的实现最常见的就是两种思路: 1.使用ExpandableListView来实现这种分组效果 2.使

Android之ListView异步加载图片且仅显示可见子项中的图片

折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整实例都没看到,只有自己一点点研究了,总体感觉 android 下面要显示个图片真不容易啊. 项目主要实现的功能: 异步加载图片图片内存缓存.异步磁盘文件缓存解决使用 viewHolder 后出现的图片错位问题优化列表滚动性能,仅显示可见子项中的图片无需固定图片显示高度,对高度进行缓存使列表滚动时不会

android 设置字体颜色、EditText自动输入转换成大写字母的多种方式

在TextView上面设置某一个字的字体颜色为指定颜色时,可以通过java类SpannableString类和Html语言来实现. (一)SpannableString类方式 private void setText(TextView t){ String text = t.getText().toString().trim(); SpannableString span = new SpannableString(text); span.setSpan(new ForegroundColorS

ios/android获取汉字拼音首字母

android/ios开发如何获取汉字拼音的首字母? 提供的一个比较好的方案,是使用 c语言编写的一个算法,可以 在ios和 android.下面提供一个可以使用的代码,并且附上使用方法: /* * pinyin.c * Chinese Pinyin First Letter * * Created by George on 4/21/10. * Copyright 2010 RED/SAFI. All rights reserved. * */ #define HANZI_START 1996

自定义绘制android EditText的背景,定义EditText文字的显示样式

EditText可以通过layer-list来绘制背景: <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="rectangle" //框为矩形 > &l

Android Studio 配置模拟器AVD存放路径(默认在c盘,解决c盘空间不够问题)

转自原文Android Studio 配置模拟器AVD存放路径(默认在c盘,解决c盘空间不够问题) Android Studio 安装之后,默认的会给我们创建一个 Nexus 的模拟器, 这个模拟器的镜像文件放在了 C:\Users\Administrator\.android  中 其中的avd文件夹就是用来存放,模拟器镜像文件的. 相当占用c盘空间,像我这种c盘空间不大的,看着真的不爽. 好了现在点进去C:\Users\Administrator\.android\avd 现在  你只需要将