Android 选择生日dialog

效果图

 dialog 创建和使用。

首先是使用

class MainActivity : AppCompatActivity() {

    private var birthday = "2020-12-6"

    private val dialog by lazy {
        SelectBirthdayDialog(this)
    }

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        dialog.setDefaultData(birthday)
        hello_world.setOnClickListener {
            dialog.setDefaultData(birthday)
            dialog.setOnDismissListener {
                run {

                }
            }
            dialog.setOnSelectBirthdayLinsener { yearData, monthData, dayData ->
                birthday = yearData.value + "-" + monthData.value + "-" + dayData.value
                hello_world.text = "选择的出生日期为:$birthday"
                dialog.dismiss()
            }
            dialog.show()
        }
    }
}
SelectBirthdayDialog 创建 集成dialog,让它从底部弹起设置
getWindow().setGravity(Gravity.BOTTOM);
getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

为了保证空白地方空白,设置主题

<style name="select_birthday_dialog" parent="@android:style/Theme.Dialog">
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:backgroundDimAmount">0.6</item>
</style>

这样设置为

public SelectBirthdayDialog(@NonNull Context context) {
    super(context, R.style.select_birthday_dialog);
    setContentView(R.layout.select_brithday_dialog);
    getWindow().setGravity(Gravity.BOTTOM);
    getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}

这里 的layout 就是独立的ui 了。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_cancel"
            android:layout_width="44dp"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:focusable="true"
            android:gravity="center"
            android:text="取消"
            android:textColor="@color/txt_color_selected"
            android:textSize="13sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:text="选择出生日期"
            android:textColor="@color/txt_color_selected"
            android:textSize="13sp" />

        <TextView
            android:id="@+id/tv_confirm"
            android:layout_width="44dp"
            android:layout_height="44dp"
            android:gravity="center"
            android:text="确定"
            android:textColor="@color/bt_color_determine"
            android:textSize="13sp" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:background="@color/white"
        android:orientation="horizontal">

        <optimistic.developers.select_birthday.view.WheelView
            android:id="@+id/wheelview1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <optimistic.developers.select_birthday.view.WheelView
            android:id="@+id/wheelview2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <optimistic.developers.select_birthday.view.WheelView
            android:id="@+id/wheelview3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />

    </LinearLayout>
</LinearLayout>
SelectBirthdayDialog主要是生日的计算了。

通过年的时间段,来确定,最低年份和当前的时间段,然后计算出现在的月份和日份,主要是闰年、31天30天28天29天计算和查看。

然后再把数据加载到

wheelView中去。
wheelView 是自定义一个2d效果的滑轮效果的展示控件。

这里有一个接口

public interface IWheelEntity {

    /**
     * 获取 wheel text
     *
     * @return WheelView text
     */
    String getWheelText();
}

是为了动态展示当前要展示的数据。

WheelView 是被人写的开源控件,我按照我的理解解读一下。

先看 初始化那些公开熟悉吧,一般是 attrs 里面

/**
 * 初始化自定义属性及默认值
 *
 * @param context 上下文
 * @param attrs   attrs
 */
private void initAttrsAndDefault(Context context, AttributeSet attrs) {
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WheelView);
    mTextSize = typedArray.getDimension(R.styleable.WheelView_wv_textSize, DEFAULT_TEXT_SIZE);
    isAutoFitTextSize = typedArray.getBoolean(R.styleable.WheelView_wv_autoFitTextSize, false);
    mTextAlign = typedArray.getInt(R.styleable.WheelView_wv_textAlign, TEXT_ALIGN_CENTER);
    mTextBoundaryMargin = typedArray.getDimension(R.styleable.WheelView_wv_textBoundaryMargin,
            DEFAULT_TEXT_BOUNDARY_MARGIN);
    mTextColor = typedArray.getColor(R.styleable.WheelView_wv_normalItemTextColor, DEFAULT_NORMAL_TEXT_COLOR);
    mSelectedItemTextColor = typedArray.getColor(R.styleable.WheelView_wv_selectedItemTextColor, DEFAULT_SELECTED_TEXT_COLOR);
    mLineSpacing = typedArray.getDimension(R.styleable.WheelView_wv_lineSpacing, DEFAULT_LINE_SPACING);
    isIntegerNeedFormat = typedArray.getBoolean(R.styleable.WheelView_wv_integerNeedFormat, false);
    mIntegerFormat = typedArray.getString(R.styleable.WheelView_wv_integerFormat);
    if (TextUtils.isEmpty(mIntegerFormat)) {
        mIntegerFormat = DEFAULT_INTEGER_FORMAT;
    }

    mVisibleItems = typedArray.getInt(R.styleable.WheelView_wv_visibleItems, DEFAULT_VISIBLE_ITEM);
    //跳转可见item为奇数
    mVisibleItems = adjustVisibleItems(mVisibleItems);
    mSelectedItemPosition = typedArray.getInt(R.styleable.WheelView_wv_selectedItemPosition, 0);
    //初始化滚动下标
    mCurrentScrollPosition = mSelectedItemPosition;
    isCyclic = typedArray.getBoolean(R.styleable.WheelView_wv_cyclic, false);

    isShowDivider = typedArray.getBoolean(R.styleable.WheelView_wv_showDivider, false);
    mDividerType = typedArray.getInt(R.styleable.WheelView_wv_dividerType, DIVIDER_TYPE_FILL);
    mDividerSize = typedArray.getDimension(R.styleable.WheelView_wv_dividerHeight, DEFAULT_DIVIDER_HEIGHT);
    mDividerColor = typedArray.getColor(R.styleable.WheelView_wv_dividerColor, DEFAULT_SELECTED_TEXT_COLOR);
    mDividerPaddingForWrap = typedArray.getDimension(R.styleable.WheelView_wv_dividerPaddingForWrap, DEFAULT_TEXT_BOUNDARY_MARGIN);

    mDividerOffset = typedArray.getDimensionPixelOffset(R.styleable.WheelView_wv_dividerOffset, 0);

    isDrawSelectedRect = typedArray.getBoolean(R.styleable.WheelView_wv_drawSelectedRect, false);
    mSelectedRectColor = typedArray.getColor(R.styleable.WheelView_wv_selectedRectColor, Color.TRANSPARENT);

    isCurved = typedArray.getBoolean(R.styleable.WheelView_wv_curved, true);
    mCurvedArcDirection = typedArray.getInt(R.styleable.WheelView_wv_curvedArcDirection, CURVED_ARC_DIRECTION_CENTER);
    mCurvedArcDirectionFactor = typedArray.getFloat(R.styleable.WheelView_wv_curvedArcDirectionFactor, DEFAULT_CURVED_FACTOR);
    //折射偏移默认值
    //Deprecated 将在新版中移除
    float curvedRefractRatio = typedArray.getFloat(R.styleable.WheelView_wv_curvedRefractRatio, 0.9f);
    mRefractRatio = typedArray.getFloat(R.styleable.WheelView_wv_refractRatio, DEFAULT_REFRACT_RATIO);
    mRefractRatio = isCurved ? Math.min(curvedRefractRatio, mRefractRatio) : mRefractRatio;
    if (mRefractRatio > 1f) {
        mRefractRatio = 1.0f;
    } else if (mRefractRatio < 0f) {
        mRefractRatio = DEFAULT_REFRACT_RATIO;
    }
    typedArray.recycle();
}

这样的先不关他这样做如何去公开设置这些属性。

onMeasure 和 onDraw 两个方法 是画线和控件的主要部分了。

绘制主要看canvas这些函数

canvas.save();
canvas.clipRect(mClipLeft, clipTop, mClipRight, clipBottom);
canvas.drawRect()
canvas.drawText(text, 0, text.length(), mStartX, mCenterY + item2CenterOffsetY - centerToBaselineY, mPaint);
canvas.restore();

这么快函数用这个一个就可以了,确定第一个和最后一个位置,然后循环处理。

中间线是俩个固定位置的线

/**
 * 绘制分割线
 *
 * @param canvas 画布
 */
private void drawDivider(Canvas canvas) {
    if (isShowDivider) {
        mPaint.setColor(mDividerColor);
        float originStrokeWidth = mPaint.getStrokeWidth();
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(mDividerSize);
        if (mDividerType == DIVIDER_TYPE_FILL) {
            canvas.drawLine(mClipLeft, mSelectedItemTopLimit, mClipRight, mSelectedItemTopLimit, mPaint);
            canvas.drawLine(mClipLeft, mSelectedItemBottomLimit, mClipRight, mSelectedItemBottomLimit, mPaint);
        } else {
            //边界处理 超过边界直接按照DIVIDER_TYPE_FILL类型处理
            int startX = (int) (mCenterX - mMaxTextWidth / 2 - mDividerPaddingForWrap);
            int stopX = (int) (mCenterX + mMaxTextWidth / 2 + mDividerPaddingForWrap);

            int wrapStartX = Math.max(startX, mClipLeft);
            int wrapStopX = Math.min(stopX, mClipRight);
            canvas.drawLine(wrapStartX, mSelectedItemTopLimit, wrapStopX, mSelectedItemTopLimit, mPaint);
            canvas.drawLine(wrapStartX, mSelectedItemBottomLimit, wrapStopX, mSelectedItemBottomLimit, mPaint);
        }
        mPaint.setStrokeWidth(originStrokeWidth);
    }
}

源码地址

https://download.csdn.net/download/OptimisticDevelo/87246799

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值