如何在 XML 中以百分比设置对话框的宽度和高度

How to set Dialog width and height in percents in XML

我需要对话框的宽度和高度占屏幕的 70% space。我正在使用 ConstraintLayout 作为根布局,并尝试通过使用 app:layout_constraintWidth_percent 来实现这一点,但它不起作用。

如果没有 Java 代码就可以在 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="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/dialog_background_shape"
    android:padding="@dimen/app_padding">

    <TextView
        android:id="@+id/textView13"
        style="@style/text_plain3"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp"
        android:text="@string/add_member_title"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/button_add_member_close"
        style="@style/text_title2"
        android:textStyle="bold"
        android:layout_width="28dp"
        android:layout_height="28dp"
        android:background="@drawable/button_dialog_close"
        android:gravity="center"
        android:text="X"
        android:textColor="@color/text_plain3"
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

    <TextView
        android:id="@+id/add_member_group_id"
        style="@style/text_group_id"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="32dp"
        android:layout_marginTop="64dp"
        android:layout_marginEnd="32dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView13" />

    <TextView
        android:id="@+id/textView17"
        style="@style/text_card"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="@string/add_member_annotation"
        app:layout_constraintStart_toStartOf="@+id/add_member_group_id"
        app:layout_constraintTop_toBottomOf="@+id/add_member_group_id"/>

    <EditText
        android:id="@+id/add_member_user_id"
        android:layout_width="248dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:hint="@string/add_member_hint_id"
        android:importantForAutofill="no"
        android:inputType="textPersonName"
        android:maxLength="28"
        app:layout_constraintEnd_toEndOf="@+id/add_member_group_id"
        app:layout_constraintStart_toStartOf="@+id/add_member_group_id"
        app:layout_constraintTop_toBottomOf="@+id/textView17" />

    <Button
        android:id="@+id/button_add_member"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:layout_marginBottom="48dp"
        android:text="@string/add_member_button_add"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/add_member_group_id"
        app:layout_constraintStart_toStartOf="@+id/add_member_group_id"
        app:layout_constraintTop_toBottomOf="@+id/add_member_user_id"/>
</androidx.constraintlayout.widget.ConstraintLayout>

约束布局:

我看到您的“对话框”包含很多不同的视图。为此,我为您制作了一个简单的示例来展示如何使用 Guideline 来实现 Views 的百分比。 我建议学习它是如何工作的,并重建你的 layout 并更好地约束这个 Guidelines,因为现在一切都连接得非常糟糕。我们的想法是将 ConstraintLayout 连接到 Guideline 并将其旁边的所有内容(例如 TextView 等)连接到 ConstraintLayout。 (没有硬编码!,这就是相关设计的工作方式)。

我的示例显示了一个 TextView(可能是您的 ConstraintLayout(所有内容的框架),正好有 70% (app:layout_constraintGuide_percent="0.7") 的垂直和水平屏幕。重要的是将 TextViews widthheight 设置为 0dp 并附加到 Guideline:

<?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">

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/vertical_guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.7" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/horizontal_guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.7" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#2962FF"
        app:layout_constraintBottom_toTopOf="@+id/horizontal_guideline"
        app:layout_constraintEnd_toStartOf="@+id/vertical_guideline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="TextView" />

</androidx.constraintlayout.widget.ConstraintLayout>

结果:

另外 LinearLayout:

您可以使用 android:layout_weight="" 来给出百分比金额。所以 70% 意味着 weight of .70.

请记住将 width or/and height 设置为 0dp

<LinearLayout
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:text="70 percent of screen" 
        android:layout_width="0dp" 
        android:layout_height="wrap_content" 
        android:layout_weight=".70" /> 

</LinearLayout>

为了有一个约束width/height DialogFragment 或(一般任何特定的宽度或高度):

  1. 将您的 ConstraintLayout 包裹到另一个 ConstraintLayout 中,以使外部占据屏幕的整个尺寸,并且内部获得所需的 width/height 百分比:

  2. 使外层android:background透明

  3. 约束内层的宽高ConstraintLayout,使其居中于parent,并在宽高上加上百分比约束:

    app:layout_constraintHeight_percent="0.7"
    app:layout_constraintWidth_percent="0.7"    
    

现在布局如下:

<?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:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent">
        
    <androidx.constraintlayout.widget.ConstraintLayout      
        android:id="@+id/main_layout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:background="@drawable/dialog_background_shape"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.7"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent="0.7"        
        android:padding="@dimen/app_padding">

        <TextView
            android:id="@+id/textView13"
            style="@style/text_plain3"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="0dp"
            android:layout_marginTop="0dp"
            android:text="@string/add_member_title"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/button_add_member_close"
            style="@style/text_title2"
            android:textStyle="bold"
            android:layout_width="28dp"
            android:layout_height="28dp"
            android:background="@drawable/button_dialog_close"
            android:gravity="center"
            android:text="X"
            android:textColor="@color/text_plain3"
            android:textSize="20sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="HardcodedText" />

        <TextView
            android:id="@+id/add_member_group_id"
            style="@style/text_group_id"
            android:layout_width="250dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="32dp"
            android:layout_marginTop="64dp"
            android:layout_marginEnd="32dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView13" />

        <TextView
            android:id="@+id/textView17"
            style="@style/text_card"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="@string/add_member_annotation"
            app:layout_constraintStart_toStartOf="@+id/add_member_group_id"
            app:layout_constraintTop_toBottomOf="@+id/add_member_group_id" />

        <EditText
            android:id="@+id/add_member_user_id"
            android:layout_width="248dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:ems="10"
            android:hint="@string/add_member_hint_id"
            android:importantForAutofill="no"
            android:inputType="textPersonName"
            android:maxLength="28"
            app:layout_constraintEnd_toEndOf="@+id/add_member_group_id"
            app:layout_constraintStart_toStartOf="@+id/add_member_group_id"
            app:layout_constraintTop_toBottomOf="@+id/textView17" />

        <Button
            android:id="@+id/button_add_member"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="48dp"
            android:layout_marginBottom="48dp"
            android:text="@string/add_member_button_add"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@+id/add_member_group_id"
            app:layout_constraintStart_toStartOf="@+id/add_member_group_id"
            app:layout_constraintTop_toBottomOf="@+id/add_member_user_id" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
  1. 在您的自定义 DialogFragment 中:
  • 将对话框的宽度和高度指定为MATCH_PARENT:
dialog?.window?.setLayout(
    LinearLayout.LayoutParams.MATCH_PARENT,
    LinearLayout.LayoutParams.MATCH_PARENT
)
  • 设置无背景主题:
<style name="NoBackgroundDialogTheme" parent="Theme.AppCompat.Light.Dialog">
    <item name="android:windowBackground">@null</item>
</style>

自定义对话框片段:

Java:

public class MyDialogFragment extends DialogFragment {

    @Nullable
    @org.jetbrains.annotations.Nullable
    @Override
    public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        return inflater.inflate(
                R.layout.dialog_layout, container,
                false
        );
    }

    @Override
    public int getTheme() {
        return R.style.NoBackgroundDialogTheme;
    }

    @Override
    public void onStart() {
        // Making the dialog full screen
        if (getDialog() != null)
            getDialog().getWindow().setLayout(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT
            );
        super.onStart();
    }
}

科特林:

class MyDialogFragment : DialogFragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        return inflater.inflate(
            R.layout.dialog_layout, container,
            false
        )
    }

    override fun getTheme(): Int = R.style.NoBackgroundDialogTheme

    override fun onStart() {
        super.onStart()
        // Making the dialog full screen
        dialog?.window?.setLayout(
            LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT
        )

    }

}

注意:我假设对话框布局是 R.layout.dialog_layout

更新

now if I click on empty space around the Dialog, it doesn't close.

这是因为对话框片段占用了整个屏幕大小;您可以通过以下解决方法解决此问题:

  • 在最外层添加一个 ID ConstraintLayout,假设它是 root >> 在顶部布局上更新
  • 在内部添加一个ID ConstraintLayout,假设它是main_layout >> 在顶部布局上更新
  • 单击 root 时关闭对话框
  • 单击 main_layout 以消耗事件时不执行任何操作,这样它就不会被关闭:

因此,将 MyDialogFragmentonStart() 更新为:

override fun onStart() {
    super.onStart()
    // Making the dialog full screen
    dialog?.window?.setLayout(
        LinearLayout.LayoutParams.MATCH_PARENT,
        LinearLayout.LayoutParams.MATCH_PARENT
    )

    
    val root = requireView().findViewById<ConstraintLayout>(R.id.root)
    root.setOnClickListener {
        dismiss() // Dismiss the dialog
    }
    
    val main = requireView().findViewById<ConstraintLayout>(R.id.main_layout)
    main.setOnClickListener {
        // Consume the event
    }

}