运行结果
先介绍一些参数
contentView : 用于设置相应的布局
animationStyle: 用于设置进入和退出的动画
isOutsideTouchable :点击外侧是否可以关闭弹窗(这这里因为我们设置了全屏所以没有设置这个)
isClippingEnabled 是否可以铺满屏幕(false为可以铺满,包括状态栏和导航栏)
具体来举个栗子说明
设置style
<style name="pop_animation">
<item name="android:windowEnterAnimation">@anim/pop_in</item>
<item name="android:windowExitAnimation">@anim/pop_out</item>
</style>
新建一个anim包,里面两个文件
pop_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fillAfter="true"
android:fromAlpha="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1" />
</set>
pop_out
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fillAfter="true"
android:fromAlpha="1"
android:interpolator="@android:anim/decelerate_interpolator"
android:toAlpha="0" />
</set>
confirm_popupwindow.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#7d000000">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="@dimen/dp_280"
android:layout_height="@dimen/dp_160"
android:background="#fff"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_confirm_cancel"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="取消"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/view2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/view2" />
<TextView
android:id="@+id/tv_confirm_ensure"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="确定"
android:textColor="#03A9F4"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tv_confirm_cancel"
app:layout_constraintTop_toTopOf="@+id/view2" />
<View
android:id="@+id/view2"
android:layout_width="@dimen/dp_1"
android:layout_height="@dimen/dp_50"
android:background="#C5C5C5"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/view3"
android:layout_width="0dp"
android:layout_height="@dimen/dp_1"
android:background="#C5C5C5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/view2" />
<TextView
android:id="@+id/tv_confirm_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/view3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
/**
* @Anthor:Tian
* @Date:2020/10/5
* @Description:弹窗
*/
class ConfirmPopupWindow(context: Context, builder: ConfirmPopupWindowBuilder? = null) : PopupWindow() {
init {
val inflater = LayoutInflater.from(context)
this.contentView = inflater.inflate(R.layout.confirm_popupwindow, null) //布局xml
this.width = LinearLayout.LayoutParams.MATCH_PARENT //父布局减去padding
this.height = LinearLayout.LayoutParams.MATCH_PARENT
this.animationStyle = R.style.pop_animation //进入和退出动画效果
this.isOutsideTouchable = true //是否可以
this.isClippingEnabled = false //背景透明化可以铺满全屏
// 设置最终的背景,也可以通过context.resources.getColor(resId)设置自己的颜色
val colorDrawable = ColorDrawable(Color.parseColor("#00000000"))
this.setBackgroundDrawable(colorDrawable) //设置背景
//设置取消的点击事件
this.contentView.tv_confirm_cancel.setOnClickListener {
//先隐藏弹窗
dismiss()
//调用接口的具体实现
builder?.mCancelListener?.invoke()
}
//设置确认的点击事件
this.contentView.tv_confirm_ensure.setOnClickListener {
//先隐藏弹窗
dismiss()
builder?.mConfirmListener?.invoke()
}
}
//创建ConfirmPopupWindow的一个内部类
//返回Builder就可以流水线定义
class ConfirmPopupWindowBuilder(val context: Context) {
companion object {
fun init(context: Context): ConfirmPopupWindowBuilder {
return ConfirmPopupWindowBuilder(context)
}
}
var mCancelListener: () -> Unit = {} //一个不需要参数的无返回值的函数
var mConfirmListener: () -> Unit = {}
private val window: ConfirmPopupWindow = ConfirmPopupWindow(context, this)
fun build(): ConfirmPopupWindow {
window.contentView.tv_confirm_content.visibility = View.VISIBLE
window.contentView.tv_confirm_cancel.visibility = View.VISIBLE
window.contentView.tv_confirm_ensure.visibility = View.VISIBLE
return window
}
fun setContent(content: String): ConfirmPopupWindowBuilder {
window.contentView.tv_confirm_content.visibility = View.VISIBLE
window.contentView.tv_confirm_content.text = content
return this
}
fun setCancelListener(callback: () -> Unit): ConfirmPopupWindowBuilder {
mCancelListener = callback
return this
}
fun setEnsureListener(callback: () -> Unit): ConfirmPopupWindowBuilder {
mConfirmListener = callback
return this
}
}
fun show() {
showAtLocation(contentView, Gravity.CENTER, 0, 0)
}
}
使用:
button.setOnClickListener {
confirmPopupWindow.show()
}
private val confirmPopupWindow: ConfirmPopupWindow by lazy {
ConfirmPopupWindow.ConfirmPopupWindowBuilder.init(this)
.setContent("确定退出吗")
.setEnsureListener {
finish()
}
.build()
}