目前我正在为Android开发一款棋盘游戏,其主要包括渐变的UI元素
为了给尽可能多的屏幕空间,并保持布局灵活,我实现了控件的片段和显示提示的另一个片段。
目前我正在使用以下布局:
<?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">
<FrameLayout
android:id="@+id/input_and_hints_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<some.package.BoardView
android:id="@+id/board"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_above="@id/input_and_hints_container" />
</RelativeLayout>
当活动开始时,它将controls-fragment放入FrameLayout。控件包含一个显示提示的按钮(如果适用),它使用show-hints-fragment替换controls-fragment。 show-hints-fragment有一个dismiss按钮,用control-fragment替换show-hints-fragment。
我的问题是,show-hints-fragment可能占用比控件片段更多(或更少)的空间,这会导致电路板的大小调整。 (只要没有方向改变,我宁愿保持电路板尺寸稳定。)
我想到了两种可能的方法来保持布局稳定:
将controls-fragment的初始大小保持为状态,为show-hints-fragment实现自定义视图,并让它在onMeasure中返回相同的维度。我的直觉是,这是过于复杂而且相当丑陋。我认为必须有一个更优雅的解决方案。
使用ViewPager包含两个片段。我之前从未使用过ViewPager,所以我只是推测这会保持布局稳定。
肯定会有更多的选择,所以我想知道最好的方法是什么。
谢谢&amp;一切顺利。
答案 0 :(得分:0)
经过一番研究后,我决定实现自己的自定义ViewGroup。从需要编写的少量状态和代码来判断,这似乎是一个可行的解决方案。
我使用this article作为起点。
我的解决方案削减了很多角落(基于领域知识) - 它从下到上列出了它的孩子。最后一个孩子只需要剩余的空间。 一个特定的孩子得到一个不同的(精确的)测量规范,以保持稳定:
public class PlayViewGroup extends ViewGroup {
private int mMeasuredControlHeight = -1;
public PlayViewGroup(final Context context) {
super(context);
}
public PlayViewGroup(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) {
final int width = r - l;
final int height = b - t;
int currentChildBottom = height;
for(int i=0; i <this.getChildCount(); i++){
final View view = getChildAt(i);
final int childLeft = (width - view.getMeasuredWidth()) / 2;
final int childRight = width - childLeft;
final int childTop = currentChildBottom - view.getMeasuredHeight();
view.layout(childLeft, childTop, childRight, currentChildBottom);
currentChildBottom -= view.getMeasuredHeight();
}
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wspec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
int remainingHeight = getMeasuredHeight();
for (int i=0; i<getChildCount(); i++) {
boolean controlPanelFound = false;
final View view = getChildAt(i);
int hspec = MeasureSpec.makeMeasureSpec(remainingHeight, MeasureSpec.AT_MOST);
if (view.getId() == R.id.input_and_hints_container) {
final FrameLayout mContainer = (FrameLayout) view;
if (mContainer.getChildCount() == 1) {
final View containedView = mContainer.getChildAt(0);
if (containedView instanceof InputPanel) {
controlPanelFound = true;
} else if (containedView != null && mMeasuredControlHeight > 0) {
hspec = MeasureSpec.makeMeasureSpec(mMeasuredControlHeight, MeasureSpec.EXACTLY);
wspec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY);
}
}
}
view.measure(wspec, hspec);
if (controlPanelFound) {
mMeasuredControlHeight = view.getMeasuredHeight();
}
remainingHeight -= view.getMeasuredHeight();
}
}
}