Android之自定义时间选择弹框

文章目录


前言

随着产品人员不断变态下,总是会要求我们的界面高大上,随意UI能画出来我们就得搞出来才行,这里有自定义弹框,以及时间选择控件的运用,根据年和月判断当月有多少天,需要什么就copy什么。


一、效果图

二、实现步骤

1.自定义Dialog

代码如下(示例):

java 复制代码
package com.example.merchant.utils;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.NumberPicker;
import android.widget.TextView;

import com.example.merchant.R;

import java.util.Calendar;


/**
 * Created by :caoliulang
 * ❤
 * Creation time :2023/9/01
 * ❤
 * Function :日期选择弹框
 */
public class TiemDialog extends Dialog {
    Context context;
    MenuListener mMenuListener;
    View mRootView;
    private Animation mShowAnim;
    private Animation mDismissAnim;
    private boolean isDismissing;
    TextView cancle;//取消
    TextView confirm;//确定
    NumberPicker number_month;//月
    NumberPicker number_day;//天
    NumberPicker number_yer;//年
    Calendar calendar = Calendar.getInstance();//取得当前时间的年月日 时分秒

    public TiemDialog(Context context) {
        super(context, R.style.ActionSheetDialog);
        this.context = context;
        getWindow().setGravity(Gravity.BOTTOM);
        initView(context);
    }

    private void initView(final Context context) {
        mRootView = View.inflate(context, R.layout.time_dialog, null);
        cancle = mRootView.findViewById(R.id.cancle);
        confirm = mRootView.findViewById(R.id.confirm);
        number_month = mRootView.findViewById(R.id.number_month);
        number_day = mRootView.findViewById(R.id.number_day);
        number_yer = mRootView.findViewById(R.id.number_yer);
        // 设置年份范围
        int curYear = Calendar.getInstance().get(Calendar.YEAR);
        number_yer.setMinValue(curYear - 10);
        number_yer.setMaxValue(curYear + 10);
        number_yer.setValue(calendar.get(Calendar.YEAR));

        // 设置月份范围
//        String[] months = new String[]{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"};
//        monthPicker.setDisplayedValues(months);
        number_month.setMinValue(1);
        number_month.setMaxValue(12);
        number_month.setValue(calendar.get(Calendar.MONTH) + 1);

        // 设置天数范围
//        String[] day = new String[]{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"};
        int day = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        number_day.setMinValue(1);
        number_day.setMaxValue(getDayTS(getYear(), getMonths()));
        number_day.setValue(calendar.get(Calendar.DAY_OF_MONTH));

        // 设置滚动监听器 年
        number_yer.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                number_day.setMinValue(1);
                number_day.setMaxValue(getDayTS(getYear(), getMonths()));
            }
        });
        // 设置滚动监听器 月
        number_month.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                number_day.setMinValue(1);
                number_day.setMaxValue(getDayTS(getYear(), getMonths()));
            }
        });
        // 设置滚动监听器 日
        number_day.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            @Override
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
            }
        });

        confirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMenuListener.onSelect();
            }
        });
        cancle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cancel();
            }
        });

        this.setContentView(mRootView);
        initAnim(context);
        setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                if (mMenuListener != null) {
                    mMenuListener.onCancel();
                }
            }
        });

    }

    private void initAnim(Context context) {
        mShowAnim = AnimationUtils.loadAnimation(context, R.anim.translate_up);
        mDismissAnim = AnimationUtils.loadAnimation(context, R.anim.translate_down);
        mDismissAnim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                dismissMe();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }


    @Override
    public void show() {
        super.show();
        mRootView.startAnimation(mShowAnim);
    }

    @Override
    public void dismiss() {
        if (isDismissing) {
            return;
        }
        isDismissing = true;
        mRootView.startAnimation(mDismissAnim);
    }

    private void dismissMe() {
        super.dismiss();
        isDismissing = false;
    }

    public int getYear() {
        return number_yer.getValue();
    }

    public int getMonths() {
        return number_month.getValue();
    }

    public int getDay() {
        return number_day.getValue();
    }

    public MenuListener getMenuListener() {
        return mMenuListener;
    }

    public void setMenuListener(MenuListener menuListener) {
        mMenuListener = menuListener;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            dismiss();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    public interface MenuListener {
        void onCancel();

        void onSelect();
    }

    /**
     * 根据是否闰年和月份判断本月的天数
     *
     * @param year
     * @param month
     * @return
     */
    private int getDayTS(int year, int month) {
        int day = 30;
        boolean flag = false;
        switch (year % 4) {
            case 0:
                flag = true;
                break;
            default:
                flag = false;
                break;
        }
        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                day = 31;
                break;
            case 2:
                day = flag ? 29 : 28;
                break;
            default:
                day = 30;
                break;
        }
        return day;
    }
}

2.xml布局

代码如下(示例):

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <LinearLayout
        android:id="@+id/ll_share"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@drawable/bzhs_bff_8"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="17dp"
            android:text="Seleccionar fecha"
            android:textColor="#232323"
            android:textSize="16dp"
            android:textStyle="bold" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="240dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:orientation="horizontal">

            <NumberPicker
                android:id="@+id/number_month"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:theme="@style/DefaultNumberPickerTheme"
                android:layout_weight="1" />

            <NumberPicker
                android:id="@+id/number_day"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:theme="@style/DefaultNumberPickerTheme"
                android:layout_weight="1" />

            <NumberPicker
                android:id="@+id/number_yer"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:theme="@style/DefaultNumberPickerTheme"
                android:layout_weight="1" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="46dp"
            android:gravity="center"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/cancle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginRight="5dp"
                android:layout_weight="1"
                android:background="@drawable/bzhs_wls_4"
                android:gravity="center"
                android:text="Cancle"
                android:textColor="#333333"
                android:textSize="16dp" />

            <TextView
                android:id="@+id/confirm"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginLeft="5dp"
                android:layout_weight="1"
                android:background="@drawable/bzhs_qls_4"
                android:gravity="center"
                android:text="Confirm"
                android:textColor="#ffffff"
                android:textSize="16dp" />

        </LinearLayout>
    </LinearLayout>


</RelativeLayout>

3.背景白色转角drawable

代码如下(示例):

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 背景颜色 -->
    <solid android:color="#ffffff" />


    <!-- 控制圆角大小 -->
    <corners android:topRightRadius="8dp"
        android:topLeftRadius="8dp"/>

</shape>

4.取消按钮背景drawable

代码如下(示例):

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 背景颜色 -->
    <solid android:color="#ffffff" />

    <!-- 控制边界线颜色和大小 -->
    <stroke
        android:width="1dp"
        android:color="#006FF0" />

    <!-- 控制圆角大小 -->
    <corners android:radius="4dp" />

</shape>

5.确定按钮背景drawable

代码如下(示例):

java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 背景颜色 -->
    <solid android:color="#006FF0" />

    <!-- 控制边界线颜色和大小 -->
    <stroke
        android:width="1dp"
        android:color="#006FF0" />

    <!-- 控制圆角大小 -->
    <corners android:radius="4dp" />

</shape>

6.NumberPicker样式和弹框样式

代码如下(示例):

java 复制代码
  <style name="DefaultNumberPickerTheme" parent="AppTheme">
        <item name="colorControlNormal">@color/dividerColor</item>
    </style>

 <style name="ActionSheetDialog" parent="android:Theme.Dialog">
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowBackground">#00000000</item>
        <item name="android:windowNoTitle">true</item>
    </style>

7.弹框动画

kotlin 复制代码
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:fromYDelta="100%"
           android:toYDelta="0"
           android:duration="250">
</translate>

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
           android:fromYDelta="0%"
           android:toYDelta="100%"
           android:duration="250">
</translate>

8.Activity使用

kotlin 复制代码
//定义变量
private lateinit var timedialog: TiemDialog//日期选择弹框
//实例化
timedialog = TiemDialog(this)
//调用
showTimeDailog()
//方法
 /**
     * 日期弹框
     */
    private fun showTimeDailog() {
        val window: Window = timedialog.window!!
        val lp = window.attributes
        //这句就是设置dialog横向满屏了。
        lp.width = WindowManager.LayoutParams.MATCH_PARENT
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT
        window.attributes = lp
        timedialog.show()
        timedialog.setCanceledOnTouchOutside(false)
        timedialog.menuListener = object : TiemDialog.MenuListener {
            //取消
            override fun onCancel() {
                timedialog.dismiss()
            }

            //确定
            override fun onSelect() {
                if (timedialog != null) {
                    text_time.text = "${timedialog.year}-${timedialog.months}-${timedialog.day}"
                    timedialog.dismiss()
                }
            }

        }
    }

总结

东西看起来多,也就两个模块,一个是自定义Dialog,一个NumberPicker的使用,欢迎随时探讨。