时钟显示不全问题源码简单分析+解决方案

这个问题不麻烦,懂JAVA的都能看懂,原因还是老外偷懒。。
问题出在这个类:/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;


    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值