自定义时间选择器

来源:互联网 发布:九局下半 知乎 编辑:程序博客网 时间:2024/06/05 06:24

前言

最近写了一个关于快餐送餐时间的AlertDialog程序,现在想分享给大家,如有什么不合理的地方望提出。

效果图

效果图

使用方法

//只需要new出来然后show()就可以使用了        new SendTimePickerDialog(this, new SendTimePickerDialog.OnReturnDateListener() {            @Override            public void onReturnDate(int date, int hour, int minute) {                //选择后返回的数据                String dateStr = SendTimePicker.dateToString(date); //把时间转化为 今天 或者 明天                Log.d("MainActivity",dateStr + " "+hour+" "+ minute);            }        }).show();

实现原理

实现的原理是模仿DatePickerDialog继承AlertDialog如下图

DatePickerDialog

实现之前我们必须先自定义一个主布局,然后把主布局加到AlertDialog中,就如DatePickerDialog的实现一样,我先把整体软件的代码结构贴出来

这里写图片描述

所以我打算先讲怎么实现时间选择的主布局,然后再讲怎么把主布局加到AlertDialog中

1、自定义时间选择的布局

我的方法是使用3个NumberPicker组成一个选择器
xml代码如下

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center">    <NumberPicker        android:id="@+id/datePicker"        android:layout_width="wrap_content"        android:layout_height="wrap_content"/>    <NumberPicker        android:id="@+id/hourPicker"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="15dp"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:gravity="center"        android:text=":"        android:textSize="30sp" />    <NumberPicker        android:id="@+id/minutePicker"        android:layout_width="wrap_content"        android:layout_height="wrap_content"/></LinearLayout>
效果如下,样式不一样是因为设置的安卓版本,不过最终都能实现选择时间的需求。

这里写图片描述

然后我们现在就可以写SendTimePicker类了,这个类只是提供对外读取时间的接口和显示布局,代码如下
package com.sven.my.test.custom.view;import android.content.Context;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.FrameLayout;import android.widget.NumberPicker;import com.sven.my.test.R;import java.util.Calendar;public class SendTimePicker extends FrameLayout {    /**     * 时间标志     */    public static final int TODAY_FLAG = 0x0;    public static final int TOMORROW_FLAG = 0x1;    private static final String TODAY = "今天";    private static final String TOMORROW = "明天";    /**     * 布局里的三个数字选择器     */    private NumberPicker mDatePicker;    private NumberPicker mHourPicker;    private NumberPicker mMinutePicker;    private int mDate;    private int mHour;    private int mMinute;    Calendar mCalendar;    private String[] mDates = new String[]{            TODAY            ,TOMORROW    };    /**     * 选择改变时的回调接口     */    private OnSelectChangedListener mOnSelectChangedListener;    public SendTimePicker(Context context) {        this(context,null);    }    public SendTimePicker(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public SendTimePicker(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        //初始化时间        mCalendar = Calendar.getInstance(); //获取系统时间        mHour = mCalendar.get(Calendar.HOUR_OF_DAY);        mMinute = mCalendar.get(Calendar.MINUTE);        mDate = TODAY_FLAG; //默认为今天        //初始化布局        View mainView = LayoutInflater.from(context).inflate(R.layout.send_time_picker,null);        mDatePicker = (NumberPicker) mainView.findViewById(R.id.datePicker);        mHourPicker = (NumberPicker) mainView.findViewById(R.id.hourPicker);        mMinutePicker = (NumberPicker) mainView.findViewById(R.id.minutePicker);        //设置三个选择器的数值        mDatePicker.setDisplayedValues(mDates);        loadPicker(mDatePicker, 0, mDates.length - 1, 0);        loadPicker(mHourPicker, mHour,23, mHour);        loadPicker(mMinutePicker, mMinute,59, mMinute);        //添加到布局中        addView(mainView);        //设置监听        initListener();    }    /**     * 加载选择框     */    private void loadPicker(NumberPicker numberPicker, int minValue, int maxValue, int value){        numberPicker.setMinValue(minValue);        numberPicker.setMaxValue(maxValue);        numberPicker.setValue(value);    }    /**     * 设置监听     */    private void initListener() {        mDatePicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {            @Override            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {              //为了让用户不能选择今天之前的时间                mDate = newVal;                int currentHour = mCalendar.get(Calendar.HOUR_OF_DAY);                int currentMinute = mCalendar.get(Calendar.MINUTE);                if(mHour < currentHour) mHour = currentHour;                if(mMinute < currentMinute) mMinute = currentMinute;                if(mDate == TODAY_FLAG){                    loadPicker(mHourPicker,currentHour,23,mHour);                    loadPicker(mMinutePicker,currentMinute,59,mMinute);                }else if(mDate == TOMORROW_FLAG){                    loadPicker(mHourPicker,0,23,mHour);                    loadPicker(mMinutePicker,0,59,mMinute);                }                callOnSelectListener();            }        });        mHourPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {            @Override            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {                mHour = newVal;                callOnSelectListener();            }        });        mMinutePicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {            @Override            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {                mMinute = newVal;                callOnSelectListener();            }        });    }    /**     * 把时间转化为可视的     */    public static String dateToString(int date){        return date==TODAY_FLAG ? TODAY : TOMORROW;    }    /**     * 调用改变选择的回调接口     */    private void callOnSelectListener(){        if(mOnSelectChangedListener != null){            mOnSelectChangedListener.onSelectChanged(mDate, mHour, mMinute);        }    }    public void setOnSelectChangedListener(OnSelectChangedListener mOnSelectChangedListener) {        this.mOnSelectChangedListener = mOnSelectChangedListener;    }    /**     * 选择发生改变的回调接口     */    public interface OnSelectChangedListener{        void onSelectChanged(int newDate, int newHour, int newMinute);    }    public void setDate(int date) {        this.mDate = date;        mDatePicker.setValue(date);    }    public void setHour(int hour) {        this.mHour = hour;        mHourPicker.setValue(hour);    }    public void setMinute(int minute) {        this.mMinute = minute;        mMinutePicker.setValue(minute);    }    public int getDate() {        return mDate;    }    public int getHour() {        return mHour;    }    public int getMinute() {        return mMinute;    }}
写完这个布局大家可以先试着用这个自定义控件运行下
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <com.sven.my.test.custom.view.SendTimePicker        android:layout_width="wrap_content"        android:layout_height="wrap_content"></com.sven.my.test.custom.view.SendTimePicker></LinearLayout>

这里写图片描述

2、把自定义布局整合到AlertDialog中

我们只需要继承AlertDialog然后把刚刚那个自定义布局添加到AlertDialog中就可以了,如下图,剩下的显示之类的功能AlertDialog内部已经帮我们实现了,所以不需要我们操心
setView(mSendTimePicker); //把选择器添加到提示框
下面贴上代码
package com.sven.my.test.custom.view;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;public class SendTimePickerDialog extends AlertDialog {    /**     * 回调接口     */    private OnReturnDateListener mOnReturnDateListener;    /**     * 选择器主布局     */    private SendTimePicker mSendTimePicker;    public SendTimePickerDialog(Context context){        this(context,null);    }    public SendTimePickerDialog(Context context, final OnReturnDateListener onReturnDateListener) {        super(context);        //设置回调监听        mOnReturnDateListener = onReturnDateListener;        //初始化布局        mSendTimePicker = new SendTimePicker(getContext());        setView(mSendTimePicker); //把选择器添加到提示框        //设置标题        setTimeTitle(); //设置标题        //设置监听 数值选择改变监听        mSendTimePicker.setOnSelectChangedListener(new SendTimePicker.OnSelectChangedListener() {            @Override            public void onSelectChanged(int newDate, int newHour, int newMinute) {                setTimeTitle(SendTimePicker.dateToString(newDate)                            , newHour, newMinute); //设置标题            }        });        //点击确定的监听        setButton(AlertDialog.BUTTON_POSITIVE, "确定", new OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                if(onReturnDateListener != null){                    onReturnDateListener.onReturnDate(mSendTimePicker.getDate()                            ,mSendTimePicker.getHour(),mSendTimePicker.getMinute());                }            }        });    }    /**     * 设置标题     */    private void setTimeTitle(){        //获取时间        int date = mSendTimePicker.getDate();        int hour = mSendTimePicker.getHour();        int minute = mSendTimePicker.getMinute();        this.setTimeTitle(SendTimePicker.dateToString(date),hour,minute);    }    /**     * 设置标题     */    private void setTimeTitle(String date, int hour, int minute){        String titleStr = String.format("%s    %d:%d",date,hour,minute);        setTitle(titleStr);    }    public void setOnReturnDateListener(OnReturnDateListener mOnReturnDateListener) {        this.mOnReturnDateListener = mOnReturnDateListener;    }    /**     * 返回数据的接口     */    public interface OnReturnDateListener{        void onReturnDate(int date, int hour, int minute);    }}
然后我们就可以使用了,就跟前面写的一样
//只需要new出来然后show()就可以使用了        new SendTimePickerDialog(this, new SendTimePickerDialog.OnReturnDateListener() {            @Override            public void onReturnDate(int date, int hour, int minute) {                //选择后返回的数据                String dateStr = SendTimePicker.dateToString(date); //把时间转化为 今天 或者 明天                Log.d("MainActivity",dateStr + " "+hour+" "+ minute);            }        }).show();

总结

就此整个设计结束,思路是先设计一个时间选择器,然后再创建一个类继承AlertDialog,最后就是把自己设计的时间选择器设置进继承AlertDialog的类中。下面是完整代码大家可以下载

下载地址

0 0