问题出在这个类:/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
重点关注这个方法。
private final CharSequence getSmallTime() {
Context context = getContext();
boolean b24 = DateFormat.is24HourFormat(context);// 取得是否是24小时格式的值
int res;
if (b24) {
res = R.string.twenty_four_hour_time_format;// 是24小时格式,取得“24小时时间格式”的资源ID
} else {
res = R.string.twelve_hour_time_format;// 不是24小时格式,取得“12小时时间格式”的资源ID
}
final char MAGIC1 = '\uEF00';
final char MAGIC2 = '\uEF01';
SimpleDateFormat sdf;
String format = context.getString(res); //根据资源ID取得时间格式,问题就出在这里,老外的时间格式是"h:mm a"而中国的格式是"a h:mm"。
if (!format.equals(mClockFormatString)) {
mClockFormat = sdf = new SimpleDateFormat(format);
mClockFormatString = format;
} else {
sdf = mClockFormat;
}
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DAY_OF_WEEK);
String todayIs = null;
String result = sdf.format(mCalendar.getTime());
if (mWeekdayStyle != WEEKDAY_STYLE_GONE) {
todayIs = whatDay(day);
result = todayIs + result;
}
SpannableStringBuilder formatted = new SpannableStringBuilder(result);
if (!b24) {
if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
if (mAmPmStyle == AM_PM_STYLE_GONE) {//判断是否设置了不显示AM/PM
formatted.delete(result.length() - 3, result.length());//这也是问题所在,这句话的作用是删除最后3个字符;result就是整个时间的文本,老外的文本是"10:58 AM",而中文是"上午 10:58",在英语环境下删掉最后3个字符得到"10:58"可以实现不显示AM/PM的功能,但在中文环境下删掉最后3个字符就成了"上午 10"
} else {
if (mAmPmStyle == AM_PM_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, result.length() - 3, result.length(),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
}
}
}
if (mWeekdayStyle != WEEKDAY_STYLE_NORMAL) {
if (todayIs != null) {
if (mWeekdayStyle == WEEKDAY_STYLE_GONE) {
formatted.delete(0, 4);
} else {
if (mWeekdayStyle == WEEKDAY_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, 0, 4,
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
}
}
}
return formatted;
}
其他的小号字显示上午下午、显示星期等等都是类似的问题,不能适用于多语言。
反编译修改解决方案:
之前论坛里出现过修改clock.smali文件的方法,思路是在拼接字符串时将上下午和时间的位置交换,这样在删除最后3个字符的时候可以删掉上下午的显示,但是这种方法在切换到英文语言环境时,即使设置显示AMPM也无法显示,因为AMPM被删掉了。
下面方法是从日期格式去修改,将中文日期格式修改的与英文一致,仅需要修改xml,对超超超新手来说够容易了吧。。
反编译framework-res,修改\res\values-zh-rCN\strings.xml
<string name="twelve_hour_time_format">a h:mm</string>
改为
<string name="twelve_hour_time_format">"h:mm a"</string>
源码修改解决方案:
这个应该不用多说,懂java的人都会,只需要改几句。。
贴上自己写的,方便比我还懒的人。。
思路就是根据当前的日期格式获取对应当前语言环境的上下午字符,然后仅仅删掉这部分字符,还有星期几部分的文本也改成了引用系统的字符串。
这些代码已经向AOKP提交,是否通过审核完全纯粹拼人品听天由命。。。。
private final CharSequence getSmallTime() {
Context context = getContext();
boolean b24 = DateFormat.is24HourFormat(context);
int res;
if (b24) {
res = R.string.twenty_four_hour_time_format;
} else {
res = R.string.twelve_hour_time_format;
}
final char MAGIC1 = '\uEF00';
final char MAGIC2 = '\uEF01';
SimpleDateFormat sdf;
String format = context.getString(res);
if (!format.equals(mClockFormatString)) {
mClockFormat = sdf = new SimpleDateFormat(format);
mClockFormatString = format;
} else {
sdf = mClockFormat;
}
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DAY_OF_WEEK);
String todayIs = null;
String result = sdf.format(mCalendar.getTime());
if (mWeekdayStyle != WEEKDAY_STYLE_GONE) {
todayIs = whatDay(day);
result = todayIs + result;
}
SpannableStringBuilder formatted = new SpannableStringBuilder(result);
if (!b24) {
if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
String AmPm;//声明一个字符串,用来放上下午的字符
if (format.indexOf("a")==0) {//判断时间格式中表示上下午的字符a是否在首位
AmPm = (new SimpleDateFormat("a ")).format(mCalendar.getTime());//在首位,按照"a "的格式获取当前上下午字符
} else {
AmPm = (new SimpleDateFormat(" a")).format(mCalendar.getTime());//不在首位,按照" a"的格式获取当前上下午字符
}
if (mAmPmStyle == AM_PM_STYLE_GONE) {
formatted.delete(result.indexOf(AmPm), result.lastIndexOf(AmPm)+AmPm.length());//删除开始位置是上下午字符首次出现的位置,删除结束位置是上下午字符最后出现位置加字符长度
} else {
if (mAmPmStyle == AM_PM_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, result.indexOf(AmPm), result.lastIndexOf(AmPm)+AmPm.length(),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
}
}
}
if (mWeekdayStyle != WEEKDAY_STYLE_NORMAL) {
if (todayIs != null) {
if (mWeekdayStyle == WEEKDAY_STYLE_GONE) {
formatted.delete(result.indexOf(todayIs), result.lastIndexOf(todayIs)+todayIs.length());
} else {
if (mWeekdayStyle == WEEKDAY_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, result.indexOf(todayIs), result.lastIndexOf(todayIs)+todayIs.length(),
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
}
}
}
return formatted;
}
/**
* pull the int given by DAY_OF_WEEK into a day string
*/
private String whatDay(int today) {
String todayIs = null;
switch (today) {
case 1:
todayIs = getResources().getString(R.string.day_of_week_medium_sunday);
break;
case 2:
todayIs = getResources().getString(R.string.day_of_week_medium_monday);
break;
case 3:
todayIs = getResources().getString(R.string.day_of_week_medium_tuesday);
break;
case 4:
todayIs = getResources().getString(R.string.day_of_week_medium_wednesday);
break;
case 5:
todayIs = getResources().getString(R.string.day_of_week_medium_thursday);
break;
case 6:
todayIs = getResources().getString(R.string.day_of_week_medium_friday);
break;
case 7:
todayIs = getResources().getString(R.string.day_of_week_medium_saturday);
break;
}
return todayIs.toUpperCase() + " ";
}
另一方案:通过ICU
import libcore.icu.LocaleData;
private final CharSequence getSmallTime() {
Context context = getContext();
boolean is24 = DateFormat.is24HourFormat(context);
LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
final char MAGIC1 = '\uEF00';
final char MAGIC2 = '\uEF01';
SimpleDateFormat sdf;
String format = is24 ? d.timeFormat24 : d.timeFormat12;
if (!format.equals(mClockFormatString)) {
/*
* Search for an unquoted "a" in the format string, so we can
* add dummy characters around it to let us find it again after
* formatting and change its size.
*/
if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
int a = -1;
boolean quoted = false;
for (int i = 0; i < format.length(); i++) {
char c = format.charAt(i);
if (c == '\'') {
quoted = !quoted;
}
if (!quoted && c == 'a') {
a = i;
break;
}
}
if (a >= 0) {
// Move a back so any whitespace before AM/PM is also in the alternate size.
final int b = a;
while (a > 0 && Character.isWhitespace(format.charAt(a-1))) {
a--;
}
format = format.substring(0, a) + MAGIC1 + format.substring(a, b)
+ "a" + MAGIC2 + format.substring(b + 1);
}
}
mClockFormat = sdf = new SimpleDateFormat(format);
mClockFormatString = format;
} else {
sdf = mClockFormat;
}
String result = sdf.format(mCalendar.getTime());
if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
int magic1 = result.indexOf(MAGIC1);
int magic2 = result.indexOf(MAGIC2);
if (magic1 >= 0 && magic2 > magic1) {
SpannableStringBuilder formatted = new SpannableStringBuilder(result);
if (AM_PM_STYLE == AM_PM_STYLE_GONE) {
formatted.delete(magic1, magic2+1);
} else {
if (AM_PM_STYLE == AM_PM_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, magic1, magic2,
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
formatted.delete(magic2, magic2 + 1);
formatted.delete(magic1, magic1 + 1);
}
return formatted;
}
}
return result;
}