Android:如何在替换片段时保持布局稳定?

时间:2015-04-10 13:58:34

标签: android android-layout android-fragments

目前我正在为Android开发一款棋盘游戏,其主要包括渐变的UI元素

  • 董事会(惊喜!)
  • 对照
  • 用于显示提示的TextView和用于关闭显示提示的按钮

为了给尽可能多的屏幕空间,并保持布局灵活,我实现了控件的片段和显示提示的另一个片段。

目前我正在使用以下布局:

<?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可能占用比控件片段更多(或更少)的空间,这会导致电路板的大小调整。 (只要没有方向改变,我宁愿保持电路板尺寸稳定。)

我想到了两种可能的方法来保持布局稳定:

  1. 将controls-fragment的初始大小保持为状态,为show-hints-fragment实现自定义视图,并让它在onMeasure中返回相同的维度。我的直觉是,这是过于复杂而且相当丑陋。我认为必须有一个更优雅的解决方案。

  2. 使用ViewPager包含两个片段。我之前从未使用过ViewPager,所以我只是推测这会保持布局稳定。

  3. 肯定会有更多的选择,所以我想知道最好的方法是什么。

    谢谢&amp;一切顺利。

1 个答案:

答案 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();
        }
    }
}
相关问题