说到时间选择器,其实就是用到NumberPicker控件。先上效果图,分别是年、月、日、时、分、秒。
1.首先看看布局代码,比较简单就不说了,直接上代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="lovelder.lovcreate.com.dateapplication.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<NumberPicker
android:id="@+id/np_year"
android:layout_width="0dp"
android:layout_weight="1.3"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_height="wrap_content">
</NumberPicker>
<NumberPicker
android:id="@+id/np_month"
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_height="wrap_content">
</NumberPicker>
<NumberPicker
android:id="@+id/np_day"
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_height="wrap_content">
</NumberPicker>
<NumberPicker
android:id="@+id/np_hour"
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_height="wrap_content">
</NumberPicker>
<NumberPicker
android:id="@+id/np_minute"
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_height="wrap_content">
</NumberPicker>
</LinearLayout>
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點擊"
/>
</LinearLayout>
2.然后点击“点击按钮”,加载MyCalendarDialog,传入对话框的宽、高、布局、属性。
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final MyCalendarDialog dialog = new MyCalendarDialog(MainActivity.this,360,230,R.layout.activity_calendar,R.style.DialogTheme);
dialog.setSureClick(new MyCalendarDialog.MyCalendar() {
@Override
public void setCalendar(int year, int month, int day, int hour, int minute) {
dialog.dismiss();
Toast.makeText(MainActivity.this, year + "年" + month + "月"+ day+ "日" + hour+ "时" + minute + "分", Toast.LENGTH_SHORT).show();
}
});
dialog.show();
}
});
3.分析一下自定义的MyCalendarDialog,设置对话框弹出的宽和高、属性、布局等。
public MyCalendarDialog(Context context, int width, int height, int layout,
int style) {
super(context, style);
// 设置内容
view = LayoutInflater.from(context).inflate(layout,null);
setContentView(view);
this.context = context;
// 设置窗口属性
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
// 设置宽度、高度、密度、对齐方式
float density = getDensity(context);
params.width = (int) (width * density);
params.height = (int) (height * density);
params.gravity = Gravity.CENTER;
window.setAttributes(params);
initData();
initView();
}
4.获取当前年、月、日、时、分的值。
private void initData() {
Calendar calendar = Calendar.getInstance();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH) + 1;
day = calendar.get(Calendar.DAY_OF_MONTH);
hour = calendar.get(Calendar.HOUR_OF_DAY);
minute = calendar.get(Calendar.MINUTE);
}
5.设置年的显示格式、最小值、最大值、滑动监听等
/**
* 年份
*/
MyFormatter formatter = new MyFormatter();
np_year.setFormatter(formatter); //显示格式
np_year.setMinValue(year); //最小值
np_year.setMaxValue(5000); //最大值
np_year.setWrapSelectorWheel(false);//当待显示的条目数大于3时,设置是否可以循环滚动,注意该行应该放在上面三行的下面
np_year.setOnValueChangedListener(listener);//当值发生改变的监听
changeValueByOne(np_year, true);//没有这个方法,值增加或者减少的时候会出现异常。
6.但是NumberPicker类的方法是私有,所有无法直接调用。只能通过反射拿到此方法。
/**
* Changes the current value by one which is increment or
* decrement based on the passes argument.
* decrement the current value.
*
* @param increment True to increment, false to decrement.
*/
private void changeValueByOne(boolean increment) {
if (mHasSelectorWheel) {
mInputText.setVisibility(View.INVISIBLE);
if (!moveToFinalScrollerPosition(mFlingScroller)) {
moveToFinalScrollerPosition(mAdjustScroller);
}
mPreviousScrollerY = 0;
if (increment) {
mFlingScroller.startScroll(0, 0, 0, -mSelectorElementHeight, SNAP_SCROLL_DURATION);
} else {
mFlingScroller.startScroll(0, 0, 0, mSelectorElementHeight, SNAP_SCROLL_DURATION);
}
invalidate();
} else {
if (increment) {
setValueInternal(mValue + 1, true);
} else {
setValueInternal(mValue - 1, true);
}
}
}
7.放射拿到changeValueByOne方法,并执行。
/**
* using reflection to change the value because
* changeValueByOne is a private function and setValue
* doesn't call the onValueChange listener.
*
* @param higherPicker the higher picker
* @param increment the increment
*/
private void changeValueByOne(final NumberPicker higherPicker, final boolean increment) {
Method method;
try {
// refelction call for
// higherPicker.changeValueByOne(true);
method = higherPicker.getClass().getDeclaredMethod("changeValueByOne", boolean.class);
method.setAccessible(true);
method.invoke(higherPicker, increment);
} catch (final NoSuchMethodException e) {
e.printStackTrace();
} catch (final IllegalArgumentException e) {
e.printStackTrace();
} catch (final IllegalAccessException e) {
e.printStackTrace();
} catch (final InvocationTargetException e) {
e.printStackTrace();
}
}