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

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

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

自定义的DataPicker和TimePicker(日期选择器和时间选择器)_第1张图片

   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

自定义的DataPicker和TimePicker(日期选择器和时间选择器)_第2张图片

因为我们的需求是需要开始时间和结束时间两个时间点,所以我直接把开始时间和结束时间封装在了一起,并且没有区分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个月份每个月的天数不同
自定义的DataPicker和TimePicker(日期选择器和时间选择器)_第3张图片

同样,首先,我们先 创建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就完成了,然后就可以使用了
自定义的DataPicker和TimePicker(日期选择器和时间选择器)_第4张图片

Demo下载地址

你可能感兴趣的:(自定义控件,TimePicker,datapicker)