【问题标题】:Android - Frame layout height not matching with coordinator layoutAndroid - 框架布局高度与协调器布局不匹配
【发布时间】:2015-12-15 12:09:42
【问题描述】:

我的 FrameLayout(抽屉布局中的容器)有问题。 FrameLayout 的高度超过屏幕高度(低于底部的android默认菜单按钮)。

<android.support.design.widget.CoordinatorLayout
        android:id="@+id/main_content"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/navContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="?attr/actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways" />

        </android.support.design.widget.AppBarLayout>

        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </android.support.design.widget.CoordinatorLayout>

【问题讨论】:

  • 我遇到了同样的问题,这是 android Coordinator 错误还是他们的任何解决方法。 (没有将边距底部作为操作栏高度的尺寸)

标签: android height matching android-framelayout


【解决方案1】:

我的第一次尝试是在 FrameLayout 中设置 android:layout_marginBottom="?attr/actionBarSize"。这解决了在没有垂直可滚动内容方面具有“固定”高度的不可滚动视图的解决方案(就像通常的具有match_parent 高度的RelativeLayout 一样)。将组件与父底部 (android:layout_alignParentBottom="true") 对齐会导致元素仍然可见。在 Android Studio 的 Previewer 中,不超过高度是可见的。

然而,这个marginBotton-fix 为根视图可滚动的片段(如RecyclerView)引入了一个新问题。对于这些视图,当向下滚动时,底部边距将在白色条中可见(如果白色是背景色)。这个接缝是合理的,对于那些视图嵌套滚动功能将滑出工具栏

tl;dr 我通过将?attr/actionBarSize 作为底部边距应用于Framelayout 内显示的不可滚动片段来解决该问题。在此之前,我将工具栏的高度设置为?attr/actionBarSize

活动布局:

        <android.support.design.widget.AppBarLayout
            android:id="@+id/navContainer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways" />

        </android.support.design.widget.AppBarLayout>

        <FrameLayout
                android:id="@+id/container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"
        />

</android.support.design.widget.CoordinatorLayout>

片段布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:layout_marginBottom="?attr/actionBarSize"
          android:orientation="vertical">
          <!-- Further stuff here -->
          <TextView android:id="@+id/label"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_alignParentBottom="true"
          />
  </LinearLayout>

我现在面临的唯一缺点是在创建片段布局时,Android Studio 的预览器中会显示空白。

【讨论】:

  • 这对我来说效果很好!作为旁注,如果您的一个片段具有隐藏应用栏的可滚动根,则在导航回前一个(不可滚动)片段时它将保持隐藏状态,无法再次显示它。这个问题有一个解决方法available here
【解决方案2】:

如果您在CoordinatorLayout 中使用不同的Fragments,您将面临问题,即一些Fragments 具有可滚动的内容,而有些则不应该滚动。您的Toolbar 具有滚动标志“scroll|enterAlways”,这对于前一种布局是可以的,但对于后者则不行。我的解决方案是自定义AppBarLayout.Behavior,它根据自定义标签(contentShouldNotScrollTag)切换滚动标志。为布局设置这个标签,它不应该像这样滚动:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:tag="@string/contentShouldNotScrollTag">
   <!-- my non-scrollable Fragment layout -->
</FrameLayout>

因此,这个 Fragment 的高度不会超过屏幕的高度。这是AppBarLayout 的自定义行为类:

public class MyScrollBehavior extends AppBarLayout.Behavior {
    private View content;

    public MyScrollBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onMeasureChild(CoordinatorLayout parent, AppBarLayout appBarLayout, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
        if(content == null) {
            content = parent.findViewById(R.id.container);
        }

        if(content != null) {
            boolean shouldNotScroll = content.findViewWithTag(parent.getContext().getString(R.string.contentShouldNotScrollTag)) != null;
            Toolbar toolbar = (Toolbar) appBarLayout.findViewById(R.id.toolbar);
            AppBarLayout.LayoutParams params =
                    (AppBarLayout.LayoutParams) toolbar.getLayoutParams();
            if (shouldNotScroll) {
                params.setScrollFlags(0);
                appBarLayout.setExpanded(true, true);
            } else {
                params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
                        | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
            }
        }

        return super.onMeasureChild(parent, appBarLayout, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 2021-11-29
    • 2021-05-03
    • 2018-06-29
    相关资源
    最近更新 更多