底部弹出菜单是什么
底部弹出菜单,即从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…