十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章将为大家详细讲解有关怎么在Android中利用PopupWindow实现一个底部弹窗功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
萨嘎ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为成都创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:13518219792(备注:SSL证书合作)期待与您的合作!1. 初始化
加载弹窗的布局
实例化 PopupWindow 传入布局和弹窗的宽高
对布局里面的控件的操作
对布局本身的一些设置
// 加载弹窗的布局 pwView = LayoutInflater.from(this).inflate(R.layout.pw_search_engine, null, false) //实例化 PopupWindow popupWindow = PopupWindow( pwView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ) // 对布局里面的控件的操作 initRecyclerView() // 对布局本身的一些设置 popupWindow.isOutsideTouchable = true popupWindow.isTouchable = true popupWindow.isFocusable = true popupWindow.animationStyle = R.style.pw_bottom_anim_style popupWindow.setOnDismissListener { backgroundAlpha(1f) }
2. 展示弹窗
弹出弹窗修改背景亮度—变暗
// 弹出弹窗 val rootView = LayoutInflater.from(this).inflate(R.layout.activity_main,null) popupWindow.showAtLocation(rootView, Gravity.BOTTOM, 0, 0) // 修改背景亮度—变暗 backgroundAlpha(0.7f)
3. 关闭弹窗
关闭弹窗
修改背景亮度—变亮
// 关闭弹窗 popupWindow.dismiss() // 修改背景亮度—变亮 backgroundAlpha(1f)
4. 背景亮度修改
// 控制背景亮度 private fun backgroundAlpha(bgAlpha: Float) { val lp = window.attributes lp.alpha = bgAlpha //0.0-1.0 window.attributes = lp }
使用 XML 标签定义并使用视图动画:
1. XML 标签
alpha 渐变透明度
scale 渐变尺寸伸缩
translate 画面位置移动
rotate 画面转移旋转
set 定义动画集
2. 给 PopupWindow 添加动画
popupWindow.animationStyle = R.style.pw_bottom_anim_style
点击主页按钮弹出底部弹窗
点击弹窗引擎,以Toast显示引擎名称并关闭弹窗
点击弹窗外部可以关闭弹窗
1. 主界面样式设计
(activity_main.xml)
主界面的样式十分简单,就是一个普通的按钮
2. 弹窗样式设计
(pw_search_engine.xml)
弹窗样式的布局也十分简单,就是一个基本的线性布局的 RecyclerView
值得注意的是,最基本的 layoutManager 可以通过指定app:layoutManager 来实现
3. 弹窗列表 item 样式设计
(item_search_engine.xml)
列表单项,因为是 Demo 示例,所以简单地用一个横向布局,内置一个图标 icon 和一个名称 TextView 来进行展示
4. 弹窗动画设计
(pw_bottom_in.xml 与 pw_bottom_out.xml)
1. 数据存储(UIData.kt 与 arrays.xml)
// 搜索引擎的数据实体类,包含名称和 icon 资源 id 两个属性 data class SearchEngine( val title : String, val res : Int )
以字符串数组的形式存储搜索引擎的名称以及对应的图标资源
- 百度
- 搜狗
- 360
- 必应
- 神马
- @drawable/ic_baidu
- @drawable/ic_sougou
- @drawable/ic_360
- @drawable/ic_bing
- @drawable/ic_shenma
2. 数据加载(MainActivity.kt)
private lateinit var engines : MutableListprivate fun initData() { // 初始化引擎列表 engines = mutableListOf() // 从 arrays.xml 获取引擎名称数组 val titleList = resources.getStringArray(R.array.search_engine_title_list) // 由于资源 id 是整型,但是在 arrays.xml 中存储的是字符串, // 所以这里先初始化一个资源 id 的数组,元素类型为整型 val iconResList : MutableList = mutableListOf() // 通过类型数组加载相关引擎资源列表,遍历其中元素,传入索引值, // 通过调用 getResourceId(index,0) 获取 icon 的资源 id 存入刚才初始化的 id 数组中 val resList: TypedArray = resources.obtainTypedArray(R.array.search_engine_res_list) for (index in 0 until resList.length()) { iconResList.add(resList.getResourceId(index,0)) } // 记得及时调用 recycle() 回收 TypedArray 对象 resList.recycle() // 循环,用获得的 title 和 id 生成对应的搜索引擎对象,存入搜索引擎列表中 for (index in titleList.indices){ if (index < iconResList.size){ engines.add(SearchEngine(titleList[index],iconResList[index])) } } }
上述提及的内容代码,此处将不再进行展示;因为重点是介绍底部弹窗的实现,弹窗布局中的 RecyclerView 的实现就不过多介绍
1. AdapterForSearchEngine.kt 弹窗列表适配器
class AdapterForSearchEngine (dataList: MutableList) : RecyclerView.Adapter () { // 搜索引擎数据集合 private val mDataList: MutableList = mutableListOf() init { // 初始化 主要是对数据进行初始化 mDataList.clear() mDataList.addAll(dataList) } // ViewHolder 方便 item 复用 class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {} // 获取列表 item 数量 override fun getItemCount(): Int { return mDataList.size } // 绑定视图与数据 override fun onBindViewHolder(holder: ViewHolder, position: Int) { val engine: SearchEngine = mDataList[position] holder.itemView.titleTV.text = engine.title holder.itemView.iconIV.setImageResource(engine.res) holder.itemView.setOnClickListener { listener?.click(engine) } } // 创建 ViewHolder 实例 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view: View = LayoutInflater.from(parent.context).inflate(R.layout.item_search_engine, parent, false) return ViewHolder(view) } // 点击事件 private var listener :OnItemClickListener? = null interface OnItemClickListener { fun click(engine: SearchEngine) } fun setOnItemClickListener(listener: OnItemClickListener) { this.listener = listener } }
2. MainActivity.kt
class MainActivity : AppCompatActivity() { private lateinit var engines : MutableListprivate lateinit var popupWindow : PopupWindow private lateinit var pwView : View private lateinit var mAdapter : AdapterForSearchEngine override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化数据 initData() // 初始化 PopupWindow initPopupWindow() // 按钮点击事件 btn.setOnClickListener { // 显示弹窗 showPopWindow() } } private fun initPopupWindow() { // 加载弹窗布局 pwView = LayoutInflater.from(this).inflate(R.layout.pw_search_engine, null, false) // 实例化 PopupWindow popupWindow = PopupWindow( pwView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT ) // 初始化弹窗列表 initRecyclerView() // 设置 popupWindow popupWindow.isOutsideTouchable = true popupWindow.isTouchable = true popupWindow.isFocusable = true // 加载弹窗动画 popupWindow.animationStyle = R.style.pw_bottom_anim_style // 设置弹窗关闭监听——恢复亮度 popupWindow.setOnDismissListener { backgroundAlpha(1f) } } private fun showPopWindow() { val rootView = LayoutInflater.from(this).inflate( R.layout.activity_main, null ) // 设置弹窗位置 popupWindow.showAtLocation(rootView, Gravity.BOTTOM, 0, 0) // 使得背景亮度变暗 backgroundAlpha(0.7f) } // 控制背景亮度 private fun backgroundAlpha(bgAlpha: Float) { val lp = window.attributes lp.alpha = bgAlpha //0.0-1.0 window.attributes = lp } private fun initRecyclerView() { mAdapter = AdapterForSearchEngine(engines) pwView.recyclerView?.adapter = mAdapter mAdapter.setOnItemClickListener(object : AdapterForSearchEngine.OnItemClickListener{ override fun click(engine: SearchEngine) { Toast.makeText(this@MainActivity, engine.title, Toast.LENGTH_SHORT).show() popupWindow.dismiss() } }) } private fun initData() { // 初始化引擎列表 engines = mutableListOf() // 从 arrays.xml 获取引擎名称数组 val titleList = resources.getStringArray(R.array.search_engine_title_list) // 由于资源 id 是整型,但是在 arrays.xml 中存储的是字符串, // 所以这里先初始化一个资源 id 的数组,元素类型为整型 val iconResList : MutableList = mutableListOf() // 通过类型数组加载相关引擎资源列表,遍历其中元素,传入索引值, // 通过调用 getResourceId(index,0) 获取 icon 的资源 id 存入刚才初始化的 id 数组中 val resList: TypedArray = resources.obtainTypedArray(R.array.search_engine_res_list) for (index in 0 until resList.length()) { iconResList.add(resList.getResourceId(index,0)) } // 记得及时调用 recycle() 回收 TypedArray 对象 resList.recycle() // 循环,用获得的 title 和 id 生成对应的搜索引擎对象,存入搜索引擎列表中 for (index in titleList.indices){ if (index < iconResList.size){ engines.add(SearchEngine(titleList[index],iconResList[index])) } } } }
关于怎么在Android中利用PopupWindow实现一个底部弹窗功能就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。