【问题标题】:How to set Dialog width and height in percents in XML如何在 XML 中以百分比设置对话框的宽度和高度
【发布时间】:2021-11-07 02:28:48
【问题描述】:

我需要我的 Dialog 宽度和高度填充 70% 的屏幕空间。我使用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>

【问题讨论】:

    标签: java android xml android-constraintlayout android-dialogfragment


    【解决方案1】:

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

    1. 将您的ConstraintLayout 包裹到另一个ConstraintLayout 中,以使外部占据屏幕的全尺寸,内部获得所需的宽度/高度百分比:

    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

    更新

    现在,如果我单击对话框周围的空白区域,它不会关闭。

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

    • 在最外面的ConstraintLayout添加一个ID,假设它是root >>在顶部布局更新
    • 给内部ConstraintLayout添加一个ID,假设它是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
        }
    
    }
    

    【讨论】:

    • 它有效,谢谢。但是有一个问题 - 现在如果我单击对话框周围的空白区域,它不会关闭。在我看来这是因为没有物理空白,只有视觉,因为父ConstraintLayout的宽度和高度设置为match_parent
    • @RomanKnyazev 请检查答案中的更新部分,希望现在解决
    【解决方案2】:

    约束布局:

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

    我的示例显示了一个TextView(可能是您的ConstraintLayout(所有内容的框架),它在屏幕的垂直和水平方向上正好有70% (app:layout_constraintGuide_percent="0.7")。重要的是设置TextViews widthheight0dp 并附加到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.70

    请记住将width 或/和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>
    

    【讨论】:

    • 这对 Dialog 不起作用。当我打开对话框时,我只是变暗了屏幕(对话框背景)。要使用指南来定义对话框大小,根布局大小必须等于父布局。在我看来,这就是问题所在。在原始代码中,根布局大小等于对话框的大小。
    • Dialog 是什么意思?它是小部件的名称吗?在您的代码中,我只看到一些看起来像“对话框”的 TextView 和布局,但它是同义词,没有小部件。我的回答中有两个选项。使用 ConstraintLayout 或 LinearLayout。有了它,您想要实现的一切都是可能的。如果您有其他 Dialog 代码,请提供。在你的问题中根本没有 Dialog :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 2014-02-17
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多