Android: 如何使自定义视图只显示可用屏幕 space?

Android: How to make a custom view take only the available screen space?

我有两个自定义视图,我想对其进行垂直布局。 第一个视图是一种游戏板,它是一个正方形。正方形很容易缩放,几乎可以适应任何可用的 space.

第二个视图是 [TableLayout][1] 的子类,其中包含多个 Button。 rows/columns的数量是在运行时确定的。

为了便于解释,我将第一个视图称为 board,将第二个视图称为 table.

我希望 board 显示在屏幕顶部,table 应该在它的正下方。 Table 应该取它需要的垂直 space (这基本上取决于行数)。 Board 应将其方形边缘尺寸设置为可用宽度和可用高度中的最小值,即按比例缩小。

我尝试使用 [RelativeLayout][2] 实现此目的,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="@dimen/default_padding"
                >

    <some.package.Table
        android:id="@+id/table"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="@dimen/default_padding"
        />

    <some.package.Board
        android:id="@+id/board"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_above="@id/table"
        />
</RelativeLayout>

通过这种方法,我希望首先测量 table 并将剩余的可用屏幕高度作为最大值传递(即 AT_MOST ) boardonMeasure 的高度规格。这个假设似乎是错误的。

当我使用这个布局时,板似乎被调整为零大小,即它没有被渲染。

当我这样扭转局面时:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="@dimen/default_padding"
                >

    <some.package.Board
        android:id="@+id/board"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        />

    <some.package.Table
        android:id="@+id/table"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="@dimen/default_padding"
        android:layout_below="@id/board"
        />
</RelativeLayout>

board 占据太多垂直 space 并且 table 在底部被切断

在这两种情况下,board 显示宽度为 AT_MOST 宽度规格,显示高度(减去状态栏和操作栏高度)为 AT_MOST高度规格所以我的 onMeasure 实现采用两者中的最小值作为正方形大小,这没有为 table 视图留出足够的空间。

谁能告诉我如何处理这个问题,好吗? 我可能需要添加嵌套布局吗?或者使用布局权重? - 我没有这样做,因为在我的理解中权重是相对大小的。

谢谢和亲切的问候


在 Gabe 的回答后编辑:

在尝试了 Gabe 的建议后,我在 boardtableonMeasure 方法中记录了一些数据:

table: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=1006
board: wM=AT_MOST minW=0 ws=736 hM=AT_MOST minH=0 hs=1006
board: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=1006
table: wM=EXACTLY minW=0 ws=736 hM=AT_MOST minH=0 hs=0
I/Choreographer﹕ Skipped 206 frames!  The application may be doing too much work on its main thread.
D/dalvikvm﹕ GC_FOR_ALLOC freed 305K, 8% free 4880K/5252K, paused 103ms, total 105ms
table: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=1006
board: wM=AT_MOST minW=0 ws=736 hM=AT_MOST minH=0 hs=1006
board: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=1006
table: wM=EXACTLY minW=0 ws=736 hM=AT_MOST minH=0 hs=0

wM 是MeasureSpec 的宽度模式,minW 是getSuggestedMinimumWidth(),ws 是MeasureSpec 的宽度大小。 这同样适用于 hM、minH 和 hs。

我在 tablenot 覆盖了 onMeasure(是的,我有,但它只是记录数据并调用 super.onMeasure())。 board.onMeasure() 中实现的行为如上所述。

我还在疑惑...


在 kha 的回答后编辑:

kha 的建议奏效了。工作 XML 布局是

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="@dimen/default_padding"
                >

    <some.package.Table
        android:id="@+id/table"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="@dimen/default_padding"
        android:layout_alignParentBottom="true"
        />

    <some.package.Board
        android:id="@+id/board"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_above="@id/table"
        />

</RelativeLayout>

日志输出现在是:

board: wM=AT_MOST minW=0 ws=736 hM=AT_MOST minH=0 hs=1006
table: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=1006
table: wM=EXACTLY minW=0 ws=736 hM=AT_MOST minH=0 hs=1006
board: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=702
I/Choreographer﹕ Skipped 118 frames!  The application may be doing too much work on its main thread.
board: wM=AT_MOST minW=0 ws=736 hM=AT_MOST minH=0 hs=1006
table: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=1006
table: wM=EXACTLY minW=0 ws=736 hM=AT_MOST minH=0 hs=1006
board: wM=EXACTLY minW=0 ws=736 hM=EXACTLY minH=0 hs=702

相对布局中视图的顺序决定了它们重叠时的 z 顺序,而不是它们的绘制顺序。此外,权重只对线性布局起作用,对相对布局不起作用。

第二个 XML 几乎是正确的 - 它会测量出 table,让它占用尽可能多的空间,然后在它下面布置电路板。将板的高度更改为 match_parent 它应该可以工作 - 它会强制它占用的空间不超过剩余空间。

试试这个:

移动并更改

android:layout_below="@id/board" 

android:layout_above="@id/table" 

在您的其他布局上。

结合 table 布局上的设置 android:alignParentBottom=true 执行此操作。