注册

Dialog 可不可以传Application

自定义Dialog

  1. 继承Dialog
class SourceDialog(context: Context, themeResId: Int) : Dialog(context, themeResId) {  

constructor(context: Context) : this(context, R.style.CustomDialogTheme)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.source_layout)
}
}
  1. 创建自己的主题样式
<style name="CustomDialogTheme" parent="@android:style/Theme.Dialog">  
<item name="android:windowBackground">@android:color/transparentitem> //透明背景
<item name="android:windowNoTitle">trueitem> //没有标题
<item name="android:windowFullscreen">trueitem> //是否全屏
<item name="android:backgroundDimEnabled">trueitem> //背景黑暗
<item name="android:backgroundDimAmount">0.5item> //背景黑暗透明度
style>

可以传入自己创建的主题,也可以不传,Android 会有默认的主题

Dialog(@UiContext @NonNull Context context, @StyleRes int themeResId,  
boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == Resources.ID_NULL) {
final TypedValue outValue = new TypedValue();
//这里会指定默认的主题,如果不传主题
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId);
} else {
mContext = context;
}

mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

final Window w = new PhoneWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setOnWindowSwipeDismissedCallback(() -> {
if (mCancelable) {
cancel();
}
});
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
}
  1. 使用
val dialog=SourceDialog(context) 
dialog.show()

遇到的问题

  1. Dialog 可不可以传Application ?

背景:这几天接到一个需求,收到动作需要在任何界面上弹出信号源选择器页面(铺满整个屏幕),我一开始是选择了Service+WindowManager 添加View显示的。之前也看了一下公司的CommonUI (展示一下亮度条,音量条之类的全局UI) 用到的是Dialog 弹出界面的。我也跟着写一个,才发现一个一个坑接着来。

答案是可以的,是要window 传一个 type

这是我的Dialog

class SourceDialog(context: Context, themeResId: Int) : Dialog(context, themeResId) {  

constructor(context: Context) : this(context, R.style.CustomDialogTheme)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.source_layout)
}
}

//传入Application
val dialog=SourceDialog(MyApplication.CONTEXT)
dialog.show()

我就很疑惑,提示Activity需要运行

屏幕截图 2024-05-24 151913.png

我后来换成了,正常运行

//传入activity
val dialog=SourceDialog(this@MainActivity)
dialog.show()

很疑惑,对比同事负责的项目发现我需要给window设置了一些东西

//Dialog 

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.source_layout)
window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
}

//这样就可以正常展示
val dialog=SourceDialog(MyApplication.CONTEXT)
dialog.show()

  1. 设置Dialog 全屏宽高不成功

我的布局文件 最外层是线性布局

<LinearLayout android:id="@+id/group_source"  
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:gravity="center"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">


LinearLayout>

但是我发现 设置主题样式true 不起作用。 我在这里参考了 三句代码创建全屏Dialog或者DialogFragment

  • 粗暴一点直接设置window 大小 ==需要在setContentView 之后设置window的大小才会生效,如果在setContentView 之前设置,此时window的dectorView为空不会更新布局
class SourceDialog(context: Context, themeResId: Int) : Dialog(context, themeResId) {  

constructor(context: Context) : this(context, R.style.CustomDialogTheme)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.source_layout)
window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
window?.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT) //也可以换成具体数值宽高
}
}
  • 主题样式增加一样 false 因为很多默认的Dialog 主题这个属性一般为true。
<style name="CustomDialogTheme" parent="@android:style/Theme.Dialog">  
<item name="android:windowBackground">@android:color/transparentitem>
<item name="android:windowNoTitle">trueitem>
<item name="android:windowFullscreen">trueitem>
<item name="android:windowIsFloating">falseitem>
<item name="android:backgroundDimEnabled">trueitem>
<item name="android:backgroundDimAmount">0.5item>
style>

Dialog setContentView 会走到PhoneWindow 的这个方法 走到installDecor -> generateLayout

屏幕截图 2024-05-24 160441.png

屏幕截图 2024-05-24 160620.png

屏幕截图 2024-05-24 160736.png 会发现这个属性为true的话,会根据内容展示。我们给这个属性设置为false这样就不用给Window设置大小了。


作者:很好881
来源:juejin.cn/post/7372396174249738278

0 个评论

要回复文章请先登录注册