一、前言

在正常使用 PopupWindow 时不是很难,只需要几行代码就能实现一个对话框,但是有很多方法都是重复的,PopupWindow 本身会有一些局限性,需要处理。在使用 PopupWindows 时,默认是没有阴影背景的,需要自己处理。仅仅使用 PopupWindow 就可以满足项目中大部分的对话框需求。但是 Dialog 也有它的优势,所以可以看具体情况选择合适的对话框。封装后,调用起来更加方便,同时对于一些高频对话框可以做成通用的,以后就不需要再重复去写,随时调用更加方便。

二、引入

安卓对话框相关及简单封装使用 - 图1
Add it in your root build.gradle at the end of repositories:

  1. allprojects {
  2. repositories {
  3. ...
  4. maven { url 'https://www.jitpack.io' }
  5. }
  6. }

Step 2. Add the dependency

  1. dependencies {
  2. implementation 'com.github.KiWiLss:LPopup:1.0.2'
  3. }

三、BasePopup简单使用

BasePopup 是封装的基本对话框,其他对话框可以直接继承 BasePopup 使用,这样使用起来更简单方便。阴影动画效果也很好,PopupWindow 使用总结,这篇文章有对阴影实现方式的分析总结。阴影的实现缺点是部分机型状态栏不能覆盖阴影,整体来说效果还是挺好的。

1. 简单使用示例

  • 效果图:iShot2020-08-0922.46.35.gif

对话框代码:
这里做对话框具体的实现,也可以设置各种想要的效果。

  1. class BasePopupDemo(activity: Activity,layoutId: Int = R.layout.pw_center): BasePopup(activity,layoutId) {
  2. override fun setInterface() {
  3. //这里可以做获取数据,设置数据的操作,点击事件,以及对话框显示前的各种设置都可以在这里
  4. contentView?.run {
  5. tv_pw_onetitle_title.text = "你好"
  6. }
  7. }
  8. }

简单布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:orientation="vertical" android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. >
  7. <LinearLayout
  8. android:id="@+id/ll_pw_onetitle_outer"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:layout_marginHorizontal="40dp"
  12. android:orientation="vertical"
  13. android:layout_gravity="center"
  14. android:background="@drawable/bg_white_fillet_10">
  15. <!--标题-->
  16. <TextView
  17. android:id="@+id/tv_pw_onetitle_title"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:text="提示"
  21. android:textSize="18sp"
  22. android:textColor="#80000000"
  23. android:layout_gravity="center_horizontal"
  24. android:gravity="center"
  25. android:padding="25dp"
  26. android:layout_marginLeft="15dp"
  27. android:layout_marginRight="15dp"/>
  28. <View
  29. android:layout_width="match_parent"
  30. android:layout_height="0.5dp"
  31. android:background="#90000000"
  32. />
  33. <LinearLayout
  34. android:layout_width="match_parent"
  35. android:layout_height="wrap_content"
  36. >
  37. <TextView
  38. android:id="@+id/tv_pw_onetitle_cancel"
  39. android:layout_width="0dp"
  40. android:layout_height="wrap_content"
  41. android:layout_weight="1"
  42. android:text="取消"
  43. android:textSize="15sp"
  44. android:textColor="#80000000"
  45. android:gravity="center"
  46. android:padding="15dp"
  47. />
  48. <View
  49. android:layout_width="0.5dp"
  50. android:layout_height="match_parent"
  51. android:background="#90000000"/>
  52. <TextView
  53. android:id="@+id/tv_pw_onetitle_sure"
  54. android:layout_width="0dp"
  55. android:layout_height="wrap_content"
  56. android:layout_weight="1"
  57. android:text="确定"
  58. android:textSize="15sp"
  59. android:textColor="#80000000"
  60. android:gravity="center"
  61. android:padding="15dp"
  62. />
  63. </LinearLayout>
  64. </LinearLayout>
  65. </LinearLayout>

调用,里面有各种方法的详细注解:

  1. //basepopup 使用示例
  2. btn_common_base.setOnClickListener {
  3. BasePopupDemo(this)
  4. // .setIsMask()//设置是否有阴影
  5. // .setIsClickDismiss()//设置点击外部是否消失
  6. // .setPopupWidth()//设置对话框宽度
  7. // .setPopupHeight()//设置对话框高度
  8. // .setAnimationStyle2()//设置对话框展示动画
  9. .showCenter()
  10. }

2.内置封装对话框使用示例,基本都是偏向 Ios 风格

效果图:
iShot2020-08-0922.53.18.gif

  • 2.1 一个标题,一个按钮对话框,代码中有详细的注释

    1. Loopopup.Builder(this)
    2. .title("builder 模式")//设置标题
    3. .titleColor(R.color.colorAccent)//标题颜色
    4. .titleIsBold(true)//设置加粗
    5. .outerBg(R.drawable.bg_white_fillet_20)//对话框背景
    6. // .btnText()//按钮文字
    7. // .btnSize()//按钮文字大小
    8. // .btnColor()//按钮文字颜色
    9. // .btnBg()//按钮背景
    10. .clickCallBack(object : LoCallback {
    11. override fun click(loopopup: BasePopup?) {
    12. loopopup?.dismiss()
    13. Toast.makeText(this@CommonPopupActivity, "hello", Toast.LENGTH_SHORT).show()
    14. }
    15. })
    16. .build()
    17. .showCenter()
  • 2.2 一个标题,两个按钮样式

    1. Lotpopup.Builder(this)
    2. .rightBg(R.drawable.bg_test_right)//设置按钮背景,圆角要和整个背景圆角大小相同
    3. .callback(object : LtCallback() {
    4. //默认设置了左侧取消按钮,如需要可重写方法,示例如下
    5. override fun right(loopopup: BasePopup?) {
    6. loopopup?.dismiss()
    7. Toast.makeText(this@CommonPopupActivity, "right", Toast.LENGTH_SHORT).show()
    8. }
    9. override fun left(loopopup: BasePopup?) {
    10. super.left(loopopup)
    11. Toast.makeText(this@CommonPopupActivity, "left", Toast.LENGTH_SHORT).show()
    12. }
    13. })
    14. .build()
    15. .showCenter()
  • 2.3 两个标题(副标题,可以作为内容),一个按钮

    1. Ltopopup.Builder(this)
    2. .callback(object : LoCallback {
    3. override fun click(loopopup: BasePopup?) {
    4. loopopup?.dismiss()
    5. }
    6. })
    7. .build()
    8. .showCenter()
  • 2.4 两个标题(副标题,可以作为内容),两个按钮

    1. val pp = Lttpopup.Builder(this)
    2. .title("任意标题")
    3. .titleColor(R.color.colorAccent)
    4. .titleSize(R.dimen.s15)
    5. .titleIsBold(true)
    6. .subtitle("随意内容")
    7. .subtitleColor(R.color.blue0076)
    8. .subtitleSize(R.dimen.s15)
    9. .leftText("残忍")
    10. .leftSize(R.dimen.s15)
    11. .leftColor(R.color.colorPrimary)
    12. .rightText("立即就去")
    13. .rightSize(R.dimen.s15)
    14. .rightColor(R.color.white)
    15. .rightBg(R.drawable.bg_test_right)
    16. .callback(object : LtCallback() {
    17. override fun right(loopopup: BasePopup?) {
    18. }
    19. })
    20. .build()
    21. //pp.animationStyle = R.style.AnimFadeCenter
    22. pp.showCenter()

    三、EasyPopup 使用

    EasyPopup 这个对话框,动画效果很好,不会出现阴影无法覆盖的状态栏情况,同时对于位置的控制更好,可以更好的用在菜单型对话框上面。推荐使用这个。

3.1 简单使用示例

效果图:iShot2020-08-0923.08.42.gif

自定义对话框继承 EasyPopu:

  1. class EasyPopupDemo(activity: Activity,layoutId: Int = R.layout.pw_center): EasyPopup(activity,layoutId) {
  2. override fun setInterface() {
  3. contentView?.run {
  4. //这里可以做获取数据,设置数据的操作,点击事件,以及对话框显示前的各种设置都可以在这里
  5. contentView?.run {
  6. tv_pw_onetitle_title.text = "你好"
  7. }
  8. }
  9. }
  10. }

自定义布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:orientation="vertical" android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. >
  7. <LinearLayout
  8. android:id="@+id/ll_pw_onetitle_outer"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:layout_marginHorizontal="40dp"
  12. android:orientation="vertical"
  13. android:layout_gravity="center"
  14. android:background="@drawable/bg_white_fillet_10">
  15. <!--标题-->
  16. <TextView
  17. android:id="@+id/tv_pw_onetitle_title"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:text="提示"
  21. android:textSize="18sp"
  22. android:textColor="#80000000"
  23. android:layout_gravity="center_horizontal"
  24. android:gravity="center"
  25. android:padding="25dp"
  26. android:layout_marginLeft="15dp"
  27. android:layout_marginRight="15dp"/>
  28. <View
  29. android:layout_width="match_parent"
  30. android:layout_height="0.5dp"
  31. android:background="#90000000"
  32. />
  33. <LinearLayout
  34. android:layout_width="match_parent"
  35. android:layout_height="wrap_content"
  36. >
  37. <TextView
  38. android:id="@+id/tv_pw_onetitle_cancel"
  39. android:layout_width="0dp"
  40. android:layout_height="wrap_content"
  41. android:layout_weight="1"
  42. android:text="取消"
  43. android:textSize="15sp"
  44. android:textColor="#80000000"
  45. android:gravity="center"
  46. android:padding="15dp"
  47. />
  48. <View
  49. android:layout_width="0.5dp"
  50. android:layout_height="match_parent"
  51. android:background="#90000000"/>
  52. <TextView
  53. android:id="@+id/tv_pw_onetitle_sure"
  54. android:layout_width="0dp"
  55. android:layout_height="wrap_content"
  56. android:layout_weight="1"
  57. android:text="确定"
  58. android:textSize="15sp"
  59. android:textColor="#80000000"
  60. android:gravity="center"
  61. android:padding="15dp"
  62. />
  63. </LinearLayout>
  64. </LinearLayout>
  65. </LinearLayout>

调用:

  1. //EasyPopup 使用示例
  2. btn_common_easy.setOnClickListener {
  3. EasyPopupDemo(this)
  4. .setIsMask()//设置是否有阴影
  5. .setIsTouchOutsideDimiss()//设置点击外部是否消失
  6. .setAnimStyle()//设置动画
  7. .showCenter()
  8. }

3.2 底部弹出对话框效果

iShot2020-08-0923.12.36.gif
对话框代码:

  1. class ChoiceHeadPw(activity: Activity,layoutId: Int = R.layout.pw_choice_head): EasyPopup(activity,layoutId) {
  2. override fun setInterface() {
  3. //这里可以初始化界面,设置数据等,设置对话框宽高,动画等都可以
  4. contentView?.run {
  5. tv_pw_choice_head_cancel.setOnClickListener {
  6. dismiss()
  7. }
  8. tv_pw_choice_head_camera.text = "选择相机"
  9. }
  10. }
  11. }

自定义布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <LinearLayout
  6. android:layout_width="match_parent"
  7. android:layout_height="wrap_content"
  8. android:orientation="vertical"
  9. android:background="@drawable/bg_white_top_round_10">
  10. <TextView
  11. android:id="@+id/tv_pw_choice_head_camera"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:text="@string/take_camera"
  15. android:layout_gravity="center"
  16. android:layout_margin="@dimen/m10"/>
  17. <View
  18. style="@style/View_line"/>
  19. <TextView
  20. android:id="@+id/tv_pw_choice_head_album"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:text="@string/my_album"
  24. android:layout_gravity="center"
  25. android:layout_margin="@dimen/m10"/>
  26. <View
  27. style="@style/View_line"/>
  28. <TextView
  29. android:id="@+id/tv_pw_choice_head_cancel"
  30. android:layout_width="wrap_content"
  31. android:layout_height="wrap_content"
  32. android:text="@string/cancel"
  33. android:layout_gravity="center"
  34. android:layout_margin="@dimen/m10"/>
  35. </LinearLayout>
  36. </RelativeLayout>

调用:

  1. //自定义对话框示例,随意一个对话框
  2. btn_common_head2.setOnClickListener {
  3. ChoiceHeadPw(this)
  4. .showBottom()
  5. }

3.3 内置常用对话框

//easypopup 封装使用,每个弹出在中间都加了渐变动画,底部有向上弹出动画,顶部下拉动画,可以自定义动画

    1. 一个标题,一个按钮

iShot2020-08-0923.18.37.gif
对话框使用示例:

  1. Xoopopup.Builder(this)
  2. .title("这是一个标题")//设置标题
  3. .titleColor(R.color.colorPrimary)//设置标题字体颜色
  4. .titleIsBold(true)//设置标题加粗
  5. .titleSize(R.dimen.s15)//设置标题字体大小
  6. //.outerBg()//设置整个对话框背景
  7. .btnText("随意点击")//按钮的文字
  8. .btnSize(R.dimen.s15)//按钮字体大小
  9. .btnColor(R.color.colorAccent)//按钮字体颜色
  10. //.btnBg()//按钮的背景,最好和对话框背景圆角一致
  11. .callback(object : LoCallback2 {
  12. //设置按钮点击
  13. override fun click(loopopup: EasyPopup?) {
  14. loopopup?.dismiss()
  15. }
  16. })
  17. .build()
  18. .showCenter()
    1. 一个标题,两个按钮

iShot2020-08-0923.19.21.gif
使用示例:

  1. Xotpopup.Builder(this)
  2. .title("标题党")//设置标题
  3. .titleColor(R.color.colorAccent)//标题颜色
  4. .titleSize(R.dimen.s12)//标题大小
  5. .titleIsBold(false)//标题是否加粗
  6. //.outerBg()//背景
  7. .leftText("关闭")//左侧按钮文字
  8. .leftColor(R.color.colorAccent)//左侧文字颜色
  9. .leftSize(R.dimen.s15)//左侧文字大小
  10. //.leftBg()//左侧背景
  11. .rightText("是")//右侧文字
  12. //.rightBg()//右侧背景
  13. .rightColor(R.color.blue0076)//右侧文字颜色
  14. .rightSize(R.dimen.s13)//右侧文字大小
  15. .callback(object : LtCallback2() {
  16. //点击回调
  17. override fun right(loopopup: EasyPopup?) {
  18. }
  19. })
  20. .build()
  21. .showCenter()
    1. 两个标题(副标题,可以当内容),一个按钮

iShot2020-08-0923.20.07.gif
使用示例:

  1. Xtopopup.Builder(this)
  2. .title("title")//设置标题
  3. // .titleColor()//设置标题颜色
  4. // .titleSize()//设置标题大小
  5. // .titleIsBold()//设置标题是否加粗
  6. // .subtitleColor()//设置内容颜色
  7. // .subtitle()//设置内容文本
  8. // .subtitleSize()//设置内容字体大小
  9. // .outerBg()//设置背景
  10. // .btnText()//设置点击文本
  11. // .btnBg()//设置点击背景
  12. // .btnColor()//设置点击文字颜色
  13. // .btnSize()//设置点击文字大小
  14. .callback(object : LoCallback2 {
  15. //点击
  16. override fun click(loopopup: EasyPopup?) {
  17. }
  18. }).build()//获取 popupwindow 实例,后面可以调用 popupwindow 的方法
  19. .showCenter()
    1. 两个标题(副标题,可以当内容),两个按钮

iShot2020-08-0923.20.48.gif
使用示例:

  1. Xttpopup.Builder(this)//这里第二个参数可以传你自己的布局(想控件生效,只要对应的控件 id一样就行)
  2. .title("标题加粗")//设置标题
  3. .titleSize(R.dimen.s18)//设置标题字体大小
  4. .titleIsBold(true)//设置标题是否加粗
  5. .titleColor(R.color.colorAccent)//设置标题颜色
  6. .outerBg(R.drawable.bg_white_fillet_20)//设置整个对话框背景
  7. .subtitle("二个标题,二个按钮")//设置副标题,内容
  8. .subtitleSize(R.dimen.s15)//设置副标题内容字体大小
  9. .subtitleColor(R.color.blue0076)//设置副标题字体颜色
  10. .leftText("残忍离开")//设置左侧标题
  11. .leftSize(R.dimen.s12)//设置左侧字体大小
  12. .leftColor(R.color.grayf5f5)//设置左侧字体颜色
  13. //.leftBg(R.drawable.bg_test_right)//设置左侧背景,最好背景左下角圆角和背景圆角一致
  14. .rightText("点开看看")//设置右侧文字
  15. .rightSize(R.dimen.s12)//设置右侧字体大小
  16. .rightColor(R.color.colorAccent)//右侧文字颜色
  17. .rightBg(R.drawable.bg_test_right)//设置右侧背景
  18. .callback(object : LtCallback2() {
  19. //可以选择是否需要取消点击
  20. override fun right(loopopup: EasyPopup?) {//右侧按钮点击
  21. loopopup?.dismiss()
  22. }
  23. override fun left(loopopup: EasyPopup?) {//左侧按钮点击
  24. super.left(loopopup)//这个方法注释可以取消 dimiss
  25. }
  26. })
  27. .build()
  28. .setIsMask(true)//设置是否有阴影
  29. .showCenter()
    1. 选择拍照和打开相册对话框

iShot2020-08-0923.25.23.gif
使用示例:

  1. val xChoiceHead = XChoiceHead(this, object : XChoiceHead.Callback {
  2. override fun camera(xChoiceHead: XChoiceHead) {
  3. }
  4. override fun album(xChoiceHead: XChoiceHead) {
  5. }
  6. })
  7. //.showBottom()
  8. //对标题不满意,可以通过这个方法对内容进行修改
  9. // val tvCamrea = xChoiceHead.getView(R.id.tv_pw_choice_header_take) as TextView?
  10. // tvCamrea?.text = "是否拍照"
  11. xChoiceHead.showBottom()

3.4 菜单形式对话框

这类对话框,原生的 PopupWindow 控制位置不是很好控制,使用原生的,显示在对应的空间下方比较容易实现,但是显示空间的上下左右的位置就有点麻烦了。

iShot2020-08-0923.34.51.gif
对话框代码:

  1. class EasyMenuDemo(activity: Activity,layoutId:Int = R.layout.pw_menu2): EasyPopup(activity,layoutId) {
  2. override fun setInterface() {
  3. }
  4. }

简单布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:orientation="vertical" android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. >
  7. <LinearLayout
  8. android:id="@+id/ll_pw_onetitle_outer"
  9. android:layout_width="120dp"
  10. android:layout_height="wrap_content"
  11. android:orientation="vertical"
  12. android:layout_gravity="center"
  13. android:background="@drawable/center_pop_bg">
  14. <!--标题-->
  15. <TextView
  16. android:id="@+id/tv_pw_onetitle_title"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:text="提示"
  20. android:textSize="15sp"
  21. android:textColor="@color/black"
  22. android:layout_gravity="center_horizontal"
  23. android:gravity="center"
  24. android:padding="15dp"
  25. />
  26. <View
  27. android:layout_width="match_parent"
  28. android:layout_height="0.5dp"
  29. android:background="@color/blue0076"
  30. />
  31. <TextView
  32. android:id="@+id/tv_pw_onetitle_cancel"
  33. android:layout_width="match_parent"
  34. android:layout_height="wrap_content"
  35. android:text="取消"
  36. android:textSize="15sp"
  37. android:textColor="@color/black"
  38. android:gravity="center"
  39. android:padding="15dp"
  40. />
  41. <View
  42. android:layout_width="match_parent"
  43. android:layout_height="0.5dp"
  44. android:background="@color/blue0076"/>
  45. <TextView
  46. android:id="@+id/tv_pw_onetitle_sure"
  47. android:layout_width="match_parent"
  48. android:layout_height="wrap_content"
  49. android:text="确定"
  50. android:textSize="15sp"
  51. android:textColor="@color/black"
  52. android:gravity="center"
  53. android:padding="15dp"
  54. />
  55. </LinearLayout>
  56. </LinearLayout>

调用:

  1. EasyMenuDemo(this)
  2. .setIsMask(true)//设置是否有阴影
  3. //.setIsTouchOutsideDimiss()//设置点击外部是否消失
  4. .setAnimStyle(R.style.PopDownRightMenu)//设置动画
  5. .showAsDropDown(btn_common_menu)

3.5 控制显示位置

iShot2020-08-0923.37.58.gif
任意简单对话框:

  1. class GravityMenu(activity: Activity,layoutId: Int = R.layout.pw_menu2): EasyPopup(activity,layoutId) {
  2. override fun setInterface() {
  3. }
  4. }

使用示例:

  1. GravityMenu(this)
  2. .showAtAnchorView(btn_common_gravity,VerticalPosition.CENTER,HorizontalPosition.CENTER)

调用时,第一个参数是要显示的对话框,相对位置的控件,第二个参数是垂直方向上的位置,第三个参数是水平方向上的位置,后面还有两个参数是相对 x 和 y 方向的数值,一般这几个参数随意组合就可以实现在想要的控件的 中间、上方、下方、左侧、右侧,其他更复杂的位置配合最后两个参数调整。

3.6 下拉对话框

iShot2020-08-0923.52.57.gif
对话框:

  1. class PullPw(activity: Activity, layoutId: Int = R.layout.pw_pull): EasyPopup(activity,layoutId) {
  2. override fun setInterface() {
  3. //设置宽高,默认是只使用,要修改成下面这样
  4. width = ViewGroup.LayoutParams.MATCH_PARENT
  5. height = ViewGroup.LayoutParams.MATCH_PARENT
  6. contentView?.run {
  7. ll_pw_pull_outer.setOnClickListener {
  8. dismiss()
  9. }
  10. ll_pw_pull_outer2.setOnClickListener {
  11. dismiss()
  12. }
  13. }
  14. }
  15. }

布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. android:id="@+id/ll_pw_pull_outer"
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:orientation="vertical"
  8. android:background="#99000000">
  9. <LinearLayout
  10. android:id="@+id/ll_pw_pull_outer2"
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:orientation="vertical"
  14. android:background="@color/white">
  15. <TextView
  16. android:layout_width="match_parent"
  17. android:layout_height="40dp"
  18. android:text="第一行"
  19. android:gravity="center"/>
  20. <TextView
  21. android:layout_width="match_parent"
  22. android:layout_height="40dp"
  23. android:text="第二行"
  24. android:gravity="center"/>
  25. <!-- <TextView-->
  26. <!-- android:layout_width="match_parent"-->
  27. <!-- android:layout_height="40dp"-->
  28. <!-- android:text="第三行"-->
  29. <!-- android:gravity="center"/>-->
  30. </LinearLayout>
  31. <!-- <TextView-->
  32. <!-- android:id="@+id/v_pw_pull_bg"-->
  33. <!-- android:layout_width="match_parent"-->
  34. <!-- android:layout_height="match_parent"-->
  35. <!-- android:background="#99000000"-->
  36. <!-- />-->
  37. </LinearLayout>

调用:

  1. //下拉对话框
  2. btn_common_pull.setOnClickListener {
  3. PullPw(this)
  4. .setAnimStyle(R.style.GrowFromTop)//设置动画
  5. .setIsMask(false)//设置没有阴影
  6. .setIsTouchOutsideDimiss(false)//设置点击外部不能消失
  7. .showAsDropDown(btn_common_pull)//显示在这个控件的底部
  8. }

注意事项:
布局里面要使用 View 填充才有效,示例如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout android:id="@+id/ll_pw_pull_outer"
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. android:background="@color/colorPrimaryDark"
  8. xmlns:app="http://schemas.android.com/apk/res-auto">
  9. <LinearLayout
  10. android:id="@+id/ll_pw_pull_outer2"
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:orientation="vertical"
  14. android:background="@color/white">
  15. <TextView
  16. android:layout_width="match_parent"
  17. android:layout_height="40dp"
  18. android:text="第一行"
  19. android:gravity="center"
  20. app:layout_constraintTop_toTopOf="parent"/>
  21. <TextView
  22. android:layout_width="match_parent"
  23. android:layout_height="40dp"
  24. android:text="第二行"
  25. android:gravity="center"
  26. app:layout_constraintTop_toTopOf="parent"/>
  27. <TextView
  28. android:layout_width="match_parent"
  29. android:layout_height="wrap_content"
  30. android:text="第三行"
  31. android:gravity="center"
  32. android:maxWidth="200dp"
  33. app:layout_constraintTop_toTopOf="parent"/>
  34. <!-- <TextView-->
  35. <!-- android:id="@+id/v_pw_pull_bg"-->
  36. <!-- android:layout_width="match_parent"-->
  37. <!-- android:layout_height="0dp"-->
  38. <!-- android:layout_weight="1"-->
  39. <!-- android:text="@string/app_name"-->
  40. <!-- android:gravity="center"-->
  41. <!-- android:background="@color/colorPrimary"-->
  42. <!-- />-->
  43. </LinearLayout>
  44. <!-- 必须是View才会显示-->
  45. <View
  46. android:layout_width="match_parent"
  47. android:layout_height="match_parent"
  48. />
  49. </LinearLayout>

四、Xpopup 简单使用

上面实现对话框需要继承 EasyPopup,如果对话框不是很复杂的话,没有必须去新建一个类。使用 Xpopup,可以不用继承任何类,直接调用就可以实现对话框效果。内置 Xpopup 类,可以直接使用,可以用于对话框,菜单等.

效果图:
iShot2020-08-1122.26.45.gif
对话框实现:

  1. val xpopup = Xpopup.Builder(this, R.layout.pw_center)
  2. .alpha(0.6f)//设置背景透明度
  3. .isMask(true)//设置是否显示阴影
  4. .isCancelable(true)//设置点击外部是否消失
  5. .build()//获取Xpopup实例
  6. xpopup.setText(R.id.tv_pw_onetitle_title, "测试")//设置文字
  7. .setOnClick(R.id.tv_pw_onetitle_cancel, View.OnClickListener {
  8. xpopup.dismiss()
  9. }) //设置点击事件
  10. .setPopupWidth(ViewGroup.LayoutParams.WRAP_CONTENT)//设置宽度
  11. .setPopupHeight(ViewGroup.LayoutParams.WRAP_CONTENT)//设置高度
  12. .show()//默认渐变动画,默认显示在中间,可以在这里设置弹出位置和动画
  13. //.setImageResource()//设置资源图片
  14. //.showCenter()//弹出在中间,默认渐变动画
  15. //.showBottom()//底部弹出,默认上推动画
  16. //.showTop()//顶部弹出,默认下拉动画
  17. // .setIsMask(true)//设置是否有阴影
  18. // .setIsTouchOutsideDimiss(true)//设置点击外部是否消失
  19. // .setBackgroundAlpha(0.5f)//设置阴影渐变度
  20. // .setAnimStyle(R.style.AnimFadeCenter)//设置动画效果
  21. //xpopup.getView(R.id.tv_pw_onetitle_title)//通过这个方法获取对应的控件

菜单:

  1. Xpopup.Builder(this, R.layout.pw_menu2)
  2. .build()
  3. .showAsDropDown(btn_common_xpopupMenu)

任意位置:

  1. Xpopup.Builder(this, R.layout.pw_menu2)
  2. .build()
  3. .showAtAnchorView(
  4. btn_common_xpopupAny,
  5. VerticalPosition.BELOW,
  6. HorizontalPosition.ALIGN_RIGHT
  7. )

五、LDialog 简单使用

这个类是对常见的 Dialog 的简单封装,适用于各种居中和底部对话框,需要继承这个类使用。同时可以设置外部点击不能消失,还可以设置点击返回键不能消失。

使用效果图:iShot2020-08-1122.42.01.gif

  • 默认样式,什么参数都不设置

Dialog 类:

  1. class DefaultDialog(context: Context) : LDialog(context) {
  2. override fun initInterface(savedInstanceState: Bundle?) {
  3. }
  4. override fun initContentView(): Int = R.layout.pw_center
  5. }

显示:

  1. val dialog = DefaultDialog(this)
  2. dialog.show()
  • 设置各类参数

Dialog 类,详细参数都在下面的注释中:

  1. class OneDialog(context: Context) : LDialog(context) {
  2. override fun initInterface(savedInstanceState: Bundle?) {
  3. setWidth(ViewGroup.LayoutParams.MATCH_PARENT) //设置宽度
  4. .setHeight(ViewGroup.LayoutParams.WRAP_CONTENT) //设置高度
  5. .setGravity(Gravity.BOTTOM) //设置显示位置
  6. //.setImageRes()//设置图标
  7. .setAnimationStyle(R.style.PushInBottom)//设置动画
  8. .setText(R.id.tv_pw_choice_head_camera, "测试LDialog") //设置控件文字
  9. .setOnClick(R.id.tv_pw_choice_head_cancel, View.OnClickListener { //设置点击
  10. dismiss()
  11. })
  12. context
  13. val tvCancel = getView<TextView>(R.id.tv_pw_choice_head_cancel)// 获取控件
  14. //setCancelable(false)//单独设置 false ,dialog弹出后,点击屏幕或物理返回键,dialog不消失
  15. //setCanceledOnTouchOutside(false)// 单独设置 false ,dialog弹出后,点击屏幕dialog不消失,物理返回键消失
  16. setOnDismissListener { //对话框消失监听
  17. Log.e("MMM", ": onDismiss");
  18. }
  19. }
  20. override fun initContentView(): Int = R.layout.pw_choice_head
  21. }

显示:

  1. OneDialog(this)
  2. .show()

六、XDialog 简单使用

这个类和 LDialog类似,只是这个类使用时不需要继承,直接使用就行。使用于展示比较简单的,交互比较少的对话框。

效果图:
iShot2020-08-1122.50.48.gif
默认简单使用:

  1. //什么都不设置,默认居中显示,无动画效果
  2. XDialog.Builder(this,R.layout.pw_center)
  3. .build()
  4. .show()

设置参数:

  1. val dialog = XDialog.Builder(this,R.layout.pw_choice_head)
  2. .width(ViewGroup.LayoutParams.MATCH_PARENT)//设置宽度
  3. .height(ViewGroup.LayoutParams.WRAP_CONTENT)//设置高度
  4. .animationStyle(R.style.PushInBottom)//设置动画
  5. .gravity(Gravity.BOTTOM)//设置位置
  6. .build()
  7. dialog.setText(R.id.tv_pw_choice_head_camera,"不想拍照")//设置文字
  8. //.setImageRes()//设置图标
  9. .setOnClick(R.id.tv_pw_choice_head_cancel,View.OnClickListener { //设置点击
  10. dialog.dismiss()
  11. })
  12. .show()
  13. //可以通过getView获取控件
  14. //dialog.getView<TextView>(R.id.tv_pw_choice_head_cancel)//

七、LDialogFg 简单使用

这个是对普通的 DialogFragment 的简单封装,相对于 Dialog 和 PopupWindow,DialogFragment 的优势是生命周期和 Fragment 一样,并且在 Activity横竖屏切换时不会新建。

效果图:
iShot2020-08-1122.53.07.gif
默认样式:

  1. class DefaultDialogFg: LDialogFg() {
  2. override fun initInterface() {
  3. }
  4. override fun initLayoutId(): Int = R.layout.pw_center
  5. }
  1. //LDialogFg使用示例
  2. btn_dialog_lfg.setOnClickListener {
  3. DefaultDialogFg().show(supportFragmentManager,"")
  4. }

设置参数:

  1. class SetDialogFg: LDialogFg() {
  2. override fun initInterface() {
  3. setGravity(Gravity.BOTTOM)//设置位置
  4. setWidth(ViewGroup.LayoutParams.MATCH_PARENT)//设置宽度
  5. setHeight(ViewGroup.LayoutParams.WRAP_CONTENT)//设置高度
  6. setmAnimationStyle(R.style.PushInBottom)//设置动画
  7. // setText()//设置文字
  8. // setImageRes()//设置图标
  9. //设置点击
  10. // setOnClick(R.id.tv_pw_choice_head_cancel,View.OnClickListener {
  11. // dismiss()
  12. // })
  13. //也可以这样设置
  14. tv_pw_choice_head_cancel.setOnClickListener {
  15. dismiss()
  16. }
  17. isCancelable = false//设置点击外部是否消失(设置为false后,点击外部和返回键均不会消失)
  18. }
  19. override fun initLayoutId(): Int = R.layout.pw_choice_head
  20. }
  1. btn_dialog_lfgset.setOnClickListener {
  2. SetDialogFg()
  3. .show(supportFragmentManager,"")
  4. }

八、地址

LPopup
参考:
EasyPopup(已停止维护)
Android基于DialogFragment封装一个通用的Dialog-阿里云开发者社区
让你的Dialog变得更简洁一点吧 - 掘金
变种 Builder 模式:优雅的对象构建方式张拭心的博客 shixinzhang-CSDN博客
弹出PopupWindow后让背景变暗的方法
【Android】在任意位置弹出PopupWindow
Gavin-ZYX/SmartPopupWindow