我有一个具有挑战性的用例。我需要在Android平板电脑上并排(水平)显示2个“面板”。一个面板(按钮面板)显示了一组相关的按钮。另一个面板(信息面板)显示文本和按钮的组合。我们正在尝试使用MVVM体系结构模式(这使我们走上了数据绑定之路)。
要求是:
我尝试了几种不同的结果混合的选项(主要是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);
}
关于如何实现此目标的任何建议?