概述
Android提供了一个选择日期的控件——DatePicker,但是这个控件本身存在一些缺陷:宽度不可控,年月日中间的间距过宽,分隔线的颜色不可以定义等等,于是网上就有了很多开源的日期选择控件,它们之中有很多写得非常棒。本文将提供一种方法,更改原生控件DatePicker中年月日的间距,以及分隔线的颜色。
首先我们还是先看一下原生控件,如果在xml布局文件中摆放一个DatePicker,它的宽度最好设为wrap_content而非固定值。如果我将它的宽度写死,并且小于它本来的宽度时,控件将会被截断,而不是缩短年月日之间的间距,效果如下图。
如果要修改控件的属性,我们最好先看看源码,了解一下这个控件是如何实现的。进入DatePicker这个类,可以看到下面一段代码
mSpinners = (LinearLayout) mDelegator.findViewById(R.id.pickers);
// calendar view day-picker
mCalendarView = (CalendarView) mDelegator.findViewById(R.id.calendar_view);
mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
setDate(year, month, monthDay);
updateSpinners();
notifyDateChanged();
}
});
// day
mDaySpinner = (NumberPicker) mDelegator.findViewById(R.id.day);
mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
mDaySpinner.setOnLongPressUpdateInterval(100);
mDaySpinner.setOnValueChangedListener(onChangeListener);
mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
// month
mMonthSpinner = (NumberPicker) mDelegator.findViewById(R.id.month);
mMonthSpinner.setMinValue(0);
mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
mMonthSpinner.setDisplayedValues(mShortMonths);
mMonthSpinner.setOnLongPressUpdateInterval(200);
mMonthSpinner.setOnValueChangedListener(onChangeListener);
mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.numberpicker_input);
// year
mYearSpinner = (NumberPicker) mDelegator.findViewById(R.id.year);
mYearSpinner.setOnLongPressUpdateInterval(100);
mYearSpinner.setOnValueChangedListener(onChangeListener);
mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.numberpicker_input);
从上面这段代码可以分析出,DatePicker中选择年月日的部分其实是三个NumberPicker,名字分别为mYearSpinner,mMonthSpinner和mDaySpinner,它们三个平铺在一个LinearLayout中,这个线性布局的名字叫做mSpinners。从这段代码向上翻,还能找到一个布局文件R.layout.date_picker_legacy,追踪进去,可以看到date_picker_legacy.xml,这个就是DatePicker的布局。可以看到,基本符合刚才的分析,这里把布局文件的代码附上。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:gravity="center">
<LinearLayout android:id="@+id/pickers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center">
<!-- Month -->
<NumberPicker
android:id="@+id/month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
<!-- Day -->
<NumberPicker
android:id="@+id/day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
<!-- Year -->
<NumberPicker
android:id="@+id/year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:focusable="true"
android:focusableInTouchMode="true"
/>
</LinearLayout>
<!-- calendar view -->
<CalendarView
android:id="@+id/calendar_view"
android:layout_width="245dip"
android:layout_height="280dip"
android:layout_marginStart="44dip"
android:layout_weight="1"
android:focusable="true"
android:focusableInTouchMode="true"
android:visibility="gone"
/>
</LinearLayout>
在布局文件里我们可以看到,NumberPicker中的间距时通过marginStart和marginEnd定义的,因此我们修改这两个值就可以更改间距,不过要注意的是,marginStart和marginEnd是在API17中登场的,对于之前的版本,需要加以判断,否则会出现NoSuchMethodError。
接下来再看分隔线颜色,由于分隔线属于NumberPicker中的一部分,因此我们应当到NumberPicker的源码中去寻找。在NumberPicker.java中有一个Drawable类型的私有成员变量叫做mSelectionDivider,这个变量对应的就是分隔线,并且在NumberPicker的onDraw()方法中,将这个Drawable画到了canvas上面。将源码中的这一部分搬运过来。
// draw the selection dividers
if (showSelectorWheel && mSelectionDivider != null) {
// draw the top divider
int topOfTopDivider = mTopSelectionDividerTop;
int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight;
mSelectionDivider.setBounds(0, topOfTopDivider, mRight, bottomOfTopDivider);
mSelectionDivider.draw(canvas);
// draw the bottom divider
int bottomOfBottomDivider = mBottomSelectionDividerBottom;
int topOfBottomDivider = bottomOfBottomDivider - mSelectionDividerHeight;
mSelectionDivider.setBounds(0, topOfBottomDivider, mRight, bottomOfBottomDivider);
mSelectionDivider.draw(canvas);
}
因此要修改分隔线颜色,我们可以采取这样的思路:用反射拿到私有变量mSelectionDivider,并且在NumberPicker绘制之前,用一个colorDrawable替换它。
为了方便以后使用,我们这里创建一个DatePicker的子类,并在它的构造中找到用于选择年月日的三个NumberPicker,将它们保存到一个ArrayList中,提供外部方法以设置间隔和颜色。我这里为了设置日期方便还提供了日期的setter和getter方法,代码如下。
源码下载链接
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.DatePicker;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
* Créé par liusiqian 15/11/27.
*/
public class CustomDatePicker extends DatePicker
{
private List<NumberPicker> mPickers;
public CustomDatePicker(Context context)
{
super(context);
findNumberPicker();
}
public CustomDatePicker(Context context, AttributeSet attrs)
{
super(context, attrs);
findNumberPicker();
}
public CustomDatePicker(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
findNumberPicker();
}
/**
* 得到控件里面的numberpicker组件
*/
private void findNumberPicker()
{
mPickers = new ArrayList<NumberPicker>();
LinearLayout llFirst = (LinearLayout) getChildAt(0);
LinearLayout mSpinners = (LinearLayout) llFirst.getChildAt(0);
for (int i = 0; i < mSpinners.getChildCount(); i++)
{
NumberPicker picker = (NumberPicker) mSpinners.getChildAt(i);
mPickers.add(i, picker);
}
}
/**
* 设置时间
* @param strDate yyyy-mm-dd
*/
public void setDate(String strDate)
{
int day, month, year;
if (!TextUtils.isEmpty(strDate))
{
String[] dateValues = strDate.split("-");
if (dateValues.length == 3)
{
year = Integer.parseInt(dateValues[0]);
month = Integer.parseInt(dateValues[1]) - 1;
day = Integer.parseInt(dateValues[2]);
updateDate(year, month, day);
return;
}
}
//error
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
day = calendar.get(Calendar.DAY_OF_MONTH);
month = calendar.get(Calendar.MONTH);
year = calendar.get(Calendar.YEAR);
updateDate(year, month, day);
}
/**
* 获得时间
* @return yyyy-mm-dd
*/
public String getDate()
{
StringBuilder sbDate = new StringBuilder();
sbDate.append(format2Digits(getYear())).append("-")
.append(format2Digits(getMonth()+1)).append("-")
.append(format2Digits(getDayOfMonth()));
return sbDate.toString();
}
private String format2Digits(int value)
{
return String.format("%02d",value);
}
/**
* 设置picker间隔
*
* @param margin
*/
public void setPickerMargin(int margin)
{
for (NumberPicker picker : mPickers)
{
LinearLayout.LayoutParams lps = (LinearLayout.LayoutParams) picker.getLayoutParams();
lps.setMargins(margin, 0, margin, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
{
lps.setMarginStart(margin);
lps.setMarginEnd(margin);
}
picker.setLayoutParams(lps);
}
}
/**
* 设置时间选择器的分割线颜色
*/
public void setDividerColor(int color)
{
for (int i = 0; i < mPickers.size(); i++)
{
NumberPicker picker = mPickers.get(i);
try
{
Field pf = NumberPicker.class.getDeclaredField("mSelectionDivider");
pf.setAccessible(true);
pf.set(picker, new ColorDrawable(color));
}
catch (NoSuchFieldException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
}
使用时,直接调用提供给外部的setDividerColor和setPickerMargin两个方法即可。
CustomDatePicker picker = (CustomDatePicker) findViewById(R.id.date_picker);
picker.setDividerColor(0xffcccccc);
picker.setPickerMargin(1);
设置之后效果如下图所示。
最后
以上就是时尚面包为你收集整理的更改DatePicker中年月日的间隔和分隔线颜色的全部内容,希望文章能够帮你解决更改DatePicker中年月日的间隔和分隔线颜色所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复