底部弹出菜单是什么

底部弹出菜单,即从app界面底部弹出的一个菜单列表,这种UI办法被众多app所选用,是一种干流的布局办法。

底部弹出菜单原来这么简单

底部弹出菜单原来这么简单

思路分析

咱们先分析一下,这样一种UI应该由哪些布局组成?首先在原界面上以一小块区域显现界面的这种办法,很明显便是对话框Dialog做的事情吧!最底部是一个撤销菜单,上面的功能菜单可所以一个,也可所以两个、三个甚至更多。所以,咱们能够运用RecyclerView完成。需要留意一点的是,最上面那个菜单的样式稍微有点不一样,由于它上面是油滑的,有圆角,这样的界面显现愈加调和。咱们首要考虑的便是弹出对话框的动画样式,另外留意一点便是能够多支持几个语种,让结构愈加专业,这儿只需要翻译“撤销”文字。

开端看代码

package dora.widget
import android.app.Activity
import android.app.Dialog
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.listener.OnItemChildClickListener
import dora.widget.bean.BottomMenu
import dora.widget.bottomdialog.R
class DoraBottomMenuDialog : View.OnClickListener, OnItemChildClickListener {
    private var bottomDialog: Dialog? = null
    private var listener: OnMenuClickListener? = null
    interface OnMenuClickListener {
        fun onMenuClick(position: Int, menu: String)
    }
    fun setOnMenuClickListener(listener: OnMenuClickListener) : DoraBottomMenuDialog {
        this.listener = listener
        return this
    }
    fun show(activity: Activity, menus: Array<String>): DoraBottomMenuDialog {
        if (bottomDialog == null && !activity.isFinishing) {
            bottomDialog = Dialog(activity, R.style.DoraView_AlertDialog)
            val contentView =
                LayoutInflater.from(activity).inflate(R.layout.dview_dialog_content, null)
            initView(contentView, menus)
            bottomDialog!!.setContentView(contentView)
            bottomDialog!!.setCanceledOnTouchOutside(true)
            bottomDialog!!.setCancelable(true)
            bottomDialog!!.window!!.setGravity(Gravity.BOTTOM)
            bottomDialog!!.window!!.setWindowAnimations(R.style.DoraView_BottomDialog_Animation)
            bottomDialog!!.show()
            val window = bottomDialog!!.window
            window!!.decorView.setPadding(0, 0, 0, 0)
            val lp = window.attributes
            lp.width = WindowManager.LayoutParams.MATCH_PARENT
            lp.height = WindowManager.LayoutParams.WRAP_CONTENT
            window.attributes = lp
        } else {
            bottomDialog!!.show()
        }
        return this
    }
    private fun initView(contentView: View, menus: Array<String>) {
        val recyclerView = contentView.findViewById<RecyclerView>(R.id.dview_recycler_view)
        val adapter = MenuAdapter()
        val list = mutableListOf<BottomMenu>()
        menus.forEachIndexed { index, s ->
            when (index) {
                0 -> {
                    list.add(BottomMenu(s, BottomMenu.TOP_MENU))
                }
                else -> {
                    list.add(BottomMenu(s, BottomMenu.NORMAL_MENU))
                }
            }
        }
        adapter.setList(list)
        recyclerView.adapter = adapter
        val decoration = DividerItemDecoration(contentView.context, DividerItemDecoration.VERTICAL)
        recyclerView.addItemDecoration(decoration)
        adapter.addChildClickViewIds(R.id.tv_menu)
        adapter.setOnItemChildClickListener(this)
        val tvCancel = contentView.findViewById<TextView>(R.id.tv_cancel)
        tvCancel.setOnClickListener(this)
    }
    private fun dismiss() {
        bottomDialog?.dismiss()
        bottomDialog = null
    }
    override fun onClick(v: View) {
        when (v.id) {
            R.id.tv_cancel -> dismiss()
        }
    }
    override fun onItemChildClick(adapter: BaseQuickAdapter<*, *>, view: View, position: Int) {
        listener?.onMenuClick(position, adapter.getItem(position) as String)
        dismiss()
    }
}

类的结构不只能够承继,还能够运用聚合和组合的办法,咱们这儿就不直接承继Dialog了,运用一种更接近署理的一种办法。条条大路通罗马,能抓到老鼠的便是好猫。这儿的规划是经过调用show办法,传入一个菜单列表的数组来显现菜单,调用dismiss办法来关闭菜单。最终添加一个菜单点击的事情,把点击item的内容和方位露出给调用方。

package dora.widget
import com.chad.library.adapter.base.BaseMultiItemQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import dora.widget.bean.BottomMenu
import dora.widget.bottomdialog.R
class MenuAdapter : BaseMultiItemQuickAdapter<BottomMenu, BaseViewHolder>() {
    init {
        addItemType(BottomMenu.NORMAL_MENU, R.layout.dview_item_menu)
        addItemType(BottomMenu.TOP_MENU, R.layout.dview_item_menu_top)
    }
    override fun convert(holder: BaseViewHolder, item: BottomMenu) {
        holder.setText(R.id.tv_menu, item.menu)
    }
}

多类型的列表布局咱们选用BRVAH,

implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper:3.0.10")

来区分有圆角和没圆角的item条目。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="DoraView.AlertDialog" parent="@android:style/Theme.Dialog">
        <!-- 是否启用标题栏 -->
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <!-- 是否运用背景半透明 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:backgroundDimEnabled">true</item>
    </style>
    <style name="DoraView.BottomDialog.Animation" parent="Animation.AppCompat.Dialog">
        <item name="android:windowEnterAnimation">@anim/translate_dialog_in</item>
        <item name="android:windowExitAnimation">@anim/translate_dialog_out</item>
    </style>
</resources>

以上是对话框的样式。咱们再来看一下进入和退出对话框的动画。

translate_dialog_in.xml

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

translate_dialog_out.xml

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

最终给你们证明一下我是做了言语国际化的。

底部弹出菜单原来这么简单

运用办法

// 翻开底部弹窗
val dialog = DoraBottomMenuDialog()
dialog.setOnMenuClickListener(object : DoraBottomMenuDialog.OnMenuClickListener {
    override fun onMenuClick(position: Int, menu: String) {
        val intent = Intent(Intent.ACTION_VIEW)
        intent.data = Uri.parse(url)
        startActivity(intent)
    }
})
dialog.show(this, arrayOf("外部浏览器翻开"))

开源项目

github.com/dora4/dview…