使用该控件时需注意他的两个listener和一个formatter:一个listener用于监听当前value的变化;一个listener用于监听该控件的scroll状态;formatter用于格式化显示该控件中的value。下面逐一介绍这几个接口:
1、NumberPicker.OnValueChangeListener :其函数public void onValueChange(NumberPicker picker, int oldVal, int newVal) ;oldVal前一个选中的值,newValue当前选中的值。
2、NumberPicker.OnScrollListener:其内部有三种scroll状态SCROLL_STATE_FLING 、 SCROLL_STATE_IDLE 、 SCROLL_STATE_TOUCH_SCROLL。
SCROLL_STATE_TOUCH_SCROLL:用户按下去然后滑动。
SCROLL_STATE_FLING: 相当于是SCROLL_STATE_TOUCH_SCROLL的后续滑动操作。
SCROLL_STATE_IDLE: NumberPicker不在滚动。
3、NumberPicker.Formatter: 格式化显示数字,例如0—23格式化为00 — 23 。具体的格式在format函数中规定,如下所示:
public String format(int value) { String Str = String.valueOf(value); if (value < 10) { Str = "0" + Str; } return Str; }value值在0—23之间,小于10的数在前面加上“0”。
介绍完NumberPicker后,就要实现我们今天的功能,首先先看效果图,如下所示:
是不是非常漂亮那,这样以后我们的项目中需要这种效果,就直接就可以拿来用了。要实现这种效果当然要先看我们的布局了,其实布局里面就三个NumberPicker如下所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:orientation="vertical" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal" android:paddingLeft="3.0dip" > <NumberPicker android:id="@+id/np_date" android:layout_width="120.0dip" android:layout_height="wrap_content" android:button="@null" /> <NumberPicker android:id="@+id/np_hour" android:layout_width="50.0dip" android:layout_height="wrap_content" android:layout_marginLeft="5.0dip" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text=":" android:textSize="20.0sp" /> <NumberPicker android:id="@+id/np_minute" android:layout_width="50.0dip" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout>就是这三个NumberPicker布局出我们刚才的效果,布局完成我们就要找到这些控件,给他们加上监听,来实现一些功能,这里面是自定义FrameLayout在直接填充布局做的。让我们来看看,如下所示:
package com.zqy.datetimepicker.datedialog; import java.util.Calendar; import com.zqy.datetimepicker.R; import android.content.Context; import android.text.format.DateFormat; import android.widget.FrameLayout; import android.widget.NumberPicker; import android.widget.NumberPicker.OnValueChangeListener; public class DateTimePicker extends FrameLayout { private final NumberPicker mDateSpinner; private final NumberPicker mHourSpinner; private final NumberPicker mMinuteSpinner; private Calendar mDate; private int mHour, mMinute; private String[] mDateDisplayValues = new String[7]; private OnDateTimeChangedListener mOnDateTimeChangedListener; public DateTimePicker(Context context) { super(context); /* *獲取系統時間 */ mDate = Calendar.getInstance(); mHour = mDate.get(Calendar.HOUR_OF_DAY); mMinute = mDate.get(Calendar.MINUTE); /** * 加载布局 */ inflate(context, R.layout.datedialog, this); /** * 初始化控件 */ mDateSpinner = (NumberPicker) this.findViewById(R.id.np_date); mDateSpinner.setMinValue(0); mDateSpinner.setMaxValue(6); updateDateControl(); mDateSpinner.setOnValueChangedListener(mOnDateChangedListener); mHourSpinner = (NumberPicker) this.findViewById(R.id.np_hour); mHourSpinner.setMaxValue(23); mHourSpinner.setMinValue(0); mHourSpinner.setValue(mHour); mHourSpinner.setOnValueChangedListener(mOnHourChangedListener); mMinuteSpinner = (NumberPicker) this.findViewById(R.id.np_minute); mMinuteSpinner.setMaxValue(59); mMinuteSpinner.setMinValue(0); mMinuteSpinner.setValue(mMinute); mMinuteSpinner.setOnValueChangedListener(mOnMinuteChangedListener); } /** * * 控件监听器 */ private NumberPicker.OnValueChangeListener mOnDateChangedListener = new OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { mDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal); /** * 更新日期 */ updateDateControl(); /** * 给接口传值 */ onDateTimeChanged(); } }; private NumberPicker.OnValueChangeListener mOnHourChangedListener = new OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { mHour = mHourSpinner.getValue(); onDateTimeChanged(); } }; private NumberPicker.OnValueChangeListener mOnMinuteChangedListener = new OnValueChangeListener() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { mMinute = mMinuteSpinner.getValue(); onDateTimeChanged(); } }; private void updateDateControl() { /** * 星期几算法 */ Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(mDate.getTimeInMillis()); cal.add(Calendar.DAY_OF_YEAR, -7 / 2 - 1); mDateSpinner.setDisplayedValues(null); for (int i = 0; i < 7; ++i) { cal.add(Calendar.DAY_OF_YEAR, 1); mDateDisplayValues[i] = (String) DateFormat.format("MM.dd EEEE", cal); } mDateSpinner.setDisplayedValues(mDateDisplayValues); mDateSpinner.setValue(7 / 2); mDateSpinner.invalidate(); } /* *接口回调 参数是当前的View 年月日小时分钟 */ public interface OnDateTimeChangedListener { void onDateTimeChanged(DateTimePicker view, int year, int month, int day, int hour, int minute); } /* *对外的公开方法 */ public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { mOnDateTimeChangedListener = callback; } private void onDateTimeChanged() { if (mOnDateTimeChangedListener != null) { mOnDateTimeChangedListener.onDateTimeChanged(this,mDate.get(Calendar.YEAR), mDate.get(Calendar.MONTH), mDate.get(Calendar.DAY_OF_MONTH), mHour, mMinute); } } }这段代码就是找到这三个控件,分别给他们setMinValue(),setMaxValue(),也就是最大值和最小值,设置完成后,我们给他们三个分别加上监听setOnValueChangedListener下面有三个监听方法,在mOnDateChangedListener这个方法了多了一个updateDateControl()方法,这个updateDateControl()方法里面主要是月份和星期几的关系算法,
写完这些,值也拿到了,但是我们需要把值传出去,下面我们又定义了一个接口来实现回调.接下来让我们在来看看对话框这个类,如下所示:
package com.zqy.datetimepicker.datedialog; import java.util.Calendar; import com.zqy.datetimepicker.datedialog.DateTimePicker.OnDateTimeChangedListener; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.text.format.DateUtils; public class DateTimePickerDialog extends AlertDialog implements OnClickListener { private DateTimePicker mDateTimePicker; private Calendar mDate = Calendar.getInstance(); private OnDateTimeSetListener mOnDateTimeSetListener; @SuppressWarnings("deprecation") public DateTimePickerDialog(Context context, long date) { super(context); mDateTimePicker = new DateTimePicker(context); setView(mDateTimePicker); /* *实现接口,实现里面的方法 */ mDateTimePicker .setOnDateTimeChangedListener(new OnDateTimeChangedListener() { @Override public void onDateTimeChanged(DateTimePicker view, int year, int month, int day, int hour, int minute) { mDate.set(Calendar.YEAR, year); mDate.set(Calendar.MONTH, month); mDate.set(Calendar.DAY_OF_MONTH, day); mDate.set(Calendar.HOUR_OF_DAY, hour); mDate.set(Calendar.MINUTE, minute); mDate.set(Calendar.SECOND, 0); /** * 更新日期 */ updateTitle(mDate.getTimeInMillis()); } }); setButton("设置", this); setButton2("取消", (OnClickListener) null); mDate.setTimeInMillis(date); updateTitle(mDate.getTimeInMillis()); } /* *接口回調 *控件 秒数 */ public interface OnDateTimeSetListener { void OnDateTimeSet(AlertDialog dialog, long date); } /** * 更新对话框日期 * @param date */ private void updateTitle(long date) { int flag = DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_TIME; setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); } /* * 对外公开方法让Activity实现 */ public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { mOnDateTimeSetListener = callBack; } public void onClick(DialogInterface arg0, int arg1) { if (mOnDateTimeSetListener != null) { mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); } } }
我们一行一行看,首先我们是继承AlertDialog,在下面我们new DateTimePicker,这个就是刚才写的类,我们这个类的对象实现我们刚才写的接口,把里面的值取到,虽然取到了,但是我们也不是在这里显示,所以我们还需要定义接口,让DateTimePickerDialog的对象去实现,下面就是我们的写的接口,我们写了那么多,只为MainActivity里面的几行代码,让我们看看,如下所示:
package com.zqy.datetimepicker.activity; import java.text.SimpleDateFormat; import com.zqy.datetimepicker.R; import com.zqy.datetimepicker.datedialog.DateTimePickerDialog; import com.zqy.datetimepicker.datedialog.DateTimePickerDialog.OnDateTimeSetListener; import android.app.Activity; import android.app.AlertDialog; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { private Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) this.findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showDialog(); } }); } public void showDialog() { DateTimePickerDialog dialog = new DateTimePickerDialog(this, System.currentTimeMillis()); /** * 实现接口 */ dialog.setOnDateTimeSetListener(new OnDateTimeSetListener() { public void OnDateTimeSet(AlertDialog dialog, long date) { Toast.makeText(MainActivity.this, "您输入的日期是:" + getStringDate(date), Toast.LENGTH_LONG) .show(); } }); dialog.show(); } /** * 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss * */ public static String getStringDate(Long date) { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateString = formatter.format(date); return dateString; } }首先我们还是new DateTimePickerDialog这个类,我们把系统时间传过去,这样时间对话框显示的就是系统时间了,我们用这个类的对象去实现我们刚才写的接口,实现里面的方法,我们又定义了一个 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss的方法,这样我用一个Toast把接口里面的值弹出来。OK,这样我们就实现完成了,有什么不明白的可以在下面留言。