android 自定义时间选择器

今天自定义了一个时间选择器,继承popupWindow实现的,代码很简单,使用也简单,效果图如下

先看下使用方法

在activity的使用如上图,show()方法用于从底部弹出时间选择器,ClickCallBack为回调方法,用于接收左右两边的两个按钮的点击事件,confirm回调方法中返回的还是一个json对象,方便使用。

默认是显示年月日时分秒,可以通过构造方法传入的type值来设置要显示的日期格式,如type为2的话,显示的是年月日时分,没有秒,具体看完整代码中的解释,备注很清楚。

还有选择器是使用了NumberPicker来实现的,也还是比较简单。

另外代码中还提供了两个方法用于修改左右两个两个TextView的文本内容,完整代码如下:

package com.example.testproject.widget;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class TimeSelector extends PopupWindow {

    private DivNumberPicker mYearPicker;
    private DivNumberPicker mMonthPicker;
    private DivNumberPicker mDayPicker;
    private DivNumberPicker mHourPicker;
    private DivNumberPicker mMinutePicker;
    private DivNumberPicker mSecondPicker;
    private TextView mTvConfirm, mTvCancel;

    //数据集合__混合文字
    private List<String> mYearList = new ArrayList<>();
    private List<String> mMonthList = new ArrayList<>();
    private List<String> mDayList = new ArrayList<>();
    private List<String> mHourList = new ArrayList<>();
    private List<String> mMinuteList = new ArrayList<>();
    private List<String> mSecondList = new ArrayList<>();
    //纯数字
    private List<Integer> mYearNumList = new ArrayList<>();
    private List<Integer> mMonthNumList = new ArrayList<>();
    private List<Integer> mDayNumList = new ArrayList<>();
    private List<Integer> mHourNumList = new ArrayList<>();
    private List<Integer> mMinuteNumList = new ArrayList<>();
    private List<Integer> mSecondNumList = new ArrayList<>();

    private Context mContext;
    private ClickCallBack mClickCallBack;
    private String mStrLeft = "取消";
    private String mStrRight = "确认";

    private int mType = 1;//1.年月日时分秒,2.年月日时分 3.年月日时,4.年月日,5.时分秒,6.时分

    public TimeSelector(Context context) {
        super(context);
        mContext = context;
        initView(context);
    }

    public TimeSelector(Context context, int mType) {
        super(context);
        mContext = context;
        this.mType = mType;
        initView(context);
    }

    private void initView(final Context context) {
        //获取屏幕宽高信息
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        if (wm != null) {
            wm.getDefaultDisplay().getMetrics(dm);
        }
        this.setHeight(dm.heightPixels / 3);
        this.setWidth(dm.widthPixels);

        //动态创建外层布局
        LinearLayout llContent = new LinearLayout(context);
        llContent.setOrientation(LinearLayout.VERTICAL);
        llContent.setBackgroundColor(Color.WHITE);

        RelativeLayout rlTitle = new RelativeLayout(context);
        rlTitle.setBackgroundColor(Color.WHITE);

        //动态创建两个TextView
        mTvCancel = new TextView(context);
        mTvCancel.setText(mStrLeft);
        mTvCancel.setTextSize(15);

        mTvConfirm = new TextView(context);
        mTvConfirm.setText(mStrRight);
        mTvConfirm.setTextSize(15);

        rlTitle.addView(mTvCancel);
        rlTitle.addView(mTvConfirm);

        RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) mTvCancel.getLayoutParams();
        rlp.setMargins(14, 12, 0, 12);
        rlp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        mTvCancel.setLayoutParams(rlp);

        RelativeLayout.LayoutParams rlp1 = (RelativeLayout.LayoutParams) mTvConfirm.getLayoutParams();
        rlp1.setMargins(0, 12, 14, 12);
        rlp1.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        mTvConfirm.setLayoutParams(rlp1);

        //动态创建NumberPicker
        LinearLayout llDataSel = new LinearLayout(context);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        llDataSel.setOrientation(LinearLayout.HORIZONTAL);
        lp.weight = 1;
        lp.setMargins(7, 0, 7, 0);
        mYearPicker = new DivNumberPicker(context);
        mMonthPicker = new DivNumberPicker(context);
        mDayPicker = new DivNumberPicker(context);
        mHourPicker = new DivNumberPicker(context);
        mMinutePicker = new DivNumberPicker(context);
        mSecondPicker = new DivNumberPicker(context);

        mYearPicker.setLayoutParams(lp);
        mMonthPicker.setLayoutParams(lp);
        mDayPicker.setLayoutParams(lp);
        mHourPicker.setLayoutParams(lp);
        mMinutePicker.setLayoutParams(lp);
        mSecondPicker.setLayoutParams(lp);

        llDataSel.addView(mYearPicker);
        llDataSel.addView(mMonthPicker);
        llDataSel.addView(mDayPicker);
        llDataSel.addView(mHourPicker);
        llDataSel.addView(mMinutePicker);
        llDataSel.addView(mSecondPicker);

        llContent.addView(rlTitle);
        llContent.addView(llDataSel);

        this.setContentView(llContent);

        initData(mType);
        initListener();
    }

    /**
     * 添加监听方法
     */
    private void initListener() {
        mTvConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mClickCallBack != null)
                    mClickCallBack.confirm(getResult());
                setAlpha(1.0f);
            }
        });

        mTvCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mClickCallBack != null)
                    mClickCallBack.cancel();
                setAlpha(1.0f);
            }
        });
        this.setOnDismissListener(new OnDismissListener() {
            @Override
            public void onDismiss() {
                setAlpha(1.0f);
            }
        });
    }

    /**
     * 显示时间选择器
     *
     * @param view
     */
    public void show(View view) {
        this.setOutsideTouchable(true);
        this.showAtLocation(view, Gravity.BOTTOM, 0, 0);
        setAlpha(0.3f);
    }

    /**
     * 改变背景透明度
     *
     * @param value
     */
    private void setAlpha(Float value) {
        WindowManager.LayoutParams layoutParams = ((Activity) mContext).getWindow().getAttributes();
        layoutParams.alpha = value;
        ((Activity) mContext).getWindow().setAttributes(layoutParams);
    }

    /**
     * 设置左边文本的内容
     * @param o
     */
    public void setLeftTextContent(Object o) {
        if (mTvCancel == null)
            return;
        if (o instanceof String)
            mTvCancel.setText((String) o);
        else if (o instanceof Integer)
            mTvCancel.setText((Integer) o);
        else
            mTvCancel.setText(mStrLeft);
    }

    /**
     * 设置左边文本的内容
     * @param o
     */
    public void setRightTextContent(Object o) {
        if (mTvConfirm == null)
            return;
        if (o instanceof String)
            mTvConfirm.setText((String) o);
        else if (o instanceof Integer)
            mTvConfirm.setText((Integer) o);
        else
            mTvConfirm.setText(mStrRight);
    }

    /**
     * 设置选中后的返回数据,以json数据的形式返回
     *
     * @return
     */
    private JSONObject getResult() {
        //数据回调
        int yearPos = mYearPicker.getValue();
        int monthPos = mMonthPicker.getValue();
        int dayPos = mDayPicker.getValue();
        int hourPos = mHourPicker.getValue();
        int minutePos = mMinutePicker.getValue();
        int secondPos = mSecondPicker.getValue();
        JSONObject object = new JSONObject();
        try {
            switch (mType) {
                case 1:
                    object.put("year", mYearNumList.get(yearPos).toString());
                    object.put("month", mMonthNumList.get(monthPos).toString());
                    object.put("day", mDayNumList.get(dayPos).toString());
                    object.put("hour", mHourNumList.get(hourPos).toString());
                    object.put("minute", mMinuteNumList.get(minutePos).toString());
                    object.put("second", mSecondNumList.get(secondPos).toString());
                    break;
                case 2:
                    object.put("year", mYearNumList.get(yearPos).toString());
                    object.put("month", mMonthNumList.get(monthPos).toString());
                    object.put("day", mDayNumList.get(dayPos).toString());
                    object.put("hour", mHourNumList.get(hourPos).toString());
                    object.put("minute", mMinuteNumList.get(minutePos).toString());
                    break;
                case 3:
                    object.put("year", mYearNumList.get(yearPos).toString());
                    object.put("month", mMonthNumList.get(monthPos).toString());
                    object.put("day", mDayNumList.get(dayPos).toString());
                    object.put("hour", mHourNumList.get(hourPos).toString());
                    break;
                case 4:
                    object.put("year", mYearNumList.get(yearPos).toString());
                    object.put("month", mMonthNumList.get(monthPos).toString());
                    object.put("day", mDayNumList.get(dayPos).toString());
                    break;
                case 5:
                    object.put("hour", mHourNumList.get(hourPos).toString());
                    object.put("minute", mMinuteNumList.get(minutePos).toString());
                    object.put("second", mSecondNumList.get(secondPos).toString());
                case 6:
                    object.put("hour", mHourNumList.get(hourPos).toString());
                    object.put("minute", mMinuteNumList.get(minutePos).toString());
                    break;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return object;
    }

    @SuppressLint("DefaultLocale")
    private void initData(int type) {
        //根据type现实ui__1年月日时分秒,2年月日时分 3年月日时,4年月日,5时分秒,6时分
        switch (type) {
            case 2:
                mSecondPicker.setVisibility(View.GONE);
                break;
            case 3:
                mMinutePicker.setVisibility(View.GONE);
                mSecondPicker.setVisibility(View.GONE);
                break;
            case 4:
                mHourPicker.setVisibility(View.GONE);
                mMinutePicker.setVisibility(View.GONE);
                mSecondPicker.setVisibility(View.GONE);
                break;
            case 5:
                mYearPicker.setVisibility(View.GONE);
                mMonthPicker.setVisibility(View.GONE);
                mDayPicker.setVisibility(View.GONE);
                break;
            case 6:
                mYearPicker.setVisibility(View.GONE);
                mMonthPicker.setVisibility(View.GONE);
                mDayPicker.setVisibility(View.GONE);
                mHourPicker.setVisibility(View.GONE);
                break;
        }

        //数据集合初始化
        //年
        Calendar startCal = Calendar.getInstance();
        startCal.setTimeInMillis(0);
        Calendar curCal = Calendar.getInstance();
        int startYear = startCal.get(Calendar.YEAR);
        int endYear = curCal.get(Calendar.YEAR);

        for (int i = endYear; i >= startYear; i--) {
            mYearList.add(i + "年");
            mYearNumList.add(i);
        }
        //月
        for (int i = 1; i <= 12; i++) {
            mMonthList.add(String.format("%02d", i) + "月");
            mMonthNumList.add(i);
        }
        //日
        int curDay = curCal.getActualMaximum(Calendar.DAY_OF_MONTH);//当前月份有多少天
        for (int i = 1; i <= curDay; i++) {
            mDayList.add(String.format("%02d", i) + "日");
            mDayNumList.add(i);
        }
        //时
        for (int i = 1; i <= 24; i++) {
            mHourList.add(String.format("%02d", i) + "时");
            mHourNumList.add(i);
        }
        //分
        for (int i = 1; i <= 60; i++) {
            mMinuteList.add(String.format("%02d", i) + "分");
            mMinuteNumList.add(i);
        }
        //秒
        for (int i = 1; i <= 60; i++) {
            mSecondList.add(String.format("%02d", i) + "秒");
            mSecondNumList.add(i);
        }
        //设置数据----------------------------------------------------------
        //获取当前初始化数据__月日时分秒
        int cMonth = curCal.get(Calendar.MONTH);//从0开始
        int cDay = curCal.get(Calendar.DATE) - 1;//日
        int cHour = curCal.get(Calendar.HOUR_OF_DAY) - 1;//时
        int cMinute = curCal.get(Calendar.MINUTE) - 1;//分
        int cSecond = curCal.get(Calendar.SECOND) - 1;//秒

        mYearPicker.setDisplayedValues(mYearList.toArray(new String[0]));
        mYearPicker.setMaxValue(mYearList.size() - 1); //设置最大值
        mYearPicker.setWrapSelectorWheel(true);
        mYearPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止输入

        mMonthPicker.setDisplayedValues(mMonthList.toArray(new String[0]));
        mMonthPicker.setMaxValue(mMonthList.size() - 1); //设置最大值
        mMonthPicker.setWrapSelectorWheel(true);
        mMonthPicker.setValue(cMonth);
        mMonthPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止输入

        mDayPicker.setDisplayedValues(mDayList.toArray(new String[0]));
        mDayPicker.setMaxValue(mDayList.size() - 1); //设置最大值
        mDayPicker.setWrapSelectorWheel(true);
        mDayPicker.setValue(cDay);
        mDayPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止输入

        mHourPicker.setDisplayedValues(mHourList.toArray(new String[0]));
        mHourPicker.setMaxValue(mHourList.size() - 1); //设置最大值
        mHourPicker.setWrapSelectorWheel(true);
        mHourPicker.setValue(cHour);
        mHourPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止输入

        mMinutePicker.setDisplayedValues(mMinuteList.toArray(new String[0]));
        mMinutePicker.setMaxValue(mMinuteList.size() - 1); //设置最大值
        mMinutePicker.setWrapSelectorWheel(true);
        mMinutePicker.setValue(cMinute);
        mMinutePicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止输入

        mSecondPicker.setDisplayedValues(mSecondList.toArray(new String[0]));
        mSecondPicker.setMaxValue(mSecondList.size() - 1); //设置最大值
        mSecondPicker.setWrapSelectorWheel(true);
        mSecondPicker.setValue(cSecond);
        mSecondPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止输入

    }


    /**
     * 自定义NumberPicker ---------------------------------------------------------------
     */
    public class DivNumberPicker extends NumberPicker {

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

        public DivNumberPicker(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public DivNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }

        @Override
        public void addView(View child) {
            super.addView(child);
            updateView(child);
        }

        @Override
        public void addView(View child, int index,
                            android.view.ViewGroup.LayoutParams params) {
            super.addView(child, index, params);
            updateView(child);
        }

        @Override
        public void addView(View child, android.view.ViewGroup.LayoutParams params) {
            super.addView(child, params);
            updateView(child);
        }

        public void updateView(View view) {
            if (view instanceof EditText) {
                //这里修改显示字体的属性,主要修改颜色
                ((EditText) view).setTextSize(12);
                ((EditText) view).setTextColor(Color.BLACK);
            }
        }

        @Override
        public void setDisplayedValues(String[] displayedValues) {
            super.setDisplayedValues(displayedValues);
            setNumberPickerDividerColor(this);
        }

        //设置分割线的颜色值
        private void setNumberPickerDividerColor(NumberPicker numberPicker) {
            Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                if (pf.getName().equals("mSelectionDivider")) {
                    pf.setAccessible(true);
                    try {
                        //设置分割线的颜色值 透明
                        pf.set(numberPicker, new ColorDrawable(Color.BLUE));
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (Resources.NotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
    }

    /**
     * 定义回调接口 ----------------------------------------------------------------------
     */
    public interface ClickCallBack {
        void cancel();

        void confirm(JSONObject jsonObject);
    }

    public void setmClickCallBack(ClickCallBack mClickCallBack) {
        this.mClickCallBack = mClickCallBack;
    }
}

猜你喜欢

转载自blog.csdn.net/taoyuxin1314/article/details/106948485