Android Setting 日期相关API,自定义DatePicker
程序员文章站
2022-03-31 20:40:25
最近在做setting日期相关的工作,整理一下相关的api(相关代码源自android 8.0高通代码)
注意:以下api来自setting,使用的地方也在setting中,如果其他非应用使用,可能...
最近在做setting日期相关的工作,整理一下相关的api(相关代码源自android 8.0高通代码)
注意:以下api来自setting,使用的地方也在setting中,如果其他非应用使用,可能需要加权限
设置日期api
void setdate(int year, int month, int day) { calendar c = calendar.getinstance(); log.d(tag, "setdate: year " + year + " month " + month + " day " + day); c.set(calendar.year, year); c.set(calendar.month, month); c.set(calendar.day_of_month, day); long when = math.max(c.gettimeinmillis(), datepreferencecontroller.datepreferencehost.min_date); if (when / 1000 < integer.max_value) { ((alarmmanager) mcontext.getsystemservice(context.alarm_service)).settime(when); } }
datepreferencecontroller.datepreferencehost.min_date:是一个长整型常量,表示日期可以设置的最小值。
dateformat api
private void set24hour(boolean is24hour) { log.d(tag, "set24hour: "); settings.system.putstring(mcontext.getcontentresolver(), settings.system.time_12_24, is24hour ? hours_24 : hours_12); }
指定12小时 24小时制
获取当前dateformat api
public boolean is24hour() { log.d(tag, "is24hour: "); return dateformat.is24hourformat(mcontext); }
设置时间api
void settime(int hourofday, int minute) { calendar c = calendar.getinstance(); c.set(calendar.hour_of_day, hourofday); c.set(calendar.minute, minute); c.set(calendar.second, 0); c.set(calendar.millisecond, 0); long when = math.max(c.gettimeinmillis(), timepreferencehost.min_date); if (when / 1000 < integer.max_value) { ((alarmmanager) mcontext.getsystemservice(context.alarm_service)).settime(when); } }
设置时区api
final alarmmanager alarm = (alarmmanager) activity.getsystemservice(context.alarm_service); alarm.settimezone(tzid);
这里tzid是一个字符串,形式为 大洲/city
比如asia/shanghai
在android 8.0高通中一共有89个城市,设置的tzid必须在这89个数据中,否则底层会抛出异常,找不到指定的时区,应用crash
自定义datepicker
由于客户给出的设计图和android原生的datepicker相差过大,只能自定义datepicker了。
注意:这里使用的numberpicker在framework层的源码做过少量修改。设计图给出的样式比较丑,还没有原生的漂亮。给出的设计大概是这样的
java代码
package com.android.settings.datetime; import android.app.alarmmanager; import android.app.alertdialog; import android.content.context; import android.os.build; import android.support.annotation.nonnull; import android.support.annotation.requiresapi; import android.util.log; import android.view.keyevent; import android.view.viewgroup.layoutparams; import android.view.windowmanager; import android.widget.numberpicker; import com.android.settings.r; import java.util.calendar; /** * created by caihuijian on 18-5-18. */ public class customdatepickerdialog extends alertdialog { private static final string tag = "customdatepickerdialog"; private numberpicker mnumberyear; private numberpicker mnumbermonth; private numberpicker mnumberday; private static final int max_year = 37;//暂定 系统某处定义了 private static final int min_year = 7;//暂定 系统某处定义了 private static final int big_month_day = 31;//大月31天 private static final int small_month_day = 30;//小月30天 private static final int leap_feb_day = 29;//闰年二月29天 private static final int not_leap_feb_day = 28;//平年二月28天 private static final int min_day = 1;//最小日 private static final int max_month = 12;//最大月数 private static final int min_month = 1;//最小月数 private context mcontext = null; final calendar calendar = calendar.getinstance(); protected customdatepickerdialog(@nonnull context context) { super(context); this.mcontext = context; } @requiresapi(api = build.version_codes.honeycomb) @override public void show() { super.show(); //全屏dialog windowmanager.layoutparams layoutparams = getwindow().getattributes(); layoutparams.width = layoutparams.match_parent; layoutparams.height = layoutparams.match_parent; getwindow().getdecorview().setpadding(0, 0, 0, 0); getwindow().setattributes(layoutparams); getwindow().getdecorview().setbackgroundresource(0x00000000); setcustomlayout(); } @requiresapi(api = build.version_codes.honeycomb) private void setcustomlayout() { setcontentview(r.layout.cus_date_picker_dialog); //控件初始化 mnumbermonth = (numberpicker) findviewbyid(r.id.month); mnumberday = (numberpicker) findviewbyid(r.id.day); mnumberyear = (numberpicker) findviewbyid(r.id.year); setviewmaxmin(); initallview(); mnumberyear.setonvaluechangedlistener(yearchangelistener); mnumbermonth.setonvaluechangedlistener(monthchangelistener); mnumberday.setonvaluechangedlistener(daychangelistener); } //取得当前时间 设置到view @requiresapi(api = build.version_codes.honeycomb) private void initallview() { int year, monthofyear, dayofmonth; if (calendar != null) { //因为控件只显示年的后两位 所以对100取余 year = calendar.get(calendar.year) % 100; monthofyear = calendar.get(calendar.month); dayofmonth = calendar.get(calendar.day_of_month); mnumberyear.setvalue(year); mnumbermonth.setvalue(monthofyear); mnumberday.setvalue(dayofmonth); } } @requiresapi(api = build.version_codes.honeycomb) private int getmonthday(int month) { switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return big_month_day; case 4: case 6: case 9: case 11: return small_month_day; case 2: int year = mnumberyear.getvalue(); boolean isleap = isleapyear(year); if (isleap) { return leap_feb_day; } else { return not_leap_feb_day; } } return 0; } //ui中,年只有2位,可以使用这两位进行闰年判断 boolean isleapyear(int year) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { log.d(tag, "isleapyear: " + year + "年是闰年"); return true; } else { log.d(tag, "isleapyear: " + year + "年不是闰年"); return false; } } @requiresapi(api = build.version_codes.honeycomb) private void setviewmaxmin() { mnumbermonth.setmaxvalue(max_month); mnumbermonth.setminvalue(min_month); mnumberday.setmaxvalue(big_month_day); mnumberday.setminvalue(min_day); mnumberyear.setmaxvalue(max_year); mnumberyear.setminvalue(min_year); } @requiresapi(api = build.version_codes.honeycomb) @override public boolean onkeyup(int keycode, keyevent event) { switch (keycode) { case keyevent.keycode_dpad_center: if (mnumberyear.isfocused()) { mnumbermonth.requestfocus(); } else if (mnumbermonth.isfocused()) { mnumberday.requestfocus(); } else if (mnumberday.isfocused()) { setdate(2000 + mnumberyear.getvalue(), mnumbermonth.getvalue(), mnumberday.getvalue()); this.dismiss(); } return true; case keyevent.keycode_back: if (mnumberday.isfocused()) { mnumbermonth.requestfocus(); return true; } else if (mnumbermonth.isfocused()) { mnumberyear.requestfocus(); return true; } } //手动输入数字 填充年月日 if (keycode >= keyevent.keycode_0 && keycode <= keyevent.keycode_9) { int singledigit = keycode - keyevent.keycode_0; log.d(tag, "onkeyup: keycode" + keycode); if (mnumberyear.hasfocus()) { log.d(tag, "onkeyup: year"); //手动输入不会触发valuechangelistener,需要自己处理 int yearchangeto = manualinput(mnumberyear, singledigit); yeartextchange(yearchangeto); } else if (mnumbermonth.hasfocus()) { log.d(tag, "onkeyup: month"); //手动输入不会触发valuechangelistener,需要自己处理 int monthchange = manualinput(mnumbermonth, singledigit); monthtextchange(monthchange); } else if (mnumberday.hasfocus()) { manualinput(mnumberday, singledigit); } return true; } return super.onkeyup(keycode, event); } @requiresapi(api = build.version_codes.honeycomb) private int manualinput(numberpicker numberpicker, int userinput) { //手动输入逻辑: //取个位数放到十位上 //输入值作为个位数 //十位 个位相加 //判断该值是否在最大与最小值之间 小于最小值取最小值 大于最大值取最大值 十位取最大值的十位数,个位为用户输入 int temp = numberpicker.getvalue(); int value = temp % 10 * 10 + userinput; int maxvalue = numberpicker.getmaxvalue(); int minvalue = numberpicker.getminvalue(); if (value < minvalue) { value = minvalue; } else if (value > maxvalue) { value = maxvalue - maxvalue % 10 + userinput; if(value > maxvalue){ value = maxvalue; } } log.d(tag, "manualinput: value" + value); numberpicker.setvalue(value); return value; } //设置日期api @requiresapi(api = build.version_codes.froyo) void setdate(int year, int month, int day) { calendar c = calendar.getinstance(); log.d(tag, "setdate: year " + year + " month " + month + " day " + day); c.set(calendar.year, year); c.set(calendar.month, month); c.set(calendar.day_of_month, day); long when = math.max(c.gettimeinmillis(), datepreferencecontroller.datepreferencehost.min_date); if (when / 1000 < integer.max_value) { ((alarmmanager) mcontext.getsystemservice(context.alarm_service)).settime(when); } } numberpicker.onvaluechangelistener yearchangelistener = new numberpicker.onvaluechangelistener() { @requiresapi(api = build.version_codes.honeycomb) @override public void onvaluechange(numberpicker numberpicker, int yearold, int yearnew) { yeartextchange(yearnew); } }; numberpicker.onvaluechangelistener monthchangelistener = new numberpicker.onvaluechangelistener() { @requiresapi(api = build.version_codes.honeycomb) @override public void onvaluechange(numberpicker numberpicker, int monthold, int monthnew) { monthtextchange(monthnew); } }; numberpicker.onvaluechangelistener daychangelistener = new numberpicker.onvaluechangelistener() { @override public void onvaluechange(numberpicker numberpicker, int dayold, int daynew) { } }; //年的控件变化需要做的处理 @requiresapi(api = build.version_codes.honeycomb) public void yeartextchange(int yearnew) { //年的变化会导致2月是否有29日变化 boolean isleapyear = isleapyear(yearnew); int month = mnumbermonth.getvalue(); if (isleapyear && month == 2) { //闰年二月 mnumberday.setmaxvalue(29); } else if (!isleapyear && month == 2) { //非闰年二月 mnumberday.setmaxvalue(28); } } //月的控件变化需要做的处理 @requiresapi(api = build.version_codes.honeycomb) private void monthtextchange(int monthnew) { int monthday = getmonthday(monthnew); mnumberday.setmaxvalue(monthday); } }
xml
使用
customdatepickerdialog datepickerdialog = new customdatepickerdialog(getactivity()); datepickerdialog.show();