更新:

通过为TimePicker控件增加属性,使其具有是否以当前时间为上限的属性设置。


1、在attrs.xml文件中增加:

<declare-styleable name="TimePicker">
    <attr name="Timelimited" format="boolean"/>
   
</declare-styleable>



2、在需要使用TimePicker控件的xml中设置:

xmlns:timePicker="http://schemas.android.com/apk/res-auto"

并在控件处使用:

<com.xxx.pickerview.TimePicker
    android:id="@+id/datepicker_start"
    timePicker:Timelimited="true"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    />



这样我们就能在TimePicker的构造函数中获取该属性并根据其值做相应操作:

比如下面的  flag  就是我们上面设置的属性值;

public TimePicker(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.TimePicker);
    boolean flag = a.getBoolean(R.styleable.TimePicker_Timelimited,false);
    LayoutInflater.from(context).inflate(R.layout.pickerview_time, this,true);//这是对上面两句的包装。
    final View timepickerview = findViewById(R.id.timepicker);
    wheelTime = new WheelTime(timepickerview, TimePickerType.Type.YEAR_MONTH_DAY);
    if (!flag){
        int endYear=a.getInt(R.styleable.TimePicker_endYear,2900);

        wheelTime.setEndYear(endYear);
    }


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

最近手上的项目要求弄一个包含两个日期选择控件的UI界面(即开始时间和结束时间)。

一、

一开始就想到使用自带的DatePicker控件。但是发现其UI很难调整到项目想要的效果。尤其是其与项目theme的关系,在xml中设置style也不好使。从Popwindow到AlertDialog都试过了,只有含单个DatePicker的DateAlertDialog还比较赏心悦目,却不满足项目需要。

于是决定用自定义DatePicker来实现。

通过一番波折,自己实现了大部分功能,但对日期的年月日的配合调整的不是很好。

无意间在网上发现了Pickerview这个开源项目。(地址:https://github.com/saiwu-bigkoo/Android-PickerView#demo-图片)其中的TimePickerView比较符合我的需求,就借来稍加改动,使用了起来。


二、

由于TimePickerView的不是传统意义上的控件,其使用方式比较固定,不方便。我稍加改动,创建了TimePicker控件。

该控件的功能是:提供年月日用于选择,可选范围是:1990年1月1日到当前时间。 通过getTime()可以获取用户选择的时间。

代码:

1、Timepicker.java

public class TimePicker extends LinearLayout {

    WheelTime wheelTime;

    private OnTimeSelectListener timeSelectListener;

    public TimePicker(Context context) {
        super(context);
    }

    public TimePicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.pickerview_time, this,true);//这是对上面两句的包装。
        final View timepickerview = findViewById(R.id.timepicker);
        wheelTime = new WheelTime(timepickerview, TimePickerType.Type.YEAR_MONTH_DAY);
        //默认选中当前时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hours = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        wheelTime.setPicker(year, month, day, hours, minute);


        this.setClickable(true);
        this.setFocusable(true);
    }
    public Date getTime(){
       String time= wheelTime.getTime();
        Log.d("TimePicker","--------------getTime  "+time);
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
        Date d=new Date();
        try {
           d=dateFormat.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return d;
    }



    /**
     * 设置可以选择的时间范围
     * 要在setTime之前调用才有效果
     * @param startYear 开始年份
     * @param endYear 结束年份
     */
    public void setRange(int startYear, int endYear) {
        wheelTime.setStartYear(startYear);
        wheelTime.setEndYear(endYear);
    }

    /**
     * 设置选中时间
     * @param date 时间
     */
    public void setTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date == null)
            calendar.setTimeInMillis(System.currentTimeMillis());
        else
            calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hours = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        wheelTime.setPicker(year, month, day, hours, minute);
    }

//    /**
//     * 指定选中的时间,显示选择器
//     *
//     * @param date
//     */
//    public void show(Date date) {
//        Calendar calendar = Calendar.getInstance();
//        if (date == null)
//            calendar.setTimeInMillis(System.currentTimeMillis());
//        else
//            calendar.setTime(date);
//        int year = calendar.get(Calendar.YEAR);
//        int month = calendar.get(Calendar.MONTH);
//        int day = calendar.get(Calendar.DAY_OF_MONTH);
//        int hours = calendar.get(Calendar.HOUR_OF_DAY);
//        int minute = calendar.get(Calendar.MINUTE);
//        wheelTime.setPicker(year, month, day, hours, minute);
//        show();
//    }

    /**
     * 设置是否循环滚动
     * @param cyclic 是否循环
     */
    public void setCyclic(boolean cyclic) {
        wheelTime.setCyclic(cyclic);
    }

}



2、对应布局文件pickerview_time.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/timepicker"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:orientation="horizontal">

        <com.koala.shop.mobile.teacher.widget.pickerview.lib.WheelView
            android:id="@+id/year"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <com.koala.shop.mobile.teacher.widget.pickerview.lib.WheelView
            android:id="@+id/month"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1.1" />

        <com.koala.shop.mobile.teacher.widget.pickerview.lib.WheelView
            android:id="@+id/day"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1.1" />

        <com.koala.shop.mobile.teacher.widget.pickerview.lib.WheelView
            android:id="@+id/hour"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1.1" />

        <com.koala.shop.mobile.teacher.widget.pickerview.lib.WheelView
            android:id="@+id/min"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1.1" />
    </LinearLayout>


</LinearLayout>



3、Wheeltime.java

public class WheelTime {
    public static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private View view;
    private WheelView wv_year;
    private WheelView wv_month;
    private WheelView wv_day;
    private WheelView wv_hours;
    private WheelView wv_mins;

    private int year_now,month_now,day_now;


    private TimePickerType.Type type;
    public static final int DEFULT_START_YEAR = 1990;
    public static final int DEFULT_END_YEAR = 2100;
    private int startYear = DEFULT_START_YEAR;
    private int endYear = DEFULT_END_YEAR;


    public WheelTime(View view) {
        super();
        this.view = view;
        type = TimePickerType.Type.ALL;
        setView(view);
    }

    public WheelTime(View view, TimePickerType.Type type) {
        super();
        this.view = view;
        this.type = type;
        setView(view);
    }

    public void setPicker(int year, int month, int day) {
        this.setPicker(year, month, day, 0, 0);
    }

    public void setPicker(int year, int month, int day, int h, int m) {
        // 添加大小月月份并将其转换为list,方便之后的判断
        String[] months_big = {"1", "3", "5", "7", "8", "10", "12"};
        String[] months_little = {"4", "6", "9", "11"};

        final List<String> list_big = Arrays.asList(months_big);
        final List<String> list_little = Arrays.asList(months_little);

        Context context = view.getContext();
        // 年
        wv_year = (WheelView) view.findViewById(R.id.year);
        wv_year.setAdapter(new NumericWheelAdapter(startYear, endYear));// 设置"年"的显示数据
        wv_year.setLabel(context.getString(R.string.pickerview_year));// 添加文字
        Log.d("WheelTime","-----------------year  "+(year - startYear));
        wv_year.setCurrentItem(year - startYear);// 初始化时显示的数据

        // 月
        wv_month = (WheelView) view.findViewById(R.id.month);
        wv_month.setAdapter(new NumericWheelAdapter(1, month_now));
        wv_month.setLabel(context.getString(R.string.pickerview_month));
        Log.d("WheelTime","-----------------month  "+month);
        wv_month.setCurrentItem(month);

        // 日
        wv_day = (WheelView) view.findViewById(R.id.day);
//        // 判断大小月及是否闰年,用来确定"日"的数据
//        if (list_big.contains(String.valueOf(month + 1))) {
//            wv_day.setAdapter(new NumericWheelAdapter(1, 31));
//        } else if (list_little.contains(String.valueOf(month + 1))) {
//            wv_day.setAdapter(new NumericWheelAdapter(1, 30));
//        } else {
//            // 闰年
//            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
//                wv_day.setAdapter(new NumericWheelAdapter(1, 29));
//            else
//                wv_day.setAdapter(new NumericWheelAdapter(1, 28));
//        }
        wv_day.setAdapter(new NumericWheelAdapter(1, day_now));
        wv_day.setLabel(context.getString(R.string.pickerview_day));
        Log.d("WheelTime","-----------------day  "+day);
        wv_day.setCurrentItem(day - 1);


        wv_hours = (WheelView) view.findViewById(R.id.hour);
        wv_hours.setAdapter(new NumericWheelAdapter(0, 23));
        wv_hours.setLabel(context.getString(R.string.pickerview_hours));// 添加文字
        wv_hours.setCurrentItem(h);

        wv_mins = (WheelView) view.findViewById(R.id.min);
        wv_mins.setAdapter(new NumericWheelAdapter(0, 59));
        wv_mins.setLabel(context.getString(R.string.pickerview_minutes));// 添加文字
        wv_mins.setCurrentItem(m);

        // 添加"年"监听
        OnItemSelectedListener wheelListener_year = new OnItemSelectedListener() {
            @Override
            public void onItemSelected(int index) {
                int year_num = index + startYear;
                // 判断大小月及是否闰年,用来确定"日"的数据
                int maxItem = 30;
                if (list_big
                        .contains(String.valueOf(wv_month.getCurrentItem() + 1))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 31));
                    maxItem = 31;
                } else if (list_little.contains(String.valueOf(wv_month
                        .getCurrentItem() + 1))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 30));
                    maxItem = 30;
                } else {
                    if ((year_num % 4 == 0 && year_num % 100 != 0)
                            || year_num % 400 == 0) {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 29));
                        maxItem = 29;
                    } else {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 28));
                        maxItem = 28;
                    }
                }
                if (wv_day.getCurrentItem() > maxItem - 1) {
                    wv_day.setCurrentItem(maxItem - 1);
                }
                if (year_num==year_now){
                    //今年最大的月份只能是当前月
                    wv_month.setAdapter(new NumericWheelAdapter(1, month_now));

                }else {
                    wv_month.setAdapter(new NumericWheelAdapter(1, 12));
                }
            }
        };
        // 添加"月"监听
        OnItemSelectedListener wheelListener_month = new OnItemSelectedListener() {
            @Override
            public void onItemSelected(int index) {
                int month_num = index + 1;
                int maxItem = 30;
                // 判断大小月及是否闰年,用来确定"日"的数据
                if (list_big.contains(String.valueOf(month_num))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 31));
                    maxItem = 31;
                } else if (list_little.contains(String.valueOf(month_num))) {
                    wv_day.setAdapter(new NumericWheelAdapter(1, 30));
                    maxItem = 30;
                } else {
                    if (((wv_year.getCurrentItem() + startYear) % 4 == 0 && (wv_year
                            .getCurrentItem() + startYear) % 100 != 0)
                            || (wv_year.getCurrentItem() + startYear) % 400 == 0) {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 29));
                        maxItem = 29;
                    } else {
                        wv_day.setAdapter(new NumericWheelAdapter(1, 28));
                        maxItem = 28;
                    }
                }
                if (wv_day.getCurrentItem() > maxItem - 1) {
                    wv_day.setCurrentItem(maxItem - 1);
                }
                if (month_num==month_now){
                    //今年最大的月份只能是当前月
                    wv_day.setAdapter(new NumericWheelAdapter(1, day_now));
                }
            }
        };
        wv_year.setOnItemSelectedListener(wheelListener_year);
        wv_month.setOnItemSelectedListener(wheelListener_month);

        // 根据屏幕密度来指定选择器字体的大小(不同屏幕可能不同)
        int textSize = 6;
        switch (type) {
            case ALL:
                textSize = textSize * 3;
                break;
            case YEAR_MONTH_DAY:
                textSize = textSize * 4;
                wv_hours.setVisibility(View.GONE);
                wv_mins.setVisibility(View.GONE);
                break;
            case HOURS_MINS:
                textSize = textSize * 4;
                wv_year.setVisibility(View.GONE);
                wv_month.setVisibility(View.GONE);
                wv_day.setVisibility(View.GONE);
                break;
            case MONTH_DAY_HOUR_MIN:
                textSize = textSize * 3;
                wv_year.setVisibility(View.GONE);
                break;
            case YEAR_MONTH:
                textSize = textSize * 4;
                wv_day.setVisibility(View.GONE);
                wv_hours.setVisibility(View.GONE);
                wv_mins.setVisibility(View.GONE);
        }
        wv_day.setTextSize(textSize);
        wv_month.setTextSize(textSize);
        wv_year.setTextSize(textSize);
        wv_hours.setTextSize(textSize);
        wv_mins.setTextSize(textSize);

    }

    /**
     * 设置是否循环滚动
     *
     * @param cyclic
     */
    public void setCyclic(boolean cyclic) {
        wv_year.setCyclic(cyclic);
        wv_month.setCyclic(cyclic);
        wv_day.setCyclic(cyclic);
        wv_hours.setCyclic(cyclic);
        wv_mins.setCyclic(cyclic);
    }

    public String getTime() {
        StringBuffer sb = new StringBuffer();
//        sb.append((wv_year.getCurrentItem() + startYear)).append("-")
//                .append((wv_month.getCurrentItem() + 1)).append("-")
//                .append((wv_day.getCurrentItem() + 1)).append(" ")
//                .append(wv_hours.getCurrentItem()).append(":")
//                .append(wv_mins.getCurrentItem());
        sb.append((wv_year.getCurrentItem() + startYear)).append("-")
                .append((wv_month.getCurrentItem() + 1)).append("-")
                .append((wv_day.getCurrentItem() + 1));
        return sb.toString();
    }

    public View getView() {
        return view;
    }

    public void setView(View view) {
        this.view = view;
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        year_now= calendar.get(Calendar.YEAR);
        month_now = calendar.get(Calendar.MONTH)+1;
        day_now = calendar.get(Calendar.DAY_OF_MONTH);
        int hours = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        this.endYear=year_now;
    }

    public int getStartYear() {
        return startYear;
    }

    public void setStartYear(int startYear) {
        this.startYear = startYear;
    }

    public int getEndYear() {
        return endYear;
    }

    public void setEndYear(int endYear) {
        this.endYear = endYear;
    }
}


提取出来的枚举类:

public class TimePickerType {
    public enum Type {
        ALL, YEAR_MONTH_DAY, HOURS_MINS, MONTH_DAY_HOUR_MIN , YEAR_MONTH
    }// 四种选择模式,年月日时分,年月日,时分,月日时分
}







效果图

Android datepicker获取 android datepicker控件_xml