缩小的时间选择器(纪念该死的MX4)
首先,庆祝我司婴儿喂养记录类应用“萌萌记”登陆各大应用市场,时间仓促,水平有限,多有不足,企望海涵。(做出伟大产品的公司,自我评价往往以“批评”和“自嘲”为主,而不是以“肯定”和“表扬”为主。我认识的杰出成就人士都认为自己做的不好,之所以能成功只是因为其他人做的更差。——Paul Graham,哈哈哈)
言归正传,android应用中日期选择器与时间选择器用的场景很多,但是原生控件并不好用。例如,需求是弹出一个Dialog,在Dialog上并排显示DatePicker与TimePicker,会发现大多屏幕放不下。此时,我们百度一下(别吐槽我用百度,百度只是个孩子),会得到
/**
* 调整FrameLayout大小
* @param tp
*/
public static void resizePikcer(FrameLayout tp){
List<NumberPicker> npList = findNumberPicker(tp);
for(NumberPicker np:npList){
resizeNumberPicker(np);
}
}
/**
* 得到viewGroup里面的numberpicker组件
* @param viewGroup
* @return
*/
private static List<NumberPicker> findNumberPicker(ViewGroup viewGroup){
List<NumberPicker> npList = new ArrayList<NumberPicker>();
View child = null;
if(null != viewGroup){
for(int i = 0;i<viewGroup.getChildCount();i++){
child = viewGroup.getChildAt(i);
if(child instanceof NumberPicker){
npList.add((NumberPicker)child);
}
else if(child instanceof LinearLayout){
List<NumberPicker> result = findNumberPicker((ViewGroup)child);
if(result.size()>0){
return result;
}
}
}
}
return npList;
}
/*
* 调整numberpicker大小
*/
private static void resizeNumberPicker(NumberPicker np){
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(100, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(15, 5, 15, 5);
np.setLayoutParams(params);
}
代码讲的很清晰,遍历ViewGroup,拿到里面的NumberPicker,重设NumberPickerd的宽度和margin。可能有人不明白为什么取NumberPicker,因为DatePicker与TimePicker就是NumberPicker拼成的。 然后,我们做下适配
int picker_width = (screen_width-margin)/5-30;//年月日时分5项
float text_size = picker_width/4;
Utils.resizeNumberPicker(picker, picker_width);
public static void resizeNumberPicker(NumberPicker np,int width){
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(15, 5, 15, 5);
np.setLayoutParams(params);
}
打完收工……怎么可能!!!这么写还有点干货么??!!上面只是开胃甜品,下面是正餐。
##纪念该死的MX4
跑到MX4上,我懵逼了,原生DatePicker被改成了好大一个日历!!! 没办法了,只能用NumberPicker去拼一个了
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/white_shape"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:paddingRight="20dp"
android:paddingLeft="20dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="年"
android:textColor="@color/font_color_1"
android:textSize="16sp"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="月"
android:textColor="@color/font_color_1"
android:textSize="16sp"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="日"
android:textColor="@color/font_color_1"
android:textSize="16sp"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="时"
android:textColor="@color/font_color_1"
android:textSize="16sp"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="分"
android:textColor="@color/font_color_1"
android:textSize="16sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_weight="1">
<NumberPicker
android:id= "@+id/picker_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_weight="1">
<NumberPicker
android:id= "@+id/picker_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_weight="1">
<NumberPicker
android:id= "@+id/picker_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_weight="1">
<NumberPicker
android:id= "@+id/picker_hour"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_weight="1">
<NumberPicker
android:id= "@+id/picker_minute"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/submit"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="30dp"
android:src="@mipmap/btn_queren" />
</LinearLayout>
picker_year = (NumberPicker) layout.findViewById(R.id.picker_year);
picker_month = (NumberPicker) layout.findViewById(R.id.picker_month);
picker_day = (NumberPicker) layout.findViewById(R.id.picker_day);
picker_hour = (NumberPicker) layout.findViewById(R.id.picker_hour);
picker_minute = (NumberPicker) layout.findViewById(R.id.picker_minute);
picker_year.setMaxValue(2020);
picker_year.setMinValue(2010);
if(year<=2020 && year>=2010){
picker_year.setValue(year);
}else{
picker_year.setValue(2015);
}
picker_month.setFormatter(new timeFormatter());
picker_month.setMaxValue(12);
picker_month.setMinValue(1);
picker_month.setValue(month);
picker_month.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker numberPicker, int i, int i2) {
picker_day.setMaxValue(DateTimeUtils.getMaxDaysofMonth(year, numberPicker.getValue() ));
}
});
picker_day.setFormatter(new timeFormatter());
picker_day.setMaxValue(DateTimeUtils.getMaxDaysofMonth(year,month));
picker_day.setMinValue(1);
picker_day.setValue(day);
picker_hour.setFormatter(new timeFormatter());
picker_hour.setMaxValue(23);
picker_hour.setMinValue(0);
picker_hour.setValue(hour);
picker_minute.setFormatter(new timeFormatter());
picker_minute.setMaxValue(59);
picker_minute.setMinValue(0);
picker_minute.setValue(minute);
ImageView img_submit = (ImageView) layout.findViewById(R.id.submit);
img_submit.setOnClickListener(onClickListener);
并排放5个NumberPicker,伪装成DatePicker与TimePicker。 然后用上面提到的方法缩小到能完美显示。 但是,还有一个问题,字体大小!!! OK,NumberPicker是变小了,但是里面的数字显示不全了能叫完美显示么?怎么办?Read The Fucking Source Code! NumberPicker的源码中有一个对象叫mSelectorWheelPaint,滑轮上的字都是它画的,这还不够,点击NumberPicker中间是会出现一个EditText的,不能忘了它
public static void setChildTextSize(ViewGroup root,float size) {
Field field;
try {
field = root.getClass().getDeclaredField("mSelectorWheelPaint");
field.setAccessible(true);
Paint paint = (Paint) field.get(root);
paint.setTextSize(size);
field = root.getClass().getDeclaredField("mInputText");
field.setAccessible(true);
EditText editText = (EditText) field.get(root);
editText.setTextSize(ScreenUtils.px2dp(MilkingApplication.getInstance().getApplicationContext(),size));
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
通过Java反射机制,拿到mSelectorWheelPaint,mInputText这两个对象,尽情的setTextSize吧。
一点小技巧,比较话唠,写了很长,有时候对原生控件做一点小改动,就能完美得完成我们的需求,并不需要去自定义View写一大堆代码。 完整的项目我会找时间整理后上传到Github,今天就算了,带了笔记本,没带电源适配器…
本文出自Yang,转载时请注明出处及相应链接。