Android中用DataBinding创建的Dialog为何忽略部分布局参数?
为什么用DataBinding创建的Dialog会忽略android:layout_height和layout_marginHorizontal参数?
我发现用DataBinding创建Dialog时,布局里的android:layout_height和android:layout_marginHorizontal参数会被忽略,推测还有其他参数也会有这个问题,目前主要被这两个问题困扰。
Dialog布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="150dp" android:layout_marginHorizontal="12dp" android:background="@color/white" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/dialogTV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/black" android:textSize="18sp" android:textStyle="bold" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:src="@drawable/ic_settings_outline_28dp" /> </LinearLayout>
Java代码
Dialog defaultDialog = new Dialog(this); defaultDialog.setContentView(R.layout.dialog_test); defaultDialog.getWindow().setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.dialog_background)); defaultDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); defaultDialog.setCancelable(true); Dialog dialogWithBinding = new Dialog(this); DialogTestBinding dialogTestBinding = DialogTestBinding.inflate(getLayoutInflater()); dialogWithBinding.setContentView(dialogTestBinding.getRoot()); dialogWithBinding.getWindow().setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.dialog_background)); dialogWithBinding.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); dialogWithBinding.setCancelable(true); findViewById(R.id.showDefaultDialog).setOnClickListener(view -> { TextView dialogTV = defaultDialog.findViewById(R.id.dialogTV); dialogTV.setText("Dialog"); defaultDialog.show(); }); findViewById(R.id.showBindingDialog).setOnClickListener(view -> { dialogTestBinding.dialogTV.setText("Dialog with Binding"); dialogWithBinding.show(); });
dialog_background是简单的透明形状
运行结果

问题原因
用DialogTestBinding.inflate(getLayoutInflater())加载布局时,未指定父容器,导致布局中layout_*系列参数(如layout_height、layout_marginHorizontal)无法生效——这类参数是给父容器传递的布局规则,没有父容器的话系统会直接忽略这些属性。
而普通方式defaultDialog.setContentView(R.layout.dialog_test)内部会自动将布局添加到Dialog的默认父容器(Window的DecorView)中,父容器能正常解析这些布局参数。
解决办法
方式一:Inflate时指定父容器
在加载布局时,把Dialog的Window内容视图作为父容器,同时设置attachToRoot=false(避免自动添加,后续通过setContentView手动设置):
Dialog dialogWithBinding = new Dialog(this); // 获取Dialog的Window内容视图作为父容器 ViewGroup parent = (ViewGroup) dialogWithBinding.getWindow().getDecorView().findViewById(android.R.id.content); DialogTestBinding dialogTestBinding = DialogTestBinding.inflate(getLayoutInflater(), parent, false); dialogWithBinding.setContentView(dialogTestBinding.getRoot()); // 保留原有配置 dialogWithBinding.getWindow().setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.dialog_background)); dialogWithBinding.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); dialogWithBinding.setCancelable(true);
方式二:手动设置根布局LayoutParams
若不想指定父容器,可在设置ContentView后,手动给根View配置包含margin和高度的LayoutParams:
Dialog dialogWithBinding = new Dialog(this); DialogTestBinding dialogTestBinding = DialogTestBinding.inflate(getLayoutInflater()); // 创建包含指定高度和水平margin的LayoutParams ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics()) ); int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics()); params.leftMargin = margin; params.rightMargin = margin; dialogTestBinding.getRoot().setLayoutParams(params); dialogWithBinding.setContentView(dialogTestBinding.getRoot()); // 保留原有配置 dialogWithBinding.getWindow().setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.dialog_background)); dialogWithBinding.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); dialogWithBinding.setCancelable(true);
额外说明
- 所有
layout_*开头的属性都属于布局参数,依赖父容器的LayoutParams解析逻辑,没有父容器或父容器不支持该参数时就会失效; - 优先推荐方式一,更符合Android布局设计逻辑,能自动解析布局中所有layout参数,无需手动逐一设置。
内容的提问来源于stack exchange,提问作者Couver
相关产品推荐
相关产品推荐

