如何使用数据绑定为GridLayout单元设置行/列号?

时间:2018-08-14 14:03:37

标签: android android-layout android-databinding android-gridlayout android-mvvm

我有一个具有挑战性的用例。我需要在Android平板电脑上并排(水平)显示2个“面板”。一个面板(按钮面板)显示了一组相关的按钮。另一个面板(信息面板)显示文本和按钮的组合。我们正在尝试使用MVVM体系结构模式(这使我们走上了数据绑定之路)。

要求是:

  1. 基于可观察的布尔标志(buttonsOnLeft),按钮面板可以显示在左侧或右侧。信息面板移到另一侧。
  2. 按钮面板的内容取决于另一个变量(guidedModeState),并且该面板的宽度根据其内容而变化(在一种模式下,一列包含3个按钮,在另一种模式下,包含2列每个3个按钮)
  3. 按钮面板的宽度应适合其内容宽度,信息面板应吸收任何多余的宽度

我尝试了几种不同的结果混合的选项(主要是RelativeLayout和LinearLayout的组合)。现在,我正在尝试使用GridLayout并已使某些功能正常工作,但是有些部分具有代码异味。

结合使用layout_width和layout_columnWeight属性,我可以根据需要获取要增加/缩小的列宽。以下是布局XML文件中的重要属性:

<!-- Panels -->
<android.support.v7.widget.GridLayout
    xmlns:grid="http://schemas.android.com/apk/res-auto"
    grid:alignmentMode="alignBounds"
    grid:columnCount="2"
    grid:rowCount="1"
    ... 
>
    <!-- Up/Down Button Panel -->
    <!-- columnWeight = 0 means this panel is fixed width -->
    <RelativeLayout
        grid:layout_column="@{vm.buttonsOnLeft ? 0 : 1,default=0}"
        grid:layout_row="0"
        grid:layout_columnWeight="0"
        grid:layout_rowWeight="1"
        grid:layout_gravity="fill"
        ...
    >
    <!-- Info Panel -->
    <!-- columnWeight = 1 means absorbs available width -->
    <RelativeLayout
        grid:layout_column="@{vm.buttonsOnLeft ? 1 : 0,default=1}"
        grid:layout_row="0"
        grid:layout_columnWeight="1"
        android:layout_width="0dp"
        grid:layout_rowWeight="1"
        grid:layout_gravity="fill"
        ... 
    >

使用GridLayout,可以为每个单元格任意设置列,这意味着布局XML中的视图顺序无关紧要。但是,无法使用“开箱即用”的数据绑定表达式来设置列号。您需要一个自定义绑定适配器才能根据表达式设置列号。

我从BindingAdaptor开始设置基本上看起来像这样的列号:

@BindingAdapter("grid:layout_column")
public static void setLayoutColumn(View view, int col) {
    GridLayout.LayoutParams lp = new GridLayout.LayoutParams(view.getLayoutParams());
    lp.columnSpec = GridLayout.spec(col);
    view.setLayoutParams(lp);
}

此版本使我可以基于表达式动态更改列号,但是它清除了columnSpec中的任何其他字段,包括列宽和布局权重,这是允许一列吸收多余空间所需的

这里的问题是:如何在绑定适配器中操纵columnSpec来仅更改列号,而保留其他值。

我的kudget解决方案是查看宽度并设置权重,但是我不喜欢这种方法。另一个副作用是单元格边距被覆盖,这意味着我还需要更改这些边距。最好的解决方案是保留所有现有的columnSpec值,而仅更改起始列号字段。

更新后的BindingAdaptor看起来像这样:

@BindingAdapter("grid:layout_column")
public static void setLayoutColumn(View view, int col) 
{
    GridLayout.LayoutParams lp = new GridLayout.LayoutParams(view.getLayoutParams());
    if (lp.width == 0) {
        // width 0 means that we want this column to fill available width. use weight = 1.0f
        lp.columnSpec = GridLayout.spec(col,1,GridLayout.FILL,1.0f);
    } else {
        // width non-zero means that this column is fixed width. use weight = 0.0f
        lp.columnSpec = GridLayout.spec(col,1,GridLayout.FILL,0.0f);
    }
    // fix margins. row gets 10 pixels on left and right edges, and 10 between the cells
    lp.leftMargin = col == 0 ? 10 : 5;
    lp.rightMargin = col == 0 ? 5 : 10;
    view.setLayoutParams(lp);
}

关于如何实现此目标的任何建议?

0 个答案:

没有答案