Android: 自定义对话框的尺寸不精确

Android: Custom Dialog's sizing is unprecise

我正在尝试为我的应用程序创建自定义对话框视图。 当运行程序运行时,结果和我预想的大相径庭

XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorPrimaryDark">

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@color/colorAccent">
</LinearLayout>

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary">

    <Button
        android:id="@+id/button10"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />
</LinearLayout>
</LinearLayout>

Java class:

public class SinglePSettings extends AppCompatDialogFragment {

    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        LayoutInflater inflater = getActivity().getLayoutInflater();

        View view = inflater.inflate(R.layout.layout_singlepsettings, null);
        builder.setView(view)
               .setTitle("Settings");

        return builder.create();
    }

    public void onResume()
    {
        super.onResume();
        Window window = getDialog().getWindow();
        Point size = new Point();
        Display display = window.getWindowManager().getDefaultDisplay();
        display.getSize(size);
        int width = (int)(size.x * 0.90);
        int height = (int)(size.y * 0.90);
        window.setLayout(width, height);
        window.setGravity(Gravity.CENTER);
    }

我不太明白为什么主要的LinearLayout是'invisible'。里面的物品似乎也不依赖于它。有没有办法用布局填充对话框块的全尺寸?

(当然后面我可以进一步定制。)

这是因为您对话的根布局的高度为 match_parent,第一个内容的总大小为 200dp child Linearlayout + 第二个为 ~24 dp child Linearlayout 小于对话框的总大小。

您应该将 parent LinearLayout 的高度更改为 wrap_content 或将 android:weight=1 添加到任一 child LinearLayouts。


让我试着解释一下线性布局的工作原理。请注意,这些都是经验之谈,您应该阅读官方文档以更好地理解。

符合orientation的维度对于线性布局的children起着至关重要的作用。因此,如果方向是水平的,那么所有的children都会水平堆叠,需要控制它们的width属性。

将水平线性布局想象成一个家。目前,假设您始终必须在 parent 线性布局中将 crucial 属性保持为 match_parent。因此我们的线性布局/家有 width=match_parent。 children的加法主要有3种:

将每个 child 保持为 wrap_content

  • 这意味着每个 child 将占用屏幕 space 等于其自身大小的数量。

  • 如果项目数量较少或屏幕尺寸足够大,此方法可行。

  • 但是如果有很多大件,那么他们所需要的总space=他们所有的宽度之和。如果此总和大于屏幕尺寸,则 部分项目会超出屏幕。

  • 在我们家的类比中,就好像我们把所有的table、椅子、床等堆成一条直线。如果space比两个端墙之间的space少,那很好,但如果他们需要更多的水平space,那我们就必须打破墙来调整它们。

  • 因此不建议将所有项目都保留为 wrap content

保持一个或多个children作为match_parent

  • 这是一种非常错误的做法。当您将 child 的宽度保持为 match_parent 时,您基本上是在告诉编译器为这个单一视图提供 完整屏幕 space

  • 而且编译器肯定会这样做。即使它是一个按钮,它也会在整个屏幕上展开并且其他视图将不可见,因为它们实际上在屏幕之外。

  • 当有多个视图 width=match_parent 时,它会简单地将整个屏幕 space 分配给左数第一个视图。

  • 在我们家的类比中,就像您将椅子的宽度属性更改为 match_parent 一样,房间神奇地扩展了它以占据完整的 space,并且因此你的床,table,等等现在都被挤在房间的一侧。

保持 layout_weight=x 一或多个 children

  • 这是线性布局中使用的最佳方法。我将其视为 将屏幕百分比 分配给视图。

  • 如果您的 child 视图具有 weight=x,则它不会受到您视图 crucial attribute 中存在的值的影响。这意味着您可以有 width= match_parentwrap_content 甚至 1000000dp,如果它有 weight=x,它将呈现为全屏视图。请注意,我只是在谈论一个关键属性,即本例中的宽度。

  • 了解具有权重的视图将如何影响其他视图也很有趣。

    • 如果另一个视图具有 width = match_parent(并且没有权重属性),则该视图将占据整个屏幕 space,但是这次 我们的权重视图不会被压扁。相反,这会得到它应该得到的最小值 space(即 wrap_content 或我们为 width=x 传递的固定值)。这就像我们为我们的椅子添加了 weight 属性,为我们的床添加了 match_parent 属性。床压扁了所有其他物品,但椅子仍然占据了它需要的 space。

  • 当其他项目将 wrap_content 作为其关键属性(但没有权重属性)的值时,也会发生类似的情况。这一次,有权重的视图将占用所有 space,除了其他视图所需的 space(将下图与第一种情况进行比较,注意圆圈现在如何占用所有剩余的space 不挤压其他视图)

  • 每个属性都有权重时,这就变成了一个有趣的百分比游戏。如果我们有两个项目,并且每个项目都有 layout_weight=1,那么不管它们的宽度是多少,两者都会占用 space 的 50%。如果其中之一有 layout_weight=2,则分配将为 2:1,即 66%:33%。这使得视图响应不同屏幕尺寸和方向。


因此,在线性布局中使用 children 视图的最佳方法 是在其关键维度中使用 wrap_content属性和 layout_weight=x。这将使它更加灵敏并且更易于控制。此外,我没有过多谈论在关键维度属性中使用固定权重,因为处理它们总是一团糟。我不会详细介绍(您可以自己尝试),但它们总是会被压扁或压扁其他视图。