本文转载两篇有关定制datepicker的相关文章:
第一篇:DatePickerDialog的月份为英文转成数字 (转自:http://blog.csdn.net/zuohenghengl/article/details/52777021 )
在项目中,发现使用日期选择器的时候,不同手机系统日期选择框显示的日期不同,有的是中文的,有的是英文!之前以为是系统语言的问题,后面发现其实不是,是Android的日期选择框的bug。
一、现附上效果图,图片的黑白,只是主题不同而已
二、现在给出将月份都转换成数字的方法:
1、首先提供两个链接,帮助理解
(1)将日期选择框的年月日进行排序 http://blog.csdn.NET/lintcgirl/article/details/50476684
(2)将日期选择框的月份进行值范围设置 http://blog.csdn.net/jb521125/article/details/17042083
注:1、排序年月日,是防止在获取月份的NumberPicker不会出现数组越界异常,因为不同手机他的排序是不同的
2、使用Locale.CHINA并不能解决英文的问题
- DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
- Calendar c = Calendar.getInstance(Locale.CHINA);
2、写一个NewDatePicker类继承DatePickerDialog
/**
* 重写DatePickerDialog
* @author Administrator
* 将不同系统月份英文修改为数字
*/
public class NewDatePicker extends DatePickerDialog{
/**
* 月份的取值
*/
private String[] mDisplayMonths = {"1", "2", "3","4", "5", "6","7", "8", "9","10", "11", "12"};
/**
* 构造方法
* @param context
* @param callBack
* @param year
* @param monthOfYear
* @param dayOfMonth
*/
public NewDatePicker(Context context, OnDateSetListener callBack, int year,
int monthOfYear, int dayOfMonth) {
super(context, callBack, year, monthOfYear, dayOfMonth);
// TODO Auto-generated constructor stub
}
public NewDatePicker(Context context, int theme,
OnDateSetListener callBack, int year, int monthOfYear,
int dayOfMonth) {
super(context, theme, callBack, year, monthOfYear, dayOfMonth);
// TODO Auto-generated constructor stub
}
/**
* 重新排序 年月日(英文会出现 月 日 年的情况,所以需要排序)
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
LinearLayout mSpinners = (LinearLayout) findViewById(getContext().getResources().getIdentifier("android:id/pickers", null, null));
if (mSpinners != null) {
NumberPicker mYearSpinner = (NumberPicker) findViewById(getContext().getResources().getIdentifier("android:id/year", null, null));
NumberPicker mMonthSpinner = (NumberPicker) findViewById(getContext().getResources().getIdentifier("android:id/month", null, null));
NumberPicker mDaySpinner = (NumberPicker)findViewById(getContext().getResources().getIdentifier("android:id/day", null, null));
mSpinners.removeAllViews();
if (mYearSpinner != null) {
mSpinners.addView(mYearSpinner);
}
if (mMonthSpinner != null) {
mSpinners.addView(mMonthSpinner);
}
if (mDaySpinner != null) {
mSpinners.addView(mDaySpinner);
}
}
}
/**
* 有了年月日的正常顺序,下面的代码就不会出现数组越界异常
*/
@Override
public void onDateChanged(DatePicker view, int year, int month, int day) {
// TODO Auto-generated method stub
super.onDateChanged(view, year, month, day);
setTitle(year+"年 "+(month+1)+"月 "+day+"日");
//关键行
((NumberPicker)((ViewGroup)((ViewGroup)view.getChildAt(0)).getChildAt(0)).getChildAt(1)).setDisplayedValues(mDisplayMonths);
}
}
3、上面只是设置了滑动的动态变换,我们在使用的时候要进行初始设置
public class DatePickInput extends TextView {
/**
* 日期框
*/
private NewDatePicker mDialog;
private Context context;
/**
* 月份的取值
*/
private String[] mDisplayMonths = {"1", "2", "3","4", "5", "6","7", "8", "9","10", "11", "12"};
public DatePickInput(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
public DatePickInput(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public DatePickInput(Context context) {
super(context);
this.context = context;
}
@Override
protected void onFinishInflate() {
if (isInEditMode()) {
return;
}
setFocusable(false);
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
final Calendar c = Calendar.getInstance(Locale.CHINA);
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Date date = new Date();
try {
date = dateFormat.parse(getText().toString());
}
catch (ParseException e) {
}
c.setTime(date);
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
mDialog = new NewDatePicker(getContext(),
AlertDialog.THEME_HOLO_LIGHT,null,year,month,day);
mDialog.setTitle(year+"年 "+(month+1)+"月 "+day+"日");
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
DatePicker datePicker = mDialog.getDatePicker();
int year = datePicker.getYear();
int month = datePicker.getMonth();
int day = datePicker.getDayOfMonth();
c.set(year, month, day);
Date date = c.getTime();
Date curDate = new Date(System.currentTimeMillis());//获取当前时间
setText(dateFormat.format(c.getTime()));
}
});
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
setText("");
}
});
mDialog.show();
/**
* 初始设置月份
*/
DatePicker dp = mDialog.getDatePicker();
if (dp != null) {
((NumberPicker)((ViewGroup)((ViewGroup)dp.getChildAt(0)).getChildAt(0)).getChildAt(1)).setDisplayedValues(mDisplayMonths);
}
}
});
}
}
4、使用,只需要在配置文件中使用自定义的TextView( DatePickInput)就可以了,一点击就会弹出日期选择框
注:这里只是简单怎么使用,使用的时候还是根据你界面来直接使用就可以了
<你的包的路径.DatePickInput
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginRight="20dp"
android:background="@color/white"
android:gravity="right|center_vertical"
android:hint="请选择日期"
android:inputType="datetime"
android:focusable="false"
android:maxLength="50"
android:singleLine="true"
android:textColorHint="@color/hint" />
第二篇:
DatePickerDialog 只显示年 (解决不同语言顺序不一样的问题) (转自: http://blog.csdn.net/u012305958/article/details/49978677)
最近的项目 由于赶进度就直接使用了系统自带的日期选择器,但是做图表选择年份的时候遇到“胡同”了,只显示年份。去网上搜了下 有解决方法可以隐藏月日的(就是只让第一个位置的NumberPicker显示),但是那种方式只能在中文韩文等语言下可以,英文的话顺序是不一样的。下面2张图是中英文语言下的显示方式:
这样年的位置就不固定了,所以我要继续找解决方法。由于我用的4.4的api,于是乎自己去看了下4.4的源码 ,然后找到了这个东东:下面代理里面根据当前语言格式解析出来的char[]然后顺序显示年月日的顺序,那么我的下手点就很明确了,我要找到这个char[]里面‘y’的位置。
- private void reorderSpinners() {
- mSpinners.removeAllViews();
- // We use numeric spinners for year and day, but textual months. Ask icu4c what
- // order the user's locale uses for that combination. http://b/7207103.
- String pattern = ICU.getBestDateTimePattern("yyyyMMMdd", Locale.getDefault().toString());
- char[] order = ICU.getDateFormatOrder(pattern);
- final int spinnerCount = order.length;
- for (int i = 0; i < spinnerCount; i++) {
- switch (order[i]) {
- case 'd':
- mSpinners.addView(mDaySpinner);
- setImeOptions(mDaySpinner, spinnerCount, i);
- break;
- case 'M':
- mSpinners.addView(mMonthSpinner);
- setImeOptions(mMonthSpinner, spinnerCount, i);
- break;
- case 'y':
- mSpinners.addView(mYearSpinner);
- setImeOptions(mYearSpinner, spinnerCount, i);
- break;
- default:
- throw new IllegalArgumentException(Arrays.toString(order));
- }
- }
- }
我就在想这个系统控件特么不能设置固定的Locale,那我就投机取巧判断年份是哪一个位置不就可以了嘛,这样就动态隐藏对应的NumberPicker(DatePicker内部是用NumberPicker实现的)。然后我就去研究这个ICU.getBestDateTimePattern是什么东东,发现居然是framework层的代码,我还很二的去找到了这个类,这个方法居然关联到了另外一个东西,这时候我突然切换到5.0api去编译看这个DatePicker时发现那行代码变了居然成了DateFormat.getBestDateTimePattern(); 我当时对这个方法很诧异,以前4.0api上开发时都没见过这个静态方法啊,当我用4.0api去编译时 果然报错了。。这时我已经想转iOS了 毕竟我还是一个新手,对于各个版本的兼容完全是小白啊T_T...
然而看了下旁边ios开发的今天没来,我就硬着头皮去看了下4.0api上的DatePicker..发现它里面用的DateFormat.getDateFormatOrder(getContext()); 返回的就是一个char[]
(char[] order = ICU.getDateFormatOrder(pattern);的结果)。
这个时候很兴奋啊 我想 我对版本兼容再不懂 起码知道向下兼容吧。。然后我就获取到了“y”年对应的位置。下面贴下代码:
- public class YearPicker extends DatePickerDialog{
- public YearPicker(Context context, int theme, OnDateSetListener callBack,
- int year, int monthOfYear, int dayOfMonth) {
- super(context, theme, callBack, year, monthOfYear, dayOfMonth);
- this.setTitle(year + "年");
- try {
- int year_index=getYearPosition();
- for (int i = 0; i < 3; i++) {
- if(year_index!=i){
- ((ViewGroup) ((ViewGroup) this.getDatePicker().getChildAt(0)).getChildAt(0)).getChildAt(i).setVisibility(View.GONE);
- }
- }
- } catch (Exception e) {
- }
- }
- @Override
- public void onDateChanged(DatePicker view, int year, int month, int day) {
- // TODO Auto-generated method stub
- super.onDateChanged(view, year, month, day);
- this.setTitle(year + "年");
- }
- private int getYearPosition(){
- char[] order = DateFormat.getDateFormatOrder(getContext());
- final int spinnerCount = order.length;
- for (int i = 0; i < spinnerCount; i++) {
- switch (order[i]) {
- case 'd':
- break;
- case 'M':
- break;
- case 'y':
- return i;
- default:
- throw new IllegalArgumentException(Arrays.toString(order));
- }
- }
- return 0;
- }
- }
这是最终的结果图:
好久没写博客了,原谅我的表达的思路混乱,毕竟我是新手,今天这事绕了不少弯子。我觉得使用系统控件的童鞋碰到这样的问题肯定也很心烦,我就共享出来了。 我这个烂方法肯定也有考虑不到的地方,请大牛们评论里面指正。多谢。。。。。。
/-----------------------------i'm sorry 这个在5.0三星上面好像不行耶 于是乎 我又从framework代码里面找到了那个ICU.Java 然后把里面的第二个
- ICU.getDateFormatOrder(pattern);copy过来 然后调用了一个新的方法 new DateFormat().getBestDateTimePattern(Locale.getDefault(), "yyyyMMdd");由于这个方法4.4以上才有 所以我加上了版本判断 4.4以下调用上面的那个方法 4.4以上调用这个方法。。。Android不是说好的向下兼容么 真是日了狗了、、代码如下。。
- public class YearPicker extends DatePickerDialog{
- public YearPicker(Context context, int theme, OnDateSetListener callBack,
- int year, int monthOfYear, int dayOfMonth) {
- super(context, theme, callBack, year, monthOfYear, dayOfMonth);
- this.setTitle(year + "年");
- try {
- int year_index=getYearPosition();
- for (int i = 0; i < 3; i++) {
- if(year_index!=i){
- ((ViewGroup) ((ViewGroup) this.getDatePicker().getChildAt(0)).getChildAt(0)).getChildAt(i).setVisibility(View.GONE);
- }
- }
- } catch (Exception e) {
- }
- }
- @Override
- public void onDateChanged(DatePicker view, int year, int month, int day) {
- // TODO Auto-generated method stub
- super.onDateChanged(view, year, month, day);
- this.setTitle(year + "年");
- }
- private int getYearPosition(){
- char[] order=null;
- if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){
- String pattener= new DateFormat().getBestDateTimePattern(Locale.getDefault(), "yyyyMMdd");
- order=getDateFormatOrder(pattener);
- }else{
- order=DateFormat.getDateFormatOrder(getContext());
- }
- final int spinnerCount = order.length;
- for (int i = 0; i < spinnerCount; i++){
- System.out.println("Test "+order[i]);
- }
- for (int i = 0; i < spinnerCount; i++) {
- System.out.println("");
- switch (order[i]) {
- case 'd':
- System.out.println("Test1 "+i);
- break;
- case 'M':
- System.out.println("Test2 "+i);
- break;
- case 'y':
- System.out.println("Test3 "+i);
- return i;
- default:
- throw new IllegalArgumentException(Arrays.toString(order));
- }
- }
- return 0;
- }
- public static char[] getDateFormatOrder(String pattern) {
- char[] result = new char[3];
- int resultIndex = 0;
- boolean sawDay = false;
- boolean sawMonth = false;
- boolean sawYear = false;
- for (int i = 0; i < pattern.length(); ++i) {
- char ch = pattern.charAt(i);
- if (ch == 'd' || ch == 'L' || ch == 'M' || ch == 'y') {
- if (ch == 'd' && !sawDay) {
- result[resultIndex++] = 'd';
- sawDay = true;
- } else if ((ch == 'L' || ch == 'M') && !sawMonth) {
- result[resultIndex++] = 'M';
- sawMonth = true;
- } else if ((ch == 'y') && !sawYear) {
- result[resultIndex++] = 'y';
- sawYear = true;
- }
- } else if (ch == 'G') {
- // Ignore the era specifier, if present.
- } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
- throw new IllegalArgumentException("Bad pattern character '" + ch + "' in " + pattern);
- } else if (ch == '\'') {
- if (i < pattern.length() - 1 && pattern.charAt(i + 1) == '\'') {
- ++i;
- } else {
- i = pattern.indexOf('\'', i + 1);
- if (i == -1) {
- throw new IllegalArgumentException("Bad quoting in " + pattern);
- }
- ++i;
- }
- } else {
- // Ignore spaces and punctuation.
- }
- }
- return result;
- }
- }