【问题标题】:Is there a way to create Multi Select Dialog inside a Bottom Sheet Dialog in android有没有办法在 android 的底部工作表对话框中创建多选对话框
【发布时间】:2022-01-20 06:23:23
【问题描述】:

我正在尝试将我的对话框移动到底部工作表对话框。但我面临的问题是底部工作表对话框没有像警报对话框中那样的构建器,或者看起来如此。我也找不到底部表中的多选对话框。

val dialogBuilder = MaterialAlertDialogBuilder(this)
    dialogBuilder.setTitle(title)
    dialogBuilder.setCancelable(false)
    dialogBuilder.background =
        AppCompatResources.getDrawable(this, R.drawable.bg_white_round_red_ripple)
    dialogBuilder.setMultiChoiceItems(
        StringArray, booleanArray
    ) { _, i, b ->
        if (b) {
            integerArrayList.add(i)
            integerArrayList.sort()
        } else {
            integerArrayList.remove(i)
        }
        
    }
    dialogBuilder.setPositiveButton("OK") { dialog, which ->
        val stringBuilder = StringBuilder()
        if (integerArrayList.size > 0) {
            for (j in 0 until integerArrayList.size) {
                stringBuilder.append(StringArray[integerArrayList[j]])
                if (j != integerArrayList.size - 1) {
                    stringBuilder.append(", ")
                }
            }
            textView.text = stringBuilder.toString()
        } else {
            textView.text = title
        }
    }
    dialogBuilder.setNegativeButton(
        "Cancel"
    ) { dialogInterface, _ -> // dismiss dialog
        dialogInterface.dismiss()
    }
    val alertDialog = dialogBuilder.create()

    alertDialog.show()

有没有办法在底部表中执行此操作,还是我必须创建一个行为像这样的自定义底部表?有造型解决方案吗?

【问题讨论】:

    标签: android kotlin android-layout material-design bottom-sheet


    【解决方案1】:

    很多天后,我决定从头开始制作一个带有底部工作表的自定义 multiSelectDialog。

    @AndroidEntryPoint
    class MultiSelectDialog (private val title: String?,
                             private val list: ArrayList<String>,
                             private var selectedItems: SparseBooleanArray,
                             val returnVal: (selectedItems: SparseBooleanArray) -> Unit
    ) : BottomSheetDialogFragment(), MultiSelectDialogListener {
    
        private var _binding: DialogMultiSelectBinding? = null
        private val binding get() = _binding!!
        val viewModel: MultiSelectDialogViewModel by viewModels()
    
        private lateinit var adapter : MultiSelectDialogRecyclerViewAdapter
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            _binding = DialogMultiSelectBinding.inflate(inflater, container, false)
            return binding.root
        }
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            binding.viewmodel = viewModel
            viewModel.multiSelectDialogListener = this
            binding.rvCheckList.layoutManager = LinearLayoutManager(requireContext())
            init()
        }
    
        private fun populateRecyclerView() {
            adapter = MultiSelectDialogRecyclerViewAdapter(requireContext(), list, selectedItems,
                object : MultiSelectDialogRecyclerViewAdapter.OnItemClickListener{
                    override fun onItemClick(isCheckedList: SparseBooleanArray, position: Int) {
                        selectedItems = isCheckedList
                    }
                })
            binding.rvCheckList.adapter = adapter
        }
    
        private fun init(){
            populateRecyclerView()
            if (!title.isNullOrEmpty()) {
                binding.tvTitle.visibility = View.VISIBLE
                viewModel.title = title
            }
            else{
                binding.tvTitle.visibility = View.GONE
            }
    
            dialog?.setOnKeyListener { _, keyCode, _ ->
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    if (dialog!!.isShowing) {
                        dialog!!.cancel()
                    }
                }
                true
            }
        }
    
        override fun onPositiveClick() {
            returnVal(selectedItems)
            dialog?.dismiss()
        }
    
        override fun onNegativeClick() {
            dialog?.cancel()
        }
    
        override fun onNeutralClick() {
            selectedItems.clear()
            adapter.setData(selectedItems)
        }
    
        override fun onCheckedChangedListener() {
            requireView().snackbar("Items Changed")
        }
        override fun getTheme(): Int {
            return R.style.AppBottomSheetDialogTheme
        }
    
    }
    

    这个视图模型是

    @HiltViewModel
    class MultiSelectDialogViewModel @Inject constructor() : ViewModel() {
        var title: String? = null
        var multiSelectDialogListener: MultiSelectDialogListener? = null
    
        fun onPositiveClick(view: View) {
            multiSelectDialogListener?.onPositiveClick()
        }
        fun onNegativeClick(view: View) {
            multiSelectDialogListener?.onNegativeClick()
        }
        fun onNeutralClick(view: View) {
            multiSelectDialogListener?.onNeutralClick()
        }
        fun onSelectedItemsChanged(){
            multiSelectDialogListener?.onCheckedChangedListener()
        }
    }
    

    也是听众

    interface MultiSelectDialogListener {
        fun onPositiveClick()
        fun onNegativeClick()
        fun onNeutralClick()
        fun onCheckedChangedListener()
    }
    

    回收器视图适配器

    class MultiSelectDialogRecyclerViewAdapter(
        val context: Context,
        private var arrayList: ArrayList<String>,
        private var isCheckedList: SparseBooleanArray,
        private var onItemClickListener: OnItemClickListener
        ):
    RecyclerView.Adapter<MultiSelectDialogRecyclerViewAdapter.ViewHolder>(){
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val v = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_check_box_list_dialog, parent, false)
            return ViewHolder(v)
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            holder.bind(position)
        }
    
        override fun getItemCount(): Int {
            return arrayList.size
        }
    
        fun setData(mIsCheckedList: SparseBooleanArray) {
            isCheckedList = mIsCheckedList
            notifyDataSetChanged()
        }
    
        inner class ViewHolder internal constructor(itemView: View): RecyclerView.ViewHolder(itemView)
        {
            val checkbox_list_dialog: MaterialCheckBox by lazy { itemView.findViewById<MaterialCheckBox>(R.id.checkbox_list_dialog) }
            val btn_positive: Button by lazy { itemView.findViewById<Button>(R.id.btn_positive) }
            val btn_negative: Button by lazy { itemView.findViewById<Button>(R.id.btn_negative) }
            val btn_neutral: Button by lazy { itemView.findViewById<Button>(R.id.btn_neutral) }
            val cl_multi_select_dialog_root: ConstraintLayout by lazy { itemView.findViewById<ConstraintLayout>(R.id.cl_multi_select_dialog_root) }
            init {
                checkbox_list_dialog.setOnClickListener{
                    onClick(it)
                }
            }
            fun bind(position: Int) {
                // use the sparse boolean array to check
                checkbox_list_dialog.isChecked = isCheckedList.get(position, false)
                checkbox_list_dialog.text = arrayList[position]
            }
            fun onClick(v: View?) {
                val adapterPosition = absoluteAdapterPosition
                if (!isCheckedList.get(adapterPosition, false)) {
                    checkbox_list_dialog.isChecked = true
                    isCheckedList.put(adapterPosition, true)
                } else {
                    checkbox_list_dialog.isChecked = false
                    isCheckedList.put(adapterPosition, false)
                }
                onItemClickListener.onItemClick(isCheckedList,adapterPosition)
            }
        }
        interface OnItemClickListener {
            fun onItemClick(isCheckedList: SparseBooleanArray, position: Int)
        }
    }
    

    以及为此的布局文件

    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">
        <data>
            <variable
                name="viewmodel"
                type="xxx.MultiSelectDialogViewModel" />
        </data>
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl_multi_select_dialog_root"
            tools:context=".ui.dialogs.multi_select.MultiSelectDialog">
            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_title" />
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_check_list" />
            <androidx.appcompat.widget.AppCompatButton
                android:id="@+id/btn_positive"/>
            <androidx.appcompat.widget.AppCompatButton
                android:id="@+id/btn_negative" />
            <androidx.appcompat.widget.AppCompatButton
                android:id="@+id/btn_neutral" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    

    还有风格

    <style name="AppBottomSheetDialogTheme"
            parent="Theme.MaterialComponents.Light.BottomSheetDialog">
            <item name="android:colorAccent">@color/onta_red</item>
            <item name="bottomSheetStyle">@style/CustomBottomSheetStyle</item>
        </style>
        <style name="CustomBottomSheetStyle"
            parent="Widget.Design.BottomSheet.Modal">
            <item name="android:background">@drawable/bg_white_bottom_sheet</item>
        </style>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-27
      • 1970-01-01
      • 2021-05-19
      相关资源
      最近更新 更多