美文网首页
android DatePicker 自定义

android DatePicker 自定义

作者: 念念不忘_2016 | 来源:发表于2020-08-16 23:46 被阅读0次

本文解决了android 原生Datapicker无法改变文字大小的问题,通过反射实现 废话不多说,直接上代码

import android.app.Dialog;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Display;
import android.view.Gravity;
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 androidx.annotation.ColorInt;
import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.LogUtils;

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

/**
 * Created by chen
 * on Date: 2020/8/2
 * on Time: 20:24
 * on Describe:对 DatePicker 和 AlertDialog 包装生成的自定义 日期 选择器dialog
 */

public class CustomDatePickerAlertDialog {

    private final Context context;
    private final AlertDialog dialog;//dialog对象
    private View dialogView;         //dialogView
    private CustomDatepickerDialogAntBinding dialogBinding;
    private       int                              year;
    private       int                              month;
    private       int                              day;

    /**
     * @param context     上下文
     * @param year        年份,具体年份   (此处三个日期 同 Calendar 中取出的值)
     * @param monthOfYear 月份,取值 0-11
     * @param dayOfMonth  天,取值1-31
     */
    public CustomDatePickerAlertDialog(Context context, int year, int monthOfYear, int dayOfMonth) {
        this.context = context;
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        dialog = builder.create();

        initDate(year, monthOfYear, dayOfMonth);
        initDialogView();
    }

    /**
     * 初始化日期,如果外部在初始化传递的都是0 ,则使用该日期去初始化DatePicker
     *
     * @param year        年份,具体年份   (此处三个日期 同 Calendar 中取出的值)
     * @param monthOfYear 月份,取值 0-11
     * @param dayOfMonth  天,取值1-31
     */
    private void initDate(int year, int monthOfYear, int dayOfMonth) {
        if (year == 0 || dayOfMonth == 0) {
            Calendar calendar = Calendar.getInstance();
            year = calendar.get(Calendar.YEAR);
            month = calendar.get(Calendar.MONTH);   //取值 0-11
            day = calendar.get(Calendar.DAY_OF_MONTH);
        } else {
            this.year = year;
            month = monthOfYear;
            day = dayOfMonth;
        }
        LogUtils.e("初始化时的年月日是:", year + "/" + (month + 1) + "/" + day);
    }

    private void initDialogView() {
        LayoutInflater inflater = LayoutInflater.from(context);
        dialogBinding = DataBindingUtil.inflate(inflater, R.layout.custom_datepicker_dialog_ant, null, false);
        dialogView = dialogBinding.getRoot();
        dialog.setView(dialogView);     //设置view
        if (Build.VERSION.SDK_INT >= 21) {  //21之前设置背景的时候依旧会有白色边框
            setBackGroundDrawableResource(0);
        }
        setDimAmount(0.15f);

        initDatePicker();
    }

    private void initDatePicker() {

        DatePicker datePicker = dialogBinding.datePickerCustomDatePickerDialog;
        datePicker.init(year, month, day, new DatePicker.OnDateChangedListener() {
            @Override
            public void onDateChanged(DatePicker view, int selectedyear, int monthOfYear, int dayOfMonth) {
                year = selectedyear;
                month = monthOfYear;
                day = dayOfMonth;
                resizePikcer(view);
            }
        });
        resizePikcer(datePicker);
    }

    /**
     * 调整FrameLayout大小
     * @param tp
     */
    private void resizePikcer(FrameLayout tp){
        List<NumberPicker> npList = findNumberPicker(tp);
        for(NumberPicker np:npList){
            resizeNumberPicker(np);
            np.performClick();
        }
    }

    /**
     * 得到viewGroup里面的numberpicker组件
     * @param viewGroup
     * @return
     */
    private List<NumberPicker> findNumberPicker(ViewGroup viewGroup){
        List<NumberPicker> npList = new ArrayList<>();
        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.size()>0){
                        return result;
                    }
                }
            }
        }
        return npList;
    }

    /**
     * 调整numberpicker大小
     */
    private void resizeNumberPicker(NumberPicker np){
        setNumberPickerText(np);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ConvertUtils.dp2px(280)/3, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.setMargins(10, 0, 10, 0);
        np.setLayoutParams(params);
    }
    public EditText setNumberPickerText(NumberPicker numberPicker){
        Field field ;
        try{
            field = numberPicker.getClass().getDeclaredField("mInputText");
            field.setAccessible(true);
            try {
                ((EditText)field.get(numberPicker)).setTextSize(24);
                ((EditText)field.get(numberPicker)).setClickable(false);
                ((EditText)field.get(numberPicker)).setFocusable(false);
                return ((EditText)field.get(numberPicker));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 设置picker之间的间距
     */
    private void setPickerMargin(DatePicker picker) {
        LinearLayout.LayoutParams p= (LinearLayout.LayoutParams) picker.getLayoutParams();
        p.width = ConvertUtils.dp2px(280)/3;
        p.height =ConvertUtils.dp2px(30);
        p.setMargins(10,0,10,0);
        if(Build.VERSION.SDK_INT> Build.VERSION_CODES.JELLY_BEAN_MR1){
            p.setMarginStart(0);
            p.setMarginEnd(0);
        }
        picker.setLayoutParams(p);
    }


    /**
     * 展示dialog
     */
    public void show() {
        if (dialog != null && !dialog.isShowing()) {
            dialog.show();
        }
    }

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

    /**
     * 返回dialog的view对象
     */
    public View getDialogView() {
        return dialogView;
    }

    /**
     * 返回dialog对象
     */
    public Dialog getDialogObj() {
        return dialog;
    }

    /**
     * 设置dialog的背景--传入资源id
     */
    public void setBackGroundDrawableResource(int drawableResId) {
        Window window = dialog.getWindow();
        if (null != window) {
            if (0 == drawableResId) {
                drawableResId = R.mipmap.img_dialog;
            }
            window.setBackgroundDrawableResource(drawableResId);
        }
    }

    /**
     * 设置背景图--传入drawable对象
     */
    public void setBackGroundDrawable(Drawable drawable) {
        Window window = dialog.getWindow();
        if (null != window) {
            if (null == drawable) {
//                    drawable = context.getResources().getDrawable(R.drawable.shape_bk_rect_cornor_white);
            }
            window.setBackgroundDrawable(drawable);
        }
    }

    /**
     * 设置背景图--根据传入的color值生成对应填充色的圆角背景图
     *
     * @param colorInt      色值
     * @param conorRadiusPx 圆角半径,单位PX
     */
    public void setBackGroundDrawable(
            @ColorInt
                    int colorInt, int conorRadiusPx) {
        GradientDrawable drawable = new GradientDrawable();
        drawable.setColor(colorInt);
        drawable.setCornerRadius(conorRadiusPx);
        drawable.setShape(GradientDrawable.RECTANGLE);

        Window window = dialog.getWindow();
        if (null != window) {
            window.setBackgroundDrawable(drawable);
        }

    }

    /**
     * 设置确定按钮的问题及其点击事件,
     * 传入的事件监听为null时,会关闭dialog
     */
    public void setPositiveButton(String des, final AntDatePickerDialogClickListener clickListener) {
        dialogBinding.setIsConfirmBtShow(true);
        dialogBinding.btnConfirm.setText(des);
        dialogBinding.btnConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != clickListener) {
                    clickListener.onClick(v, year, month + 1, day);
                }
                dismissDialog();
            }
        });
    }

    public void setPositiveButton(int strResId, final AntDatePickerDialogClickListener clickListener) {
        dialogBinding.setIsConfirmBtShow(true);
        dialogBinding.btnConfirm.setText(context.getResources().getString(strResId));
        dialogBinding.btnConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != clickListener) {
                    clickListener.onClick(v, year, month + 1, day);
                }
                dismissDialog();
            }
        });
    }

    /**
     * 取消按钮的点击事件
     */
    public void setNegativeButton(String des, final AntDatePickerDialogClickListener clickListener) {
        dialogBinding.setIsCancleBtShow(true);
        dialogBinding.btnCancel.setText(des);
        dialogBinding.btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != clickListener) {
                    clickListener.onClick(v, year, month + 1, day);
                }
                dismissDialog();
            }
        });
    }

    public void setNegativeButton(int strResId, final AntDatePickerDialogClickListener clickListener) {
        dialogBinding.setIsCancleBtShow(true);
        dialogBinding.btnCancel.setText(context.getResources().getString(strResId));
        dialogBinding.btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != clickListener) {
                    clickListener.onClick(v, year, month + 1, day);
                }
                dismissDialog();
            }
        });
    }
    /**
     * 设置确认按钮的文字颜色
     */
    public void setPositiveButtonTextColor(
            @ColorInt
                    int color) {
        dialogBinding.btnConfirm.setTextColor(color);
    }

    public void setPositiveButtonTextColor(ColorStateList colorStateList) {
        dialogBinding.btnConfirm.setTextColor(colorStateList);
    }

    /**
     * 设置取消按钮的字体颜色
     */
    public void setNegativeButtonTextColor(
            @ColorInt
                    int color) {
        dialogBinding.btnCancel.setTextColor(color);
    }

    public void setNegativeButtonTextColor(ColorStateList colorStateList) {
        dialogBinding.btnCancel.setTextColor(colorStateList);
    }



    /**
     * 设置标题
     */
    public void setTitle(String title) {
        dialogBinding.setIsTitleShow(true);
        dialogBinding.tvTitle.setText(title);
    }

    public void setTitle(int strResId) {
        dialogBinding.setIsTitleShow(true);
        dialogBinding.tvTitle.setText(context.getResources().getString(strResId));
    }

    /**
     * 更改主标题文字的大小
     */
    public void setTitleTextSize(int sizeSP) {
        if (sizeSP <= 0) {
            sizeSP = 14;
        }
        dialogBinding.tvTitle.setTextSize(sizeSP);
    }

    /**
     * 修改Dialog阴影区域的灰度百分比
     * <p>
     * 取值 0-1.
     */
    public void setDimAmount(float rate) {
        Window window = dialog.getWindow();
        if (null != window) {
            if (rate < 0) {
                rate = 0;
            } else if (rate > 1) {
                rate = 1;
            }
            window.setDimAmount(rate);
        }
    }

    /**
     * 点击非内容区域是否可以关闭
     */
    public void setCancelable(boolean bool) {
        dialog.setCancelable(bool);
    }

    /**
     * 对外暴露点击事件的自定义接口
     */
    public interface AntDatePickerDialogClickListener {
        void onClick(View view, int selectedYear, int selectedMonth, int selectedDay);
    }
}

这里是布局文件

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="android.view.View"/>
        <variable name="isTitleShow" type="Boolean"/>
        <variable name="isSubTitleShow" type="Boolean"/>
        <variable name="isCancleBtShow" type="Boolean"/>
        <variable name="isConfirmBtShow" type="Boolean"/>
        <variable name="isSkipBtShow" type="Boolean"/>

    </data>

    <!--外面这层RL的实际作用是,让内部的LL布局参数生效,因为在填充布局时parent传递的null,所以被填充布局的第一层布局参数不生效,从第二层起才生效-->
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <LinearLayout
            android:id="@+id/ll_root_antDialog"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@mipmap/img_dialog"
            android:layout_centerInParent="true"
            android:orientation="vertical"
            android:showDividers="middle">

            <!--主标题-->
            <TextView
                android:id="@+id/tv_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:includeFontPadding="false"
                android:text="选择日期"
                android:padding="@dimen/dp_10"
                android:textColor="@color/white"
                android:textSize="23sp" />
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:background="@mipmap/ic_select_main_bg"
                android:layout_marginTop="20dp"
                android:orientation="vertical">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="28dp"
                    android:layout_marginLeft="20dp"
                    android:layout_marginRight="20dp"
                    android:orientation="horizontal">
                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:gravity="center"
                        android:textColor="@color/white"
                        android:textSize="16.67sp"
                        android:text="年"/>
                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:gravity="center"
                        android:textColor="@color/white"
                        android:textSize="16.67sp"
                        android:text="月"/>
                    <TextView
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:gravity="center"
                        android:textColor="@color/white"
                        android:textSize="16.67sp"
                        android:text="日"/>
                </LinearLayout>
                <DatePicker
                    android:id="@+id/datePicker_customDatePickerDialog"
                    style="@android:style/Widget.DatePicker"
                    android:layout_width="match_parent"
                    android:layout_height="96dp"
                    android:yearListSelectorColor="@color/light_gray"
                    android:calendarViewShown="false"
                    android:background="@color/white"
                    android:layout_marginLeft="@dimen/dp_10"
                    android:layout_marginRight="@dimen/dp_10"
                    android:datePickerMode="spinner"/>
            </LinearLayout>
            <!--底部按钮-->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:showDividers="middle"
                android:layout_marginTop="18dp"
                android:gravity="center_horizontal"
                android:visibility="@{isConfirmBtShow||isCancleBtShow?View.VISIBLE:View.GONE}">
                <top.jnsh.health.view.SoundButton
                    android:id="@+id/btn_confirm"
                    android:layout_width="129dp"
                    android:layout_height="45dp"
                    android:layout_gravity="center"
                    android:background="@drawable/select_confirm_btn_bg"
                    android:gravity="center"
                    android:text="确认"
                    android:textColor="@drawable/select_confirm_btn_text_bg"
                    android:textSize="18sp" />
                <top.jnsh.health.view.SoundButton
                    android:id="@+id/btn_cancel"
                    android:layout_width="129dp"
                    android:layout_height="45dp"
                    android:layout_gravity="center"
                    android:background="@drawable/select_confirm_btn_bg"
                    android:gravity="center"
                    android:layout_marginStart="22dp"
                    android:text="取消"
                    android:textColor="@drawable/select_confirm_btn_text_bg"
                    android:textSize="18sp" />
            </LinearLayout>

        </LinearLayout>
    </RelativeLayout>

</layout>

相关文章

  • android DatePicker 自定义

    本文解决了android 原生Datapicker无法改变文字大小的问题,通过反射实现 废话不多说,直接上代码 这...

  • datePicker android

    init 年月日 只是设定初始值 绘制View会根据初始值设置默认值 如果View已经绘制,只改变默认值,而不改变...

  • Android DatePicker

    前言 话说日期时间选择控件许多项目都会用到,今天小可不才,也发一个自己写的日期选择控件 先上图 1、首先自定义日期...

  • Android DatePicker的简单自定义

    最近因为需求做了一个简单的选择日期的demo,我们可以同android自带的DatePicker控件达到选择日期简...

  • 时间插件 jquery datepicker插件和boots

    datepicker插件: $( ".datepicker" ).datepicker({ showOtherMo...

  • vue自定义日期组件

    vue-datepicker 基于 vuejs 2.x 可自定义主题的日期组件 github DMOE Insta...

  • 自定义DatePicker

    首行为现在,当选择时间小于现在时间的时候,会自动滚回最小时间。 GitHub链接

  • android DatePicker属性

    android:calendarViewShown=”false” 是否显示日历视图android:firstDa...

  • JQuery插件:日历UI----datepicker

    一、调用datepicker的方法$('#date').datepicker();二、修改datepicker()...

  • Android自定义View

    Android自定义View 参考:从此再有不愁自定义View——Android自定义view详解android ...

网友评论

      本文标题:android DatePicker 自定义

      本文链接:https://www.haomeiwen.com/subject/hzxfjktx.html