Android 仿ios四级联动地址选择器

效果图


序言

    如果只需要三级联动目前有现成的库可以使用,但是呢目前需求是需要四级地址选择,没办法只能自己写一个基于Android-PickerView库作为拓展,废话不多说,下面开始贴代码

导入包
api 'com.contrarywind:Android-PickerView:4.1.9'
布局

pv_addressview_options.xml

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

    <include
        layout="@layout/include_pickerview_topbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/pickerview_topbar_height" />

    <LinearLayout
        android:id="@+id/optionspicker"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        android:gravity="center"
        android:minHeight="180dp"
        android:orientation="horizontal">

        <com.contrarywind.view.WheelView
            android:id="@+id/my_address_options1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <com.contrarywind.view.WheelView
            android:id="@+id/my_address_options2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <com.contrarywind.view.WheelView
            android:id="@+id/my_address_options3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <com.contrarywind.view.WheelView
            android:id="@+id/my_address_options4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>
</LinearLayout>
代码
  1. listener/OnAddressOptionsSelectChangeListener.kt
package org.fyc.publib.diyPickerview.listener

/**
 * 地址 - 四级联动
 */
interface OnAddressOptionsSelectChangeListener {
    fun onOptionsSelectChanged(options1: Int, options2: Int, options3: Int, options4: Int)
}
  1. options/MyPickerOptions.kt
package org.fyc.publib.diyPickerview.options

import com.bigkoo.pickerview.configure.PickerOptions
import org.fyc.publib.diyPickerview.R
import org.fyc.publib.diyPickerview.listener.OnAddressOptionsSelectChangeListener

class MyPickerOptions(buildType: Int): PickerOptions(buildType) {

    val TAG_SUBMIT = "submit"
    val TAG_CANCEL = "cancel"

    var label4: String = ""
    var option4 = 0 //默认选中项
    var x_offset_four = 0//x轴偏移量
    var cyclic4 = false

    init {
        if (buildType == TYPE_PICKER_OPTIONS) {
            layoutRes = R.layout.pv_addressview_options
        }
    }

    var optionsAddSelectChangeListener: OnAddressOptionsSelectChangeListener? = null
}
  1. options/MyAddressWheelOptions.kt
package org.fyc.publib.diyPickerview.options

import android.graphics.Typeface
import android.view.View
import com.bigkoo.pickerview.adapter.ArrayWheelAdapter
import com.contrarywind.listener.OnItemSelectedListener
import com.contrarywind.view.WheelView
import com.contrarywind.view.WheelView.DividerType
import org.fyc.publib.diyPickerview.R
import org.fyc.publib.diyPickerview.listener.OnAddressOptionsSelectChangeListener

// isRestoreItem - 切换时,还原第一项
class MyAddressWheelOptions<T>(private val view: View, private val isRestoreItem: Boolean) {
    private val wv_option1: WheelView = view.findViewById(R.id.my_address_options1)
    private val wv_option2: WheelView = view.findViewById(R.id.my_address_options2)
    private val wv_option3: WheelView = view.findViewById(R.id.my_address_options3)
    private val wv_option4: WheelView = view.findViewById(R.id.my_address_options4)

    private var mOptions1Items: List<T>? = null
    private var mOptions2Items: List<List<T>>? = null
    private var mOptions3Items: List<List<List<T>>>? = null
    private var mOptions4Items: List<List<List<List<T>>>>? = null

    private var linkage = true //默认联动
    private var isSelectCallback = true // 是否选中回调,默认回调

    private var wheelListener_option1: OnItemSelectedListener? = null
    private var wheelListener_option2: OnItemSelectedListener? = null
    private var wheelListener_option3: OnItemSelectedListener? = null
    private var optionsSelectChangeListener: OnAddressOptionsSelectChangeListener? = null

    fun setPicker(
        options1Items: List<T>?,
        options2Items: List<List<T>>?,
        options3Items: List<List<List<T>>>?,
        options4Items: List<List<List<List<T>>>>?
    ) {
        mOptions1Items = options1Items
        mOptions2Items = options2Items
        mOptions3Items = options3Items
        mOptions4Items = options4Items

        // 选项1
        wv_option1.adapter = ArrayWheelAdapter(mOptions1Items) // 设置显示数据
        wv_option1.currentItem = 0 // 初始化时显示的数据
        // 选项2
        if (mOptions2Items != null) {
            wv_option2.adapter = ArrayWheelAdapter(mOptions2Items!![0]) // 设置显示数据
        }
        wv_option2.currentItem = wv_option2.currentItem // 初始化时显示的数据
        // 选项3
        if (mOptions3Items != null) {
            wv_option3.adapter = ArrayWheelAdapter(mOptions3Items!![0][0]) // 设置显示数据
        }
        wv_option3.currentItem = wv_option3.currentItem
        // 选项4
        if (mOptions4Items != null) {
            wv_option4.adapter = ArrayWheelAdapter(mOptions4Items!![0][0][0]) // 设置显示数据
        }
        wv_option4.currentItem = wv_option4.currentItem

        wv_option1.setIsOptions(true)
        wv_option2.setIsOptions(true)
        wv_option3.setIsOptions(true)
        wv_option4.setIsOptions(true)

        if (mOptions2Items == null) {
            wv_option2.visibility = View.GONE
        } else {
            wv_option2.visibility = View.VISIBLE
        }
        if (mOptions3Items == null) {
            wv_option3.visibility = View.GONE
        } else {
            wv_option3.visibility = View.VISIBLE
        }
        if (mOptions4Items == null) {
            wv_option4.visibility = View.GONE
        } else {
            wv_option4.visibility = View.VISIBLE
        }

        // 联动监听器
        wheelListener_option1 =  OnItemSelectedListener { index ->
            if (mOptions2Items != null) {
                // 滑动一级默认,选中第一项
                wv_option2.adapter =
                    ArrayWheelAdapter(mOptions2Items!![index])
                wv_option2.currentItem = 0

                // 关联设置三、四级
                if (mOptions3Items != null) {
                    wv_option3.adapter =
                        ArrayWheelAdapter(mOptions3Items!![index][0])
                    wv_option3.currentItem = 0
                }
                if (mOptions4Items != null) {
                    wv_option4.adapter =
                        ArrayWheelAdapter(mOptions4Items!![index][0][0])
                    wv_option4.currentItem = 0
                }
            }

            if (optionsSelectChangeListener != null && isSelectCallback) {
                optionsSelectChangeListener!!.onOptionsSelectChanged(
                    index, 0, 0, 0
                )
            }
        }

        wheelListener_option2 = OnItemSelectedListener { index ->
            if (mOptions3Items != null) {
                // 滑动二级默认,选中第一项
                wv_option3.adapter =
                    ArrayWheelAdapter(mOptions3Items!![wv_option1.currentItem][index])
                wv_option3.currentItem = 0
                // 设置默认4级
                if (mOptions4Items != null) {
                    wv_option4.adapter =
                        ArrayWheelAdapter(mOptions4Items!![wv_option1.currentItem][index][0])
                    wv_option4.currentItem = 0
                }
            }

            // 联动数据实时回调
            if (optionsSelectChangeListener != null && isSelectCallback) {
                optionsSelectChangeListener!!.onOptionsSelectChanged(
                    wv_option1.currentItem, index, 0, 0
                )
            }
        }

        wheelListener_option3 = OnItemSelectedListener { index ->
            if (mOptions4Items != null) {
                // 滑动三级默认,选中第一项
                wv_option4.adapter =
                    ArrayWheelAdapter(mOptions4Items!![wv_option1.currentItem][wv_option2.currentItem][index])
                wv_option4.currentItem = 0
            }

            // 联动数据实时回调
            if (optionsSelectChangeListener != null && isSelectCallback) {
                optionsSelectChangeListener!!.onOptionsSelectChanged(
                    wv_option1.currentItem, wv_option2.currentItem, index, 0
                )
            }
        }

        // 添加联动监听
        if (linkage) {
            wv_option1.setOnItemSelectedListener(wheelListener_option1)
            wv_option2.setOnItemSelectedListener(wheelListener_option2)
            wv_option3.setOnItemSelectedListener(wheelListener_option3)

            if (optionsSelectChangeListener != null && isSelectCallback) {
                wv_option4.setOnItemSelectedListener { index ->
                    optionsSelectChangeListener!!.onOptionsSelectChanged(
                        wv_option1.currentItem,
                        wv_option2.currentItem,
                        wv_option3.currentItem,
                        index
                    )
                }
            }
        }
    }

    // 不联动情况下
    fun setNPicker(
        options1Items: List<T>?,
        options2Items: List<T>?,
        options3Items: List<T>?,
        options4Items: List<T>?
    ) {
        // 选项1
        wv_option1.adapter = ArrayWheelAdapter(options1Items) // 设置显示数据
        wv_option1.currentItem = 0 // 初始化时显示的数据
        // 选项2
        if (options2Items != null) {
            wv_option2.adapter = ArrayWheelAdapter(options2Items) // 设置显示数据
        }
        wv_option2.currentItem = wv_option2.currentItem // 初始化时显示的数据
        // 选项3
        if (options3Items != null) {
            wv_option3.adapter = ArrayWheelAdapter(options3Items) // 设置显示数据
        }
        wv_option3.currentItem = wv_option3.currentItem
        // 选项4
        if (options4Items != null) {
            wv_option4.adapter = ArrayWheelAdapter(options4Items) // 设置显示数据
        }
        wv_option4.currentItem = wv_option4.currentItem

        wv_option1.setIsOptions(true)
        wv_option2.setIsOptions(true)
        wv_option3.setIsOptions(true)
        wv_option4.setIsOptions(true)

        optionsSelectChangeListener?.let {
            wv_option1.setOnItemSelectedListener { index ->
                optionsSelectChangeListener!!.onOptionsSelectChanged(
                    index,
                    wv_option2.currentItem,
                    wv_option3.currentItem,
                    wv_option4.currentItem
                )
            }
        }

        if (options2Items == null) {
            wv_option2.visibility = View.GONE
        } else {
            wv_option2.visibility = View.VISIBLE
            if (optionsSelectChangeListener != null) {
                wv_option2.setOnItemSelectedListener { index ->
                    optionsSelectChangeListener!!.onOptionsSelectChanged(
                        wv_option1.currentItem,
                        index,
                        wv_option3.currentItem,
                        wv_option4.currentItem
                    )
                }
            }
        }
        if (options3Items == null) {
            wv_option3.visibility = View.GONE
        } else {
            wv_option3.visibility = View.VISIBLE
            if (optionsSelectChangeListener != null) {
                wv_option3.setOnItemSelectedListener { index ->
                    optionsSelectChangeListener!!.onOptionsSelectChanged(
                        wv_option1.currentItem,
                        wv_option2.currentItem,
                        index,
                        wv_option4.currentItem,
                    )
                }
            }
        }

        if (options4Items == null) {
            wv_option4.visibility = View.GONE
        } else {
            wv_option4.visibility = View.VISIBLE
            if (optionsSelectChangeListener != null) {
                wv_option4.setOnItemSelectedListener { index ->
                    optionsSelectChangeListener!!.onOptionsSelectChanged(
                        wv_option1.currentItem,
                        wv_option2.currentItem,
                        wv_option3.currentItem,
                        index,
                    )
                }
            }
        }
    }

    fun setTextContentSize(textSize: Int) {
        wv_option1.setTextSize(textSize.toFloat())
        wv_option2.setTextSize(textSize.toFloat())
        wv_option3.setTextSize(textSize.toFloat())
        wv_option4.setTextSize(textSize.toFloat())
    }

    /**
     * 设置选项的单位
     *
     * @param label1 单位
     * @param label2 单位
     * @param label3 单位
     * @param label4 单位
     */
    fun setLabels(label1: String?, label2: String?, label3: String?, label4: String?) {
        if (label1 != null) {
            wv_option1.setLabel(label1)
        }
        if (label2 != null) {
            wv_option2.setLabel(label2)
        }
        if (label3 != null) {
            wv_option3.setLabel(label3)
        }
        if (label4 != null) {
            wv_option4.setLabel(label4)
        }
    }

    /**
     * 设置x轴偏移量
     */
    fun setTextXOffset(
        x_offset_one: Int,
        x_offset_two: Int,
        x_offset_three: Int,
        x_offset_four: Int
    ) {
        wv_option1.setTextXOffset(x_offset_one)
        wv_option2.setTextXOffset(x_offset_two)
        wv_option3.setTextXOffset(x_offset_three)
        wv_option4.setTextXOffset(x_offset_four)
    }

    /**
     * 设置是否循环滚动
     *
     * @param cyclic 是否循环
     */
    fun setCyclic(cyclic: Boolean) {
        wv_option1.setCyclic(cyclic)
        wv_option2.setCyclic(cyclic)
        wv_option3.setCyclic(cyclic)
        wv_option4.setCyclic(cyclic)
    }

    /**
     * 设置字体样式
     *
     * @param font 系统提供的几种样式
     */
    fun setTypeface(font: Typeface?) {
        wv_option1.setTypeface(font)
        wv_option2.setTypeface(font)
        wv_option3.setTypeface(font)
        wv_option4.setTypeface(font)
    }

    /**
     * 分别设置第一二三级是否循环滚动
     *
     * @param cyclic1,cyclic2,cyclic3 是否循环
     */
    fun setCyclic(cyclic1: Boolean, cyclic2: Boolean, cyclic3: Boolean, cyclic4: Boolean) {
        wv_option1.setCyclic(cyclic1)
        wv_option2.setCyclic(cyclic2)
        wv_option3.setCyclic(cyclic3)
        wv_option4.setCyclic(cyclic4)
    }

    /**
     * 返回当前选中的结果对应的位置数组 因为支持三级联动效果,分三个级别索引,0,1,2。
     * 在快速滑动未停止时,点击确定按钮,会进行判断,如果匹配数据越界,则设为0,防止index出错导致崩溃。
     *
     * @return 索引数组
     */
    fun getCurrentItems(): IntArray {
        val currentItems = IntArray(4)
        currentItems[0] = wv_option1.currentItem
        if (!mOptions2Items.isNullOrEmpty()) { //非空判断
            currentItems[1] =
                if (wv_option2.currentItem > mOptions2Items!![currentItems[0]].size - 1) 0 else wv_option2.currentItem
        } else {
            currentItems[1] = wv_option2.currentItem
        }
        if (!mOptions3Items.isNullOrEmpty()) { //非空判断
            currentItems[2] =
                if (wv_option3.currentItem > mOptions3Items!![currentItems[0]][currentItems[1]].size - 1) 0 else wv_option3.currentItem
        } else {
            currentItems[2] = wv_option3.currentItem
        }
        if (!mOptions4Items.isNullOrEmpty()) { //非空判断
            currentItems[3] =
                if (wv_option4.currentItem > mOptions4Items!![currentItems[0]][currentItems[1]][currentItems[2]].size - 1) 0 else wv_option4.currentItem
        } else {
            currentItems[3] = wv_option4.currentItem
        }
        return currentItems
    }

    fun setCurrentItems(option1: Int, option2: Int, option3: Int, option4: Int) {
        if (linkage) {
            itemSelected(option1, option2, option3, option4)
        } else {
            wv_option1.currentItem = option1
            wv_option2.currentItem = option2
            wv_option3.currentItem = option3
            wv_option4.currentItem = option4
        }
    }

    private fun itemSelected(opt1Select: Int, opt2Select: Int, opt3Select: Int, opt4Select: Int) {
        if (mOptions1Items != null) {
            wv_option1.currentItem = opt1Select
        }
        if (mOptions2Items != null) {
            wv_option2.adapter = ArrayWheelAdapter(mOptions2Items!![opt1Select])
            wv_option2.currentItem = opt2Select
        }
        if (mOptions3Items != null) {
            wv_option3.adapter = ArrayWheelAdapter(mOptions3Items!![opt1Select][opt2Select])
            wv_option3.currentItem = opt3Select
        }
        if (mOptions4Items != null) {
            wv_option4.adapter =
                ArrayWheelAdapter(mOptions4Items!![opt1Select][opt2Select][opt3Select])
            wv_option4.currentItem = opt4Select
        }
    }

    /**
     * 设置间距倍数,但是只能在1.2-4.0f之间
     *
     * @param lineSpacingMultiplier
     */
    fun setLineSpacingMultiplier(lineSpacingMultiplier: Float) {
        wv_option1.setLineSpacingMultiplier(lineSpacingMultiplier)
        wv_option2.setLineSpacingMultiplier(lineSpacingMultiplier)
        wv_option3.setLineSpacingMultiplier(lineSpacingMultiplier)
        wv_option4.setLineSpacingMultiplier(lineSpacingMultiplier)
    }

    /**
     * 设置分割线的颜色
     *
     * @param dividerColor
     */
    fun setDividerColor(dividerColor: Int) {
        wv_option1.setDividerColor(dividerColor)
        wv_option2.setDividerColor(dividerColor)
        wv_option3.setDividerColor(dividerColor)
        wv_option4.setDividerColor(dividerColor)
    }

    /**
     * 设置分割线的类型
     *
     * @param dividerType
     */
    fun setDividerType(dividerType: DividerType?) {
        wv_option1.setDividerType(dividerType)
        wv_option2.setDividerType(dividerType)
        wv_option3.setDividerType(dividerType)
        wv_option4.setDividerType(dividerType)
    }

    /**
     * 设置分割线之间的文字的颜色
     *
     * @param textColorCenter
     */
    fun setTextColorCenter(textColorCenter: Int) {
        wv_option1.setTextColorCenter(textColorCenter)
        wv_option2.setTextColorCenter(textColorCenter)
        wv_option3.setTextColorCenter(textColorCenter)
        wv_option4.setTextColorCenter(textColorCenter)
    }

    /**
     * 设置分割线以外文字的颜色
     *
     * @param textColorOut
     */
    fun setTextColorOut(textColorOut: Int) {
        wv_option1.setTextColorOut(textColorOut)
        wv_option2.setTextColorOut(textColorOut)
        wv_option3.setTextColorOut(textColorOut)
        wv_option4.setTextColorOut(textColorOut)
    }

    /**
     * Label 是否只显示中间选中项的
     *
     * @param isCenterLabel
     */
    fun isCenterLabel(isCenterLabel: Boolean) {
        wv_option1.isCenterLabel(isCenterLabel)
        wv_option2.isCenterLabel(isCenterLabel)
        wv_option3.isCenterLabel(isCenterLabel)
        wv_option4.isCenterLabel(isCenterLabel)
    }

    fun setOptionsSelectChangeListener(optionsSelectChangeListener: OnAddressOptionsSelectChangeListener?) {
        this.optionsSelectChangeListener = optionsSelectChangeListener
    }

    // 是否联动,默认联动
    fun setLinkage(linkage: Boolean) {
        this.linkage = linkage
    }

    // 是否选中回调,默认回调
    fun setSelectCallback(isSelectCallback: Boolean) {
        this.isSelectCallback = isSelectCallback
    }

    /**
     * 设置最大可见数目
     *
     * @param itemsVisible 建议设置为 3 ~ 9之间。
     */
    fun setItemsVisible(itemsVisible: Int) {
        wv_option1.setItemsVisibleCount(itemsVisible)
        wv_option2.setItemsVisibleCount(itemsVisible)
        wv_option3.setItemsVisibleCount(itemsVisible)
        wv_option4.setItemsVisibleCount(itemsVisible)
    }

    fun setAlphaGradient(isAlphaGradient: Boolean) {
        wv_option1.setAlphaGradient(isAlphaGradient)
        wv_option2.setAlphaGradient(isAlphaGradient)
        wv_option3.setAlphaGradient(isAlphaGradient)
        wv_option4.setAlphaGradient(isAlphaGradient)
    }
}
  1. view/MyAddressOptionsPickerView.kt
package org.fyc.publib.diyPickerview.view

import android.content.Context
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import com.bigkoo.pickerview.view.BasePickerView
import org.fyc.publib.diyPickerview.R
import org.fyc.publib.diyPickerview.options.MyAddressWheelOptions
import org.fyc.publib.diyPickerview.options.MyPickerOptions

/**
 * 地址条件选择器
 */
class MyAddressOptionsPickerView<T>(private val pickerOptions: MyPickerOptions): BasePickerView(pickerOptions.context), View.OnClickListener {

    private var wheelOptions: MyAddressWheelOptions<T>? = null

    init {
        mPickerOptions = pickerOptions
        initView(pickerOptions.context)
    }

    private fun initView(context: Context) {
        setDialogOutSideCancelable()
        initViews()
        initAnim()
        initEvents()

        if (pickerOptions.customListener == null) {
            LayoutInflater.from(context).inflate(pickerOptions.layoutRes, contentContainer)

            //顶部标题
            val tvTitle = findViewById(R.id.tvTitle) as TextView
            val rv_top_bar = findViewById(R.id.rv_topbar) as RelativeLayout

            //确定和取消按钮
            val btnSubmit = findViewById(R.id.btnSubmit) as Button
            val btnCancel = findViewById(R.id.btnCancel) as Button

            btnSubmit.tag = pickerOptions.TAG_SUBMIT
            btnCancel.tag = pickerOptions.TAG_CANCEL
            btnSubmit.setOnClickListener(this)
            btnCancel.setOnClickListener(this)

            //设置文字
            btnSubmit.text =
                if (TextUtils.isEmpty(pickerOptions.textContentConfirm)) context.resources.getString(
                    R.string.pickerview_submit
                ) else pickerOptions.textContentConfirm
            btnCancel.text =
                if (TextUtils.isEmpty(pickerOptions.textContentCancel)) context.resources.getString(
                    R.string.pickerview_cancel
                ) else pickerOptions.textContentCancel
            tvTitle.text =
                if (TextUtils.isEmpty(pickerOptions.textContentTitle)) "" else pickerOptions.textContentTitle //默认为空


            //设置color
            btnSubmit.setTextColor(pickerOptions.textColorConfirm)
            btnCancel.setTextColor(pickerOptions.textColorCancel)
            tvTitle.setTextColor(pickerOptions.textColorTitle)
            rv_top_bar.setBackgroundColor(pickerOptions.bgColorTitle)

            //设置文字大小
            btnSubmit.textSize = pickerOptions.textSizeSubmitCancel.toFloat()
            btnCancel.textSize = pickerOptions.textSizeSubmitCancel.toFloat()
            tvTitle.textSize = pickerOptions.textSizeTitle.toFloat()
        } else {
            pickerOptions.customListener.customLayout(
                LayoutInflater.from(context).inflate(pickerOptions.layoutRes, contentContainer)
            )
        }

        // ----滚轮布局
        val optionsPicker = findViewById(R.id.optionspicker) as LinearLayout
        optionsPicker.setBackgroundColor(pickerOptions.bgColorWheel)

        wheelOptions = MyAddressWheelOptions(optionsPicker, pickerOptions.isRestoreItem)
        if (pickerOptions.optionsAddSelectChangeListener != null) {
            wheelOptions?.setOptionsSelectChangeListener(pickerOptions.optionsAddSelectChangeListener)
        }

        wheelOptions?.setTextContentSize(pickerOptions.textSizeContent)
        wheelOptions?.setItemsVisible(pickerOptions.itemsVisibleCount)
        wheelOptions?.setAlphaGradient(pickerOptions.isAlphaGradient)
        wheelOptions?.setLabels(pickerOptions.label1, pickerOptions.label2, pickerOptions.label3, pickerOptions.label4)
        wheelOptions?.setTextXOffset(
            pickerOptions.x_offset_one,
            pickerOptions.x_offset_two,
            pickerOptions.x_offset_three,
            pickerOptions.x_offset_four,
        )
        wheelOptions?.setCyclic(
            pickerOptions.cyclic1,
            pickerOptions.cyclic2,
            pickerOptions.cyclic3,
            pickerOptions.cyclic4
        )
        wheelOptions?.setTypeface(pickerOptions.font)

        setOutSideCancelable(pickerOptions.cancelable)

        wheelOptions?.setDividerColor(pickerOptions.dividerColor)
        wheelOptions?.setDividerType(pickerOptions.dividerType)
        wheelOptions?.setLineSpacingMultiplier(pickerOptions.lineSpacingMultiplier)
        wheelOptions?.setTextColorOut(pickerOptions.textColorOut)
        wheelOptions?.setTextColorCenter(pickerOptions.textColorCenter)
        wheelOptions?.isCenterLabel(pickerOptions.isCenterLabel)
    }

    /**
     * 动态设置标题
     *
     * @param text 标题文本内容
     */
    fun setTitleText(text: String?) {
        val tvTitle = findViewById(R.id.tvTitle) as TextView
        tvTitle.text = text
    }

    /**
     * 设置默认选中项
     *
     * @param option1
     */
    fun setSelectOptions(option1: Int) {
        mPickerOptions.option1 = option1
        reSetCurrentItems()
    }

    private fun reSetCurrentItems() {
        if (wheelOptions != null) {
            wheelOptions!!.setCurrentItems(
                pickerOptions.option1,
                pickerOptions.option2,
                pickerOptions.option3,
                pickerOptions.option4
            )
        }
    }

    fun setPicker(optionsItems: List<T>?, isSelectCallback: Boolean = true) {
        this.setPicker(optionsItems, null, isSelectCallback)
    }

    fun setPicker(options1Items: List<T>?, options2Items: List<List<T>>?, isSelectCallback: Boolean = true) {
        this.setPicker(options1Items, options2Items, null, isSelectCallback)
    }

    fun setPicker(
        options1Items: List<T>?,
        options2Items: List<List<T>>?,
        options3Items: List<List<List<T>>>?,
        isSelectCallback: Boolean = true
    ) {
        this.setPicker(options1Items, options2Items, options3Items, null, isSelectCallback)
    }

    fun setPicker(
        options1Items: List<T>?,
        options2Items: List<List<T>>?,
        options3Items: List<List<List<T>>>?,
        options4Items: List<List<List<List<T>>>>?,
        isSelectCallback: Boolean = true
    ) {
        if (!isSelectCallback) {
            wheelOptions?.setSelectCallback(false)
        }
        wheelOptions?.setPicker(options1Items, options2Items, options3Items, options4Items)
        reSetCurrentItems()
    }

    //不联动情况下调用
    fun setNPicker(
        options1Items: List<T>?,
        options2Items: List<T>?,
        options3Items: List<T>?,
        options4Items: List<T>?
    ) {
        wheelOptions?.setLinkage(false)
        wheelOptions?.setNPicker(options1Items, options2Items, options3Items, options4Items)
        reSetCurrentItems()
    }

    override fun onClick(v: View) {
        val tag = v.tag as String
        if (tag == pickerOptions.TAG_SUBMIT) {
            returnData()
        } else if (tag == pickerOptions.TAG_CANCEL) {
            if (pickerOptions.cancelListener != null) {
                pickerOptions.cancelListener.onClick(v)
            }
        }
        dismiss()
    }

    //抽离接口回调的方法
    private fun returnData() {
        if (pickerOptions.optionsAddSelectChangeListener != null && wheelOptions != null) {
            val optionsCurrentItems = wheelOptions!!.getCurrentItems()
            pickerOptions.optionsAddSelectChangeListener?.onOptionsSelectChanged(
                optionsCurrentItems[0],
                optionsCurrentItems[1],
                optionsCurrentItems[2],
                optionsCurrentItems[3]
            )
        }
    }

    override fun isDialog(): Boolean {
        return pickerOptions.isDialog
    }
}
  1. builder/MyAddressOptionsPickerBuilder.kt
package org.fyc.publib.diyPickerview.builder

import android.content.Context
import android.graphics.Typeface
import android.view.View
import android.view.ViewGroup
import androidx.annotation.ColorInt
import com.bigkoo.pickerview.configure.PickerOptions
import com.bigkoo.pickerview.listener.CustomListener
import com.contrarywind.view.WheelView.DividerType
import org.fyc.publib.diyPickerview.listener.OnAddressOptionsSelectChangeListener
import org.fyc.publib.diyPickerview.options.MyPickerOptions
import org.fyc.publib.diyPickerview.view.MyAddressOptionsPickerView

class MyAddressOptionsPickerBuilder(context: Context, listener: OnAddressOptionsSelectChangeListener) {

    // 配置类
    private val mPickerOptions: MyPickerOptions = MyPickerOptions(PickerOptions.TYPE_PICKER_OPTIONS)

    init {
        mPickerOptions.context = context
        mPickerOptions.optionsAddSelectChangeListener = listener
    }

    //Option
    fun setSubmitText(textContentConfirm: String): MyAddressOptionsPickerBuilder {
        mPickerOptions.textContentConfirm = textContentConfirm
        return this
    }

    fun setCancelText(textContentCancel: String): MyAddressOptionsPickerBuilder {
        mPickerOptions.textContentCancel = textContentCancel
        return this
    }

    fun setTitleText(textContentTitle: String): MyAddressOptionsPickerBuilder {
        mPickerOptions.textContentTitle = textContentTitle
        return this
    }

    fun isDialog(isDialog: Boolean): MyAddressOptionsPickerBuilder {
        mPickerOptions.isDialog = isDialog
        return this
    }

    fun addOnCancelClickListener(cancelListener: View.OnClickListener): MyAddressOptionsPickerBuilder {
        mPickerOptions.cancelListener = cancelListener
        return this
    }

    fun setSubmitColor(textColorConfirm: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textColorConfirm = textColorConfirm
        return this
    }

    fun setCancelColor(textColorCancel: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textColorCancel = textColorCancel
        return this
    }

    /**
     * [.setOutSideColor] instead.
     *
     * @param backgroundId color resId.
     */
    @Deprecated("")
    fun setBackgroundId(backgroundId: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.outSideColor = backgroundId
        return this
    }

    /**
     * 显示时的外部背景色颜色,默认是灰色
     *
     * @param outSideColor color resId.
     * @return
     */
    fun setOutSideColor(outSideColor: Int):MyAddressOptionsPickerBuilder {
        mPickerOptions.outSideColor = outSideColor
        return this
    }

    /**
     * ViewGroup 类型
     * 设置PickerView的显示容器
     *
     * @param decorView Parent View.
     * @return
     */
    fun setDecorView(decorView: ViewGroup?): MyAddressOptionsPickerBuilder {
        mPickerOptions.decorView = decorView
        return this
    }

    fun setLayoutRes(res: Int, listener: CustomListener?): MyAddressOptionsPickerBuilder {
        mPickerOptions.layoutRes = res
        mPickerOptions.customListener = listener
        return this
    }

    fun setBgColor(bgColorWheel: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.bgColorWheel = bgColorWheel
        return this
    }

    fun setTitleBgColor(bgColorTitle: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.bgColorTitle = bgColorTitle
        return this
    }

    fun setTitleColor(textColorTitle: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textColorTitle = textColorTitle
        return this
    }

    fun setSubCalSize(textSizeSubmitCancel: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textSizeSubmitCancel = textSizeSubmitCancel
        return this
    }

    fun setTitleSize(textSizeTitle: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textSizeTitle = textSizeTitle
        return this
    }

    fun setContentTextSize(textSizeContent: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textSizeContent = textSizeContent
        return this
    }

    fun setOutSideCancelable(cancelable: Boolean): MyAddressOptionsPickerBuilder {
        mPickerOptions.cancelable = cancelable
        return this
    }

    fun setLabels(label1: String = "", label2: String = "", label3: String = "",  label4: String = ""): MyAddressOptionsPickerBuilder {
        mPickerOptions.label1 = label1
        mPickerOptions.label2 = label2
        mPickerOptions.label3 = label3
        mPickerOptions.label4 = label4
        return this
    }

    /**
     * 设置Item 的间距倍数,用于控制 Item 高度间隔
     *
     * @param lineSpacingMultiplier 浮点型,1.0-4.0f 之间有效,超过则取极值。
     */
    fun setLineSpacingMultiplier(lineSpacingMultiplier: Float): MyAddressOptionsPickerBuilder {
        mPickerOptions.lineSpacingMultiplier = lineSpacingMultiplier
        return this
    }

    /**
     * Set item divider line type color.
     *
     * @param dividerColor color resId.
     */
    fun setDividerColor(@ColorInt dividerColor: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.dividerColor = dividerColor
        return this
    }

    /**
     * Set item divider line type.
     *
     * @param dividerType enum Type [WheelView.DividerType]
     */
    fun setDividerType(dividerType: DividerType?): MyAddressOptionsPickerBuilder {
        mPickerOptions.dividerType = dividerType
        return this
    }

    /**
     * Set the textColor of selected item.
     *
     * @param textColorCenter color res.
     */
    fun setTextColorCenter(textColorCenter: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textColorCenter = textColorCenter
        return this
    }

    /**
     * Set the textColor of outside item.
     *
     * @param textColorOut color resId.
     */
    fun setTextColorOut(@ColorInt textColorOut: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.textColorOut = textColorOut
        return this
    }

    fun setTypeface(font: Typeface?): MyAddressOptionsPickerBuilder {
        mPickerOptions.font = font
        return this
    }

    fun setCyclic(cyclic1: Boolean, cyclic2: Boolean, cyclic3: Boolean, cyclic4: Boolean): MyAddressOptionsPickerBuilder {
        mPickerOptions.cyclic1 = cyclic1
        mPickerOptions.cyclic2 = cyclic2
        mPickerOptions.cyclic3 = cyclic3
        mPickerOptions.cyclic4 = cyclic4
        return this
    }

    fun setSelectOptions(option1: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.option1 = option1
        return this
    }

    fun setSelectOptions(option1: Int, option2: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.option1 = option1
        mPickerOptions.option2 = option2
        return this
    }

    fun setSelectOptions(option1: Int, option2: Int, option3: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.option1 = option1
        mPickerOptions.option2 = option2
        mPickerOptions.option3 = option3
        return this
    }

    fun setSelectOptions(option1: Int, option2: Int, option3: Int, option4: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.option1 = option1
        mPickerOptions.option2 = option2
        mPickerOptions.option3 = option3
        mPickerOptions.option4 = option4
        return this
    }

    fun setTextXOffset(
        xoffset_one: Int,
        xoffset_two: Int,
        xoffset_three: Int,
        x_offset_four: Int
    ): MyAddressOptionsPickerBuilder {
        mPickerOptions.x_offset_one = xoffset_one
        mPickerOptions.x_offset_two = xoffset_two
        mPickerOptions.x_offset_three = xoffset_three
        mPickerOptions.x_offset_four = x_offset_four
        return this
    }

    fun isCenterLabel(isCenterLabel: Boolean): MyAddressOptionsPickerBuilder {
        mPickerOptions.isCenterLabel = isCenterLabel
        return this
    }

    /**
     * 设置最大可见数目
     *
     * @param count 建议设置为 3 ~ 9之间。
     */
    fun setItemVisibleCount(count: Int): MyAddressOptionsPickerBuilder {
        mPickerOptions.itemsVisibleCount = count
        return this
    }

    /**
     * 透明度是否渐变
     *
     * @param isAlphaGradient true of false
     */
    fun isAlphaGradient(isAlphaGradient: Boolean): MyAddressOptionsPickerBuilder {
        mPickerOptions.isAlphaGradient = isAlphaGradient
        return this
    }

    /**
     * 切换选项时,是否还原第一项
     *
     * @param isRestoreItem true:还原; false: 保持上一个选项
     * @return TimePickerBuilder
     */
    fun isRestoreItem(isRestoreItem: Boolean): MyAddressOptionsPickerBuilder {
        mPickerOptions.isRestoreItem = isRestoreItem
        return this
    }

    /**
     * @param listener 切换item项滚动停止时,实时回调监听。
     * @return
     */
    fun setOptionsSelectChangeListener(listener: OnAddressOptionsSelectChangeListener): MyAddressOptionsPickerBuilder {
        mPickerOptions.optionsAddSelectChangeListener = listener
        return this
    }


    fun <T> build(): MyAddressOptionsPickerView<T> {
        return MyAddressOptionsPickerView(mPickerOptions)
    }
}
测试
package com.fyc.test.myaddressviewtest

import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.bigkoo.pickerview.builder.OptionsPickerBuilder
import org.fyc.publib.diyPickerview.builder.MyAddressOptionsPickerBuilder
import org.fyc.publib.diyPickerview.listener.OnAddressOptionsSelectChangeListener


class MainActivity : AppCompatActivity() {

    private lateinit var buttonOne: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initView()
        initClick()
    }

    private fun initView() {
        buttonOne = findViewById(R.id.btn_one)
    }

    private val item1Array = mutableListOf("广东省", "广西省")
    private val item2Array = mutableListOf<List<String>>(
        mutableListOf("广州市", "韶关市", "深圳市"),
        mutableListOf("南宁市")
    )

    private val item3Array = mutableListOf<List<List<String>>>(
        mutableListOf(mutableListOf("荔湾区"), mutableListOf("越秀区", "aa区"), mutableListOf("福田区")),
        mutableListOf(mutableListOf("兴宁区"))
    )

    private val item4Array = mutableListOf<List<List<List<String>>>>(
        mutableListOf(mutableListOf(mutableListOf("x1街道", "x2街道")),mutableListOf(mutableListOf("y1街道", "y2街道"), mutableListOf("y3街道", "y4街道")), mutableListOf(mutableListOf("z1街道", "z2街道"))),
        mutableListOf(mutableListOf(mutableListOf("t1街道")))
    )

    private fun initClick() {
        buttonOne.setOnClickListener {
            testOne()
        }
    }

    private fun testOne() {
        val pvOptions = MyAddressOptionsPickerBuilder(this, object : OnAddressOptionsSelectChangeListener {
            override fun onOptionsSelectChanged(
                options1: Int,
                options2: Int,
                options3: Int,
                options4: Int
            ) {
//                Log.e("fyc", "MyAddressOptionsPickerBuilder >>> options1 = $options1, options2 = $options2, options3 = $options3, options4 = $options4")

                Log.e("fyc", "MyAddressOptionsPickerBuilder >>> options1 = ${item1Array[options1]}, options2 = ${item2Array[options1][options2]}, options3 = ${item3Array[options1][options2][options3]}, options4 = ${item4Array[options1][options2][options3][options4]}")
            }
        }).build<String>()

        pvOptions.setPicker(item1Array, item2Array, item3Array, item4Array, false)
        pvOptions.show()
    }

    private fun testTwo() {
        //条件选择器
        val pvOptions = OptionsPickerBuilder(
            this@MainActivity
        ) { options1, options2, options3, _ -> //返回的分别是三个级别的选中位置
            Log.e("fyc", "MyAddressOptionsPickerBuilder >>> options1 = $options1, options2 = $options2, options3 = $options3")
        }.build<String>()
        pvOptions.setPicker(item1Array, item2Array, item3Array)
        pvOptions.show()
    }
}
总结

    遇到问题还是优先尝试解决问题吧。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您介绍一下Android仿IOS自定义AlertDialog提示框的实现方法。 首先,我们需要在Android项目中创建一个自定义布局文件,用于显示弹框的内容。可以使用LinearLayout或RelativeLayout等布局容器来组织弹框的内容,例如: ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="标题" android:textSize="18sp" /> <TextView android:id="@+id/message" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="内容" android:textSize="14sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center"> <Button android:id="@+id/confirm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确定" /> <Button android:id="@+id/cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消" /> </LinearLayout> </LinearLayout> ``` 接下来,我们需要创建一个自定义AlertDialog类,用于显示弹框和处理按钮点击事件。在这个类中,我们需要实现onCreateDialog方法来加载自定义布局文件,并设置弹框的标题、内容和按钮监听器等。例如: ```java public class IOSAlertDialog extends DialogFragment { private String title; private String message; private DialogInterface.OnClickListener confirmListener; private DialogInterface.OnClickListener cancelListener; public IOSAlertDialog(String title, String message, DialogInterface.OnClickListener confirmListener, DialogInterface.OnClickListener cancelListener) { this.title = title; this.message = message; this.confirmListener = confirmListener; this.cancelListener = cancelListener; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = LayoutInflater.from(getActivity()); View view = inflater.inflate(R.layout.dialog_ios_alert, null); TextView titleView = view.findViewById(R.id.title); TextView messageView = view.findViewById(R.id.message); Button confirmButton = view.findViewById(R.id.confirm); Button cancelButton = view.findViewById(R.id.cancel); titleView.setText(title); messageView.setText(message); confirmButton.setOnClickListener(confirmListener); cancelButton.setOnClickListener(cancelListener); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setView(view); return builder.create(); } } ``` 最后,在我们的Activity中,我们可以通过创建一个实例对象,并调用show方法来显示弹框。例如: ```java IOSAlertDialog dialog = new IOSAlertDialog( "提示", "确定要删除吗?", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 确定按钮点击事件 } }, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 取消按钮点击事件 } }); dialog.show(getSupportFragmentManager(), "IOSAlertDialog"); ``` 这样,我们就可以实现一个Android仿IOS自定义AlertDialog提示框了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值