自定义的DataPicker和TimePicker(日期选择器和时间选择器)

来源:互联网 发布:老子化胡 知乎 编辑:程序博客网 时间:2024/06/06 12:44

公司项目里用到了TimePicker和DataPicker,但是因为项目用的版本较低,所以TimePicker和DataPicker显示出来的样式不怎么美观,那种黑白的,实在看不下去,于是自己定义了两个控件,拿出来分享一下

首先封装一个输入框,加减可控制:

这里写图片描述

   private void onCreat() {        view = LayoutInflater.from(this.getContext()).inflate(R.layout.dialog_picker, this, true);        initView();    }

监听点击事件和输入事件,将接口透出去:

/**     * 接口     * imgAdd  +     * imgMinus  —     */    public interface OnClickListener {        //加        void add(String inputStr);        //减        void minus(String inputStr);        //输入的内容的监听        void textChange(Editable str);    }

点击事件

 //点击事件  加号        imgAdd.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (onClickListener != null) {                    String inputStr = edInput.getText().toString();                    onClickListener.add(inputStr);                }            }        }); //点击事件  减号        imgMinus.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (onClickListener != null) {                    String inputStr = edInput.getText().toString();                    onClickListener.minus(inputStr);                }            }        });

输入事件监听,之前是准备让EditText中的值也可以手动输入,但是这样的话会牵涉到焦点的获取之类的,还有更多的逻辑判断,项目当时有点紧,就没有让EditText设置可输入,有兴趣的小伙伴们可以自己加上去

edInput.addTextChangedListener(new TextWatcher() {            @Override            public void beforeTextChanged(CharSequence s, int start, int count, int after) {            }            @Override            public void onTextChanged(CharSequence s, int start, int before, int count) {            }            @Override            public void afterTextChanged(Editable s) {                if (onClickListener != null) {                    onClickListener.textChange(s);                }            }        });

设置输入的长度 xml中设置了最大显示数目

    public void setInputLenth(int inputLenth) {        if (inputLenth == 0 || String.valueOf(inputLenth).length() == 0 || "".equals(String.valueOf(inputLenth))) {            edInput.setFilters(new InputFilter[]{new InputFilter.LengthFilter(4)});        } else {            //最大输入长度            edInput.setFilters(new InputFilter[]{new InputFilter.LengthFilter(inputLenth)});        }    }

因为封装的这个控件会分别用到DataPicker和Timeker 中,所以要实用多种情况,控件中间不光是一个EditText,EditText 的右面还有一个TextView,宽度设置自适应,这样就还可以通过代码直接设置显示的情况,从而实现作用于不同的场景

   /**     * 设置显示的类型     *     * @param inputType tvType 显示的值 "年","月","日"     */    public void setInputType(String inputType) {        tvType.setText(inputType);    }

设置EditText 中输入的值,一般用来设置默认的显示值

   /**     * 设置EditText显示的内容     *     * @param string EditText要显示的值     */    public void setEdInput(String string) {        edInput.setText(string);    }

获得EditText中输入的值

   public String getEdInput() {        return edInput.getText().toString();    }

现在这一部分就基本完成了,接着就要开始封装TimePicker了


封装TimePickerDialog

这里写图片描述

因为我们的需求是需要开始时间和结束时间两个时间点,所以我直接把开始时间和结束时间封装在了一起,并且没有区分12时计时法和24时计时法,默认成24时计时法,其实如果想加上的话只需要把定义一个全局变量,把接口透出去,就可以了,这里就不做赘述了

view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_time, null);        hourStart = (MyDatePickerDia) view.findViewById(R.id.date_hour_start);        hourEnd = (MyDatePickerDia) view.findViewById(R.id.date_hour_end);        minuteStart = (MyDatePickerDia) view.findViewById(R.id.date_minute_start);        minuteEnd = (MyDatePickerDia) view.findViewById(R.id.date_minute_end);        tvDate = (TextView) view.findViewById(R.id.tv_date);        tvOk = (TextView) view.findViewById(R.id.ok);        tvOk.setClickable(true);        tvCancle = (TextView) view.findViewById(R.id.cancel);        tvCancle.setClickable(true);        //点击确定的时候把每个之前封装的控件中的值取到,然后用“:”和"-"拼接之后传出去        tvOk.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (onClickListener != null) {                    int hs = Integer.parseInt(hourStart.getEdInput());                    int he = Integer.parseInt(hourEnd.getEdInput());                    int ms = Integer.parseInt(minuteStart.getEdInput());                    int me = Integer.parseInt(minuteEnd.getEdInput());                    String time = String.format(format, hs) + ":" + String.format(format, ms)                            + "-" + String.format(format, he) + ":" + String.format(format, me);                    onClickListener.clickOk(time);                }                dismiss();            }        });//点击取消的时候,将时间设置成默认,这里是将开始时间默认设置为800,结束时间默认设置成1800        tvCancle.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (onClickListener != null) {                    String time = "08:00-18:00";                    onClickListener.clickCancle(time);                }                dismiss();            }        });

透出的接口

  /**     * 接口     */    public interface OnClickListener {        void clickOk(String ok);        void clickCancle(String cancle);    }

设置确定按钮和取消按钮显示的字符串

/**     * 设置取消按钮的显示内容     *     * @param cancle 显示的内容     */    public void setTextCancle(String cancle) {        tvCancle.setText(cancle);    }    /**     * 设置确定按钮的显示内容     *     * @param ok     */    public void steTextOk(String ok) {        tvOk.setText(ok);    }

设置Dialog的样式,

  /**     * dialog 的宽高的设置     */    private void resize() {        Window dialogWindow = this.getWindow();        int width = WindowUtils.getScreenWidth(dialogWindow);        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值        p.width = (int) (width * 0.85); // 宽度设置为屏幕的0.85        dialogWindow.setAttributes(p);    }

设置Dialog的标题

  /**     * 设置标题     */    public void setTittle(String string) {        tvDate.setText(string);    }

准备工作算是基本完成了,现在该开始写逻辑了

上班的时间中的小时的操作

 /**     * 上班时间  -小时     */    private void hourStartSetting() {        //设置最多显示两位        hourStart.setInputLenth(2);        //不足两位十位补零 默认设置为  08        hourStart.setEdInput(String.format(format, 8));        hourStart.setOnClickListener(new MyDatePickerDia.OnClickListener() {            @Override            public void add(String inputStr) {                hourAdd(true);            }            @Override            public void minus(String inputStr) {                hourMinus(true);            }            @Override            public void textChange(Editable str) {            }        });    }

上班分钟的操作

/**     * 上班时间  -分钟     */    private void minuteStartSetting() {        minuteStart.setInputLenth(2);        minuteStart.setEdInput(String.format(format, 0));        minuteStart.setOnClickListener(new MyDatePickerDia.OnClickListener() {            @Override            public void add(String inputStr) {                minuteAdd(true);            }            @Override            public void minus(String inputStr) {                minuteMinus(true);            }            @Override            public void textChange(Editable str) {            }        });    }

下班小时操作

 /**     * 下班时间  -小时     */    private void hourEndSetting() {      //设置最多显示两位        hourStart.setInputLenth(2);        //不足两位十位补零 默设置为 18        hourEnd.setEdInput(String.format(format, 18));        hourEnd.setOnClickListener(new MyDatePickerDia.OnClickListener() {            @Override            public void add(String inputStr) {                hourAdd(false);            }            @Override            public void minus(String inputStr) {                hourMinus(false);            }            @Override            public void textChange(Editable str) {            }        });    }

下班分钟的操作

/**     * 下班时间  -分钟     */    private void minuEndSetting() {        minuteEnd.setInputLenth(2);        minuteEnd.setEdInput(String.format(format, 0));        minuteEnd.setOnClickListener(new MyDatePickerDia.OnClickListener() {            @Override            public void add(String inputStr) {                minuteAdd(false);            }            @Override            public void minus(String inputStr) {                minuteMinus(false);            }            @Override            public void textChange(Editable str) {            }        });    }

小时+

 /**     * 小时 +     *     * @param type 类型 true 开始  false 结束     */    private void hourAdd(boolean type) {        int hour = 0;        if (type) {            hour = Integer.parseInt(hourStart.getEdInput());        } else {            hour = Integer.parseInt(hourEnd.getEdInput());        }        if (hour == 23) {            hour = 0;        } else {            hour++;        }        String Hour = String.format(format, hour);        if (type) {            hourStart.setEdInput(Hour);        } else {            hourEnd.setEdInput(Hour);        }    }

小时-

 /**     * 小时 -     *     * @param type 类型 true 开始  false 结束     */    private void hourMinus(boolean type) {        int hour = 0;        if (type) {            hour = Integer.parseInt(hourStart.getEdInput());        } else {            hour = Integer.parseInt(hourEnd.getEdInput());        }        if (hour == 0) {            hour = 23;        } else {            hour--;        }        String Hour = String.format(format, hour);        if (type) {            hourStart.setEdInput(Hour);            return;        }        hourEnd.setEdInput(Hour);    }

分钟+

 /**     * 分钟  +     *     * @param type 类型 true 开始  false 结束     */    private void minuteAdd(boolean type) {        int minute = 0;        if (type) {            minute = Integer.parseInt(minuteStart.getEdInput());        } else {            minute = Integer.parseInt(minuteEnd.getEdInput());        }        if (minute == 59) {            minute = 0;            if (type) {                hourAdd(true);            } else {                hourAdd(false);            }        } else {            minute++;        }        if (type) {            minuteStart.setEdInput(String.format(format, minute));            return;        }        minuteEnd.setEdInput(String.format(format, minute));    }

分钟-

/**     * 分钟减     *     * @param type 类型 true 开始  false 结束     */    private void minuteMinus(boolean type) {        int minute = 0;        if (type) {            minute = Integer.parseInt(minuteStart.getEdInput());        } else {            minute = Integer.parseInt(minuteEnd.getEdInput());        }        if (minute == 0) {            minute = 59;            if (type) {                hourMinus(true);            } else {                hourMinus(false);            }        } else {            minute--;        }        if (type) {            minuteStart.setEdInput(String.format(format, minute));            return;        }        minuteEnd.setEdInput(String.format(format, minute));    }

到这里基本的逻辑也就完成的差不多了,TimePickerDialog也就基本完成了


接下来我们接着封装DataPickerDialog

DataPicker相比TimePicker稍微麻烦一点,原因就是DataPicker中牵扯到了闰年平年,以及12个月份每个月的天数不同
这里写图片描述

同样,首先,我们先 创建Diallog

 view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_date, null);        year = (MyDatePickerDia) view.findViewById(R.id.date_year);        month = (MyDatePickerDia) view.findViewById(R.id.date_month);        day = (MyDatePickerDia) view.findViewById(R.id.date_day);        tvDate = (TextView) view.findViewById(R.id.tv_date);        tvOk = (TextView) view.findViewById(R.id.ok);        tvOk.setClickable(true);        tvCancle = (TextView) view.findViewById(R.id.cancel);        tvCancle.setClickable(true);        tvOk.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (onClickListener != null) {                    onClickListener.clickOk(tittleShow());                }                dismiss();            }        });        tvCancle.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (onClickListener != null) {                    String now = String.valueOf(calendar.get(Calendar.YEAR)) + "年-"                            + String.format(format, calendar.get(Calendar.MONTH) + 1) + "月-"                            + String.format(format, calendar.get(Calendar.DAY_OF_MONTH)) + "日";                    onClickListener.clickCancle(now);                }                dismiss();            }        });

与TimePickerDialog差不多,不做赘述
这里主要写逻辑代码
年的设置

 /**     * 年的设置     */    private void yearSetting() {        year.setInputType("年");        year.setInputLenth(4);        year.setEdInput(String.valueOf(calendar.get(Calendar.YEAR)));        year.setOnClickListener(new MyDatePickerDia.OnClickListener() {            @Override            public void add(String inputStr) {                yearAdd(inputStr);                tittleShow();            }            @Override            public void minus(String inputStr) {                yearMinus(inputStr);                tittleShow();            }            @Override            public void textChange(Editable str) {                tvDate.setText(str);            }        });    }

月的设置

/**     * 月的设置     */    private void monthSetting() {        month.setInputType("月");        month.setInputLenth(2);        month.setEdInput(String.format(format, calendar.get(Calendar.MONTH) + 1));        month.setOnClickListener(new MyDatePickerDia.OnClickListener() {            @Override            public void add(String inputStr) {                monthAdd(inputStr);                tittleShow();            }            @Override            public void minus(String inputStr) {                monthMinus(inputStr);                tittleShow();            }            @Override            public void textChange(Editable str) {            }        });    }

天的设置

/**     * 天的设置     */    private void daySetting() {        day.setInputType("日");        day.setInputLenth(2);        day.setEdInput(String.format(format, calendar.get(Calendar.DAY_OF_MONTH)));        day.setOnClickListener(new MyDatePickerDia.OnClickListener() {            @Override            public void add(String inputStr) {                dayAdd(inputStr);                tittleShow();            }            @Override            public void minus(String inputStr) {                dayMinus(inputStr);                tittleShow();            }            @Override            public void textChange(Editable str) {            }        });    }

年+

 /**     * 年 +     *     * @param add     */    private void yearAdd(String add) {        int input = 0;        if (add.length() == 0 || "".equals(add) || Integer.parseInt(add) < 1900) {            add = "1900";            year.setEdInput(add);        } else {            input = Integer.parseInt(add);            input++;            if (input > 2100) {                input = 2100;            }            yearChange(input);            year.setEdInput(String.valueOf(input));        }    }

年-

 /**     * 年 -     *     * @param minus     */    private void yearMinus(String minus) {        int input = 0;        if (minus.length() == 0 || "".equals(minus) || Integer.parseInt(minus) < 1900) {            minus = "1900";            year.setEdInput(minus);        } else {            input = Integer.parseInt(minus);            if (input > 2101) {                input = 2101;            }            input--;            if (input < 1900) {                input = 1900;            }            yearChange(input);            year.setEdInput(String.valueOf(input));        }    }

月 +

/**     * 月 +     *     * @param add     */    private void monthAdd(String add) {        int input = 0;        if ((add.length() == 0) || "".equals(add) || (Integer.parseInt(add) > 12) || (Integer.parseInt(add) < 1)) {            add = String.format(format, calendar.get(Calendar.MONTH));            month.setEdInput(add);        } else {            input = Integer.parseInt(add);            if (input == 12) {                input = 1;                //月份变化对年的影响 +1                yearAdd(year.getEdInput());            } else {                input++;                //月份变化对日的影响                monthChange(input);            }            month.setEdInput(String.format(format, input));        }    }

月-

 /**     * 月 -     *     * @param minus     */    private void monthMinus(String minus) {        int input = 0;        if ((minus.length() == 0) || "".equals(minus) || (Integer.parseInt(minus) > 12) || (Integer.parseInt(minus) < 1)) {            minus = String.format(format, calendar.get(Calendar.MONTH));            month.setEdInput(minus);            return;        }        input = Integer.parseInt(minus);        if (input == 1) {            input = 12;            //月份变化对年的影响 -1            yearMinus(year.getEdInput());        } else {            input--;            //月份变化对日的影响            monthChange(input);        }        month.setEdInput(String.format(format, input));    }

日+

/**     * 日 +     *     * @param add     */    private void dayAdd(String add) {        int y = Integer.parseInt(year.getEdInput());        int m = Integer.parseInt(month.getEdInput());        int d = Integer.parseInt(add);        if ("".equals(add) || add.length() == 0 || d > 31 || d < 1) {            month.setEdInput(String.format(format, calendar.get(Calendar.MONTH) + 1));            day.setEdInput(String.format(format, calendar.get(Calendar.DAY_OF_MONTH)));        } else if (d == 31) {            monthAdd(String.format(format, m));            day.setEdInput(String.format(format, 1));        } else if (d == 30) {            if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) {                d++;                day.setEdInput(String.format(format, d));            } else {                monthAdd(String.format(format, m));                day.setEdInput(String.format(format, 1));            }        } else if (d == 29) {            if (m == 2) {                monthAdd(String.format(format, m));                day.setEdInput(String.format(format, 1));            } else {                d++;                day.setEdInput(String.format(format, d));            }        } else if (d == 28) {            if (m == 2) {                if (isLeapYear(y)) {                    d++;                    day.setEdInput(String.format(format, d));                } else {                    monthAdd(String.format(format, m));                    day.setEdInput(String.format(format, 1));                }            } else {                d++;                day.setEdInput(String.format(format, d));            }        } else {            d++;            day.setEdInput(String.format(format, d));        }    }

日-

/**     * 日 —     *     * @param minus     */    private void dayMinus(String minus) {        int y = Integer.parseInt(year.getEdInput());        int m = Integer.parseInt(month.getEdInput());        int d = Integer.parseInt(minus);        if ("".equals(minus) || minus.length() == 0 || d > 31 || d < 1) {            day.setEdInput(String.format(format, calendar.get(Calendar.DAY_OF_MONTH)));        } else if (d == 1) {            //46911四个月是30天,上一个月一号减1,变成30if (m == 5 || m == 7 || m == 10 || m == 12) {                day.setEdInput(String.format(format, 30));            } else if (m == 3) {                if (isLeapYear(y)) {                    day.setEdInput(String.format(format, 29));                } else {                    day.setEdInput(String.format(format, 28));                }            } else {                day.setEdInput(String.format(format, 31));            }            monthMinus(String.format(format, m));        } else if (d == 31) {            if (m == 2) {                if (isLeapYear(y)) {                    day.setEdInput(String.format(format, 29));                } else {                    day.setEdInput(String.format(format, 28));                }            } else if (m == 4 || m == 6 || m == 9 || m == 11) {                day.setEdInput(String.format(format, 30));            } else {                d--;                day.setEdInput(String.format(format, d));            }        } else if (d == 30) {            if (m == 2 && !isLeapYear(y)) {                day.setEdInput(String.format(format, 28));            } else {                d--;                day.setEdInput(String.format(format, d));            }        } else {            d--;            day.setEdInput(String.format(format, d));        }    }

不同的月份对天的影响不同

   /**     * 月份改变对日的影响     *     * @param month 月份     */    private void monthChange(int month) {        //2月情况特殊,需分平年闰年,特殊处理        if (month == 2) {            if (isLeapYear(Integer.parseInt(year.getEdInput()))) {                if (Integer.parseInt(day.getEdInput()) > 29) {                    day.setEdInput("29");                }            } else {                if (Integer.parseInt(day.getEdInput()) > 28) {                    day.setEdInput("28");                }            }            //4,6,9,11一个月最多三十天        } else if (month == 4 || month == 6 || month == 9 || month == 11) {            if (Integer.parseInt(day.getEdInput()) > 30) {                day.setEdInput("30");            }        }    }

不同的年份对天的影响也不一样

   /**     * 年份改变对日的影响     *     * @param year 年份     */    private void yearChange(int year) {        int m = Integer.parseInt(month.getEdInput());        int d = Integer.parseInt(day.getEdInput());        if (m == 2) {            if (isLeapYear(year)) {                if (d > 29) {                    day.setEdInput("29");                }            } else {                if (d > 28) {                    day.setEdInput("28");                }            }        } else if (m == 4 || m == 6 || m == 9 || m == 11) {            if (d > 30) {                day.setEdInput("30");            }        }    }

基姆拉尔森计算公式 ,根据日期计算星期几

    /**     * 基姆拉尔森计算公式  Week=(Day + 2*Month + 3*(Month+1)/5 + Year + Year/4 - Year/100 + Year/400) % 7     *     * @param y 年     * @param m 月  1,2月需要按13月,14日     * @param d 日     * @return     */    private String getWeek(int y, int m, int d) {        String Week = "星期";        if (m == 1) {            m = 13;        }        if (m == 2) {            m = 14;        }        int week = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;        switch (week) {            case 0:                Week += "一";                break;            case 1:                Week += "二";                break;            case 2:                Week += "三";                break;            case 3:                Week += "四";                break;            case 4:                Week += "五";                break;            case 5:                Week += "六";                break;            case 6:                Week += "日";                break;            default:                break;        }        return Week;    }

这样基本上DataPickerDialog就完成了,然后就可以使用了
这里写图片描述


Demo下载地址

2 0
原创粉丝点击