您好,欢迎来到欧得旅游网。
搜索
您的当前位置:首页android 自定义时间选择器 CustomDateDialog

android 自定义时间选择器 CustomDateDialog

来源:欧得旅游网

在项目中需做一个自定义时间选择器,仅显示选择年月,其中设置分割线颜色和宽度,设置仅能选择已知时间,不能设置未来时间.话不多说,直接上代码.

Fragment代码片段
//...
import com.xxx.dialog.CustomDateDialog;
//...
private CustomDateDialog timeDialog;
private View mainView;
//...
private ConstraintLayout timeBtn;//时间盒子
private AppCompatTextView timeText; //时间文字
private String selectTime = ""; //所选择时间值
//...

timeBtn = mainView.findViewById(R.id.time_btn);//时间盒子
timeText = mainView.findViewById(R.id.time_text); //时间文字
//...

//时间筛选
timeBtn.setOnClickListener(v -> {
    //ButtonUtils 多次点击仅一次有效
    if (!ButtonUtils.isFastDoubleClick()) {
        timeDialog = new CustomDateDialog(getContext());
        Calendar calendar = Calendar.getInstance();
        timeDialog.setDate(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),(year, month, day) -> {
        //Log.i(TAG, "日期:" + year + month + day);
        String monthNum = month + "";
        String dayNum = day + "";
        if (monthNum.length() == 1) {
             monthNum = "0" + monthNum;
        }
        //if (dayNum.length() == 1) {
        // dayNum = "0" + dayNum;
        // }
        // timeText .setText(year + "年" + monthNum + "月" + dayNum);
        timeText .setText(year + "年" + monthNum + "月");
        selectTime = year + "-" + monthNum;
         //请求数据
         getList(true, true);
         });
         timeDialog.show();
     }
});

//获取数据
private void getList(boolean clearData, boolean showDialog) {
       //TODO
}

 //CustomDateDialog片段

//...
package com.xxx.dialog;
import com.xxx.R;
//...

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.NumberPicker;

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

import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatTextView;

public class CustomDateDialog implements View.OnClickListener, DatePicker.OnDateChangedListener {

    private Dialog dialog;
    private AppCompatTextView titleTv;//标题
    private DatePicker datePicker;//日期选择控件
    private AppCompatButton confirmTv;//确认按钮
    private AppCompatButton cancelTv;//取消按钮
    private View dialogView;
    private OnDateSetListener onDateSetListener;

    /**
     * 构造器
     *
     * @param context 上下文
     */
    public CustomDateDialog(Context context) {
        dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_time_warp, null);
        dialog = new Dialog(context, R.style.CustomDateDialog);
        titleTv = dialogView.findViewById(R.id.type_title);
        datePicker = dialogView.findViewById(R.id.datePicker);
        resizePicker(datePicker);
        ViewGroup viewGroup1 = (ViewGroup) datePicker.getChildAt(0);
        ViewGroup viewGroup2 = (ViewGroup) viewGroup1.getChildAt(0);//获取年月日的下拉列表项

        //隐藏 --日--
        if (viewGroup2.getChildCount() == 3) {//有的机型没有竖线,只有年、月、日
            viewGroup2.getChildAt(2).setVisibility(View.GONE);
        } else if (viewGroup2.getChildCount() == 5) {//有的机型有有竖线
            viewGroup2.getChildAt(3).setVisibility(View.GONE);
            viewGroup2.getChildAt(4).setVisibility(View.GONE);
        }
        confirmTv = dialogView.findViewById(R.id.ok_btn);
        cancelTv = dialogView.findViewById(R.id.cancel_btn);
        confirmTv.setOnClickListener(this);
        cancelTv.setOnClickListener(this);
        setDatePickerDividerColor(datePicker);

        //设置最大日期
        setMaxSelectableDate(datePicker);
        datePicker.setOnDateChangedListener(this);
    }


    /**
     * 显示对话框
     */
    public void show() {
        Window window = dialog.getWindow();
        window.setContentView(dialogView);//设置对话框窗口的内容视图(这里有个坑,参数不要传R.layout.date_dialog,否则会出现各种问题,比如按钮响应不了点击事件)
        window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);//设置对话框窗口的布局参数
        dialog.show();
        dialog.setCancelable(false);
    }

    /**
     * 关闭对话框
     */
    public void dismiss() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    /**
     * 设置标题
     *
     * @param title 标题
     */
    public void setTitle(String title) {
        titleTv.setText(title);
    }

    public void setDate(int year, int month, OnDateSetListener onDateSetListener) {
        Calendar calendar = Calendar.getInstance();
        datePicker.init(year, month, calendar.get(Calendar.DAY_OF_MONTH), this);
        this.onDateSetListener = onDateSetListener;
    }


    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.ok_btn) {
            dialog.dismiss();
            if (onDateSetListener != null) {
                datePicker.clearFocus();
                int year = datePicker.getYear();
                int month = datePicker.getMonth();
                int day = datePicker.getDayOfMonth();
                onDateSetListener.onDateSet(year, month + 1, day);
            }
        }
        if (v.getId() == R.id.cancel_btn) {
            dialog.dismiss();
        }
    }

    @Override
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        Calendar now = Calendar.getInstance();
        if (year > now.get(Calendar.YEAR) ||
                (year == now.get(Calendar.YEAR) && monthOfYear > now.get(Calendar.MONTH)) ||
                (year == now.get(Calendar.YEAR) && monthOfYear == now.get(Calendar.MONTH) && dayOfMonth > now.get(Calendar.DAY_OF_MONTH))) {
            // 如果选择了未来日期,则重置为当前日期
            datePicker.updateDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH));
        }
//        datePicker.init(year, monthOfYear, dayOfMonth, this);
    }

    public interface OnDateSetListener {
        void onDateSet(int year, int month, int day);
    }


    /**
     * 调整FrameLayout的大小
     */
    private void resizePicker(FrameLayout tp) {        //DatePicker和TimePicker继承自FrameLayout
        List<NumberPicker> npList = findNumberPicker(tp);  //找到组成的NumberPicker
        for (NumberPicker np : npList) {
            resizeNumberPicker(np);      //调整每个NumberPicker的宽度
        }
    }

    /**
     * 得到viewGroup 里面的numberpicker组件
     */
    private List<NumberPicker> findNumberPicker(ViewGroup viewGroup) {
        List<NumberPicker> npList = new ArrayList<NumberPicker>();
        View child = null;
        if (null != viewGroup) {
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                child = viewGroup.getChildAt(i);
                if (child instanceof NumberPicker) {
                    npList.add((NumberPicker) child);
                } else if (child instanceof LinearLayout) {
                    List<NumberPicker> result = findNumberPicker((ViewGroup) child);
                    if (!result.isEmpty()) {
                        return result;
                    }
                }
            }
        }
        return npList;
    }

    /**
     * 调整numberpicker大小
     */
    private void resizeNumberPicker(NumberPicker np) {
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(200, 220);
//        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(200, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.setMargins(20, 14, 20, 14);
        np.setLayoutParams(params);
    }

    /**
     * 设置时间选择器的分割线颜色
     *
     * @param datePicker
     */
    private void setDatePickerDividerColor(DatePicker datePicker) {
        // Divider changing:
        // 获取 mSpinners
        LinearLayout llFirst = (LinearLayout) datePicker.getChildAt(0);

        // 获取 CustomNumberPicker
        LinearLayout mSpinners = (LinearLayout) llFirst.getChildAt(0);
        for (int i = 0; i < mSpinners.getChildCount(); i++) {
            NumberPicker picker = (NumberPicker) mSpinners.getChildAt(i);
            picker.setSelectionDividerHeight(0);//设置分割线高度为0
            for (EditText editText : findEditText(picker)) {
                editText.setTextSize(32);
                resizeNumberPicker(picker);
                picker.setWrapSelectorWheel(true);
                picker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
                picker.setOnScrollListener((view, scrollState) -> {
                    view.performClick();//刷新选中状态
                });
            }

            //设置分割线颜色
            Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                pf.setAccessible(true);
                if (pf.getName().equals("mSelectionDivider")) {
                    try {
                        pf.set(picker, new ColorDrawable(Color.alpha(0)));设置分割线颜色
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
    }

    private List<EditText> findEditText(ViewGroup viewGroup) {
        List<EditText> npList = new ArrayList<>();
        View child = null;
        if (null != viewGroup) {
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                child = viewGroup.getChildAt(i);
                if (child instanceof EditText) {
                    npList.add((EditText) child);
                } else if (child instanceof LinearLayout) {
                    List<EditText> result = findEditText((ViewGroup) child);
                    if (!result.isEmpty()) {
                        return result;
                    }
                }
            }
        }
        return npList;
    }

    /**
     * 设置最大可选日期为当前日期
     *
     * @param datePicker
     */
    private void setMaxSelectableDate(DatePicker datePicker) {
        Calendar calendar = Calendar.getInstance();
        int currentYear = calendar.get(Calendar.YEAR);
        int currentMonth = calendar.get(Calendar.MONTH);
        int currentDay = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.set(currentYear,currentMonth,currentDay);
        long maxDate = calendar.getTimeInMillis();
        datePicker.setMaxDate(maxDate);
        datePicker.init(currentYear, currentMonth, currentDay, this);
     //设置最大时间为当前月
      datePicker.updateDate(currentYear,currentYear, currentYear);
    }

}
// dialog_time_warp片段
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="760dp"
            android:layout_height="wrap_content"
            android:background="@drawable/dialog_box"
            android:paddingBottom="48dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/type_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="32dp"
                android:gravity="center"
                android:text="请选择年月"
                android:textColor="@color/colorFFF"
                android:textSize="32sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <!--年月-->
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="80dp"
                android:layout_marginStart="50dp"
                android:layout_marginTop="182dp"
                android:layout_marginEnd="50dp"
                android:background="@drawable/service_item"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent">

                <androidx.appcompat.widget.AppCompatTextView
                    android:id="@+id/year_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="286dp"
                    android:gravity="center"
                    android:text="年"
                    android:textColor="@color/colorFFF"
                    android:textSize="32sp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

                <androidx.appcompat.widget.AppCompatTextView
                    android:id="@+id/month_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="184dp"
                    android:gravity="center"
                    android:text="月"
                    android:textColor="@color/colorFFF"
                    android:textSize="32sp"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintStart_toEndOf="@+id/year_text"
                    app:layout_constraintTop_toTopOf="parent" />

            </androidx.constraintlayout.widget.ConstraintLayout>

            <DatePicker
                android:id="@+id/datePicker"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="100dp"
                android:calendarViewShown="false"
                android:datePickerMode="spinner"
                android:spinnersShown="true"
                android:theme="@style/my_time_picker_style"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />


                <androidx.appcompat.widget.AppCompatButton
                    android:id="@+id/cancel_btn"
                    android:layout_width="312dp"
                    android:layout_height="80dp"
                    android:background="@drawable/cancel_btn"
                    android:gravity="center"
                    android:text="取消"
                    android:textColor="@color/color_cancel_txt"
                    android:textSize="28sp"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

  
                <androidx.appcompat.widget.AppCompatButton
                    android:id="@+id/ok_btn"
                    android:layout_width="312dp"
                    android:layout_height="80dp"
                    android:background="@drawable/ok_btn"
                    android:gravity="center"
                    android:text="确认"
                    android:textColor="@color/color_ok_txt"
                    android:textSize="28sp"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />

     
        </androidx.constraintlayout.widget.ConstraintLayout>

效果图如下所示:

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- ovod.cn 版权所有 湘ICP备2023023988号-4

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务