android取弹窗中的数据,怎么在Android中利用PopupWindow实现一个底部弹窗功能

怎么在Android中利用PopupWindow实现一个底部弹窗功能

发布时间:2020-12-30 14:02:01

来源:亿速云

阅读:127

作者:Leah

这篇文章将为大家详细讲解有关怎么在Android中利用PopupWindow实现一个底部弹窗功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

(一)PopupWindow

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

二、界面效果

56f41f78b98ee4123759007ec340753c.gif

三、设计实现

(一)需求分析点击主页按钮弹出底部弹窗

点击弹窗引擎,以Toast显示引擎名称并关闭弹窗

点击弹窗外部可以关闭弹窗

(二)文件列表

6e3a8df58fa72799ac90cd6cec493550.png

(三)布局设计

1. 主界面样式设计

(activity_main.xml)

主界面的样式十分简单,就是一个普通的按钮<?xml  version="1.0" encoding="utf-8"?>

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

tools:context=".MainActivity">

android:id="@+id/btn"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="14dp"

android:text="点击——底部弹窗"

android:textColor="@color/white"/>

2. 弹窗样式设计

(pw_search_engine.xml)

弹窗样式的布局也十分简单,就是一个基本的线性布局的 RecyclerView

值得注意的是,最基本的 layoutManager 可以通过指定 app:layoutManager 来实现<?xml  version="1.0" encoding="utf-8"?>

xmlns:app="http://schemas.android.com/apk/res-auto"

android:orientation="vertical"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@color/white">

android:id="@+id/recyclerView"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:overScrollMode="never"

app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

3. 弹窗列表 item 样式设计

(item_search_engine.xml)

列表单项,因为是 Demo 示例,所以简单地用一个横向布局,内置一个图标 icon 和一个名称 TextView 来进行展示<?xml  version="1.0" encoding="utf-8"?>

android:orientation="horizontal"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center">

android:id="@+id/iconIV"

android:layout_width="36dp"

android:layout_height="36dp"

android:layout_margin="14dp" />

android:id="@+id/titleTV"

android:layout_width="0dp"

android:layout_height="wrap_content"

android:layout_weight="1"

android:layout_marginEnd="36dp"

android:maxLines="1"

android:ellipsize = "end"

android:textColor="@color/black"

android:textSize="16sp" />

4. 弹窗动画设计

(pw_bottom_in.xml 与 pw_bottom_out.xml)

android:duration="300"

android:fromXDelta="0"

android:fromYDelta="1000"

android:toXDelta="0"

android:toYDelta="0" />

android:duration="300"

android:fromXDelta="0"

android:fromYDelta="0"

android:toXDelta="0"

android:toYDelta="1000" />

(四)数据存储与加载

1. 数据存储(UIData.kt 与 arrays.xml)// 搜索引擎的数据实体类,包含名称和 icon 资源 id 两个属性

data class SearchEngine(

val title : String,

val res : Int

)

以字符串数组的形式存储搜索引擎的名称以及对应的图标资源<?xml  version="1.0" encoding="utf-8"?>

百度

搜狗

360

必应

神马

@drawable/ic_baidu

@drawable/ic_sougou

@drawable/ic_360

@drawable/ic_bing

@drawable/ic_shenma

2. 数据加载(MainActivity.kt)private lateinit var engines : MutableList

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 

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.ktclass MainActivity : AppCompatActivity() {

private lateinit var engines : MutableList

private 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 

engines.add(SearchEngine(titleList[index],iconResList[index]))

}

}

}

}

关于怎么在Android中利用PopupWindow实现一个底部弹窗功能就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android,如果你想要点击PopupWindow周围关闭,可以通过以下几个步骤实现: 1.创建一个透明的背景层,并添加点击事件,当用户点击背景层时,关闭PopupWindow。 2.在PopupWindow的showAsDropDown()方法,设置setBackgroundDrawable(),将PopupWindow的背景设置为透明,这样点击背景层时,点击事件才能被响应。 下面是示例代码: ```java // 创建透明的背景层 View backgroundView = new View(context); backgroundView.setBackgroundColor(Color.parseColor("#80000000")); backgroundView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popupWindow.dismiss(); } }); // 创建PopupWindow View contentView = LayoutInflater.from(context).inflate(R.layout.popup_layout, null); PopupWindow popupWindow = new PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); popupWindow.setFocusable(true); // 设置PopupWindow可以获焦点 popupWindow.setOutsideTouchable(true); // 设置PopupWindow外部可点击 popupWindow.showAsDropDown(anchorView); // 添加背景层 ViewGroup rootView = (ViewGroup) ((Activity) context).getWindow().getDecorView().findViewById(android.R.id.content); rootView.addView(backgroundView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); ``` 这样,当用户点击PopupWindow周围的背景层时,就可以关闭了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值