当CollapsingToolbarLayout展开时,折叠内容而不是滚动。

8

我使用安卓的CollapsingToolbarLayout创建了一个简单的项目,下面是它的结构(完整布局源代码在问题底部):

CoordinatorLayout
  AppBarLayout
    CollapsingToolbarLayout
      Toolbar
  RelativeLayout (layout_behavior="@string/appbar_scrolling_view_behavior")
    TextView (layout_alignParentTop="true")
    TextView (layout_alignParentBottom="true")

当我展开/折叠工具栏时,视图会滚动并且底部视图超出屏幕:enter image description here 我要实现的是将内容(我的RelativeLayout)折叠/缩小(而不是滚动),以使底部文本始终可见:enter image description hereenter image description here 如何在Android上实现?
这是我的完整布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:toolbarId="@+id/toolbar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:text="The text on the top"
            android:textSize="32sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="The text on the bottom"
            android:textSize="32sp"/>
    </RelativeLayout>

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

我正在寻找非常相似的东西。谢谢。 - filthy_wizard
3个回答

6
这里真正的问题是如何在应用栏高度改变时正确调整RelativeLayout的大小。在查看如何做到这一点之前,我们需要对XML布局进行更改。
来自AppBarLayout文档

AppBarLayout还需要一个单独的可滚动兄弟,以便知道何时滚动。

由于RelativeLayout不符合“可滚动兄弟”的条件,因此我们需要将其包含在一个诸如“NestedScrollView”之类的兄弟中。以下是更新后的XML文件:

activity_main.xml

<android.support.design.widget.CoordinatorLayout 
    android:id="@+id/coordinatorLayoutProfile"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="220dp"
            android:background="@color/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?android:attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

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

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

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:id="@+id/relativeLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/holo_blue_light">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:text="The text on the top"
                android:textSize="32sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:text="The text on the bottom"
                android:textSize="32sp" />
        </RelativeLayout>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

我可能对XML进行了一些其他更改,以使其在我的环境中正常工作,但除了插入NestedScrollView之外,不应有任何实质性的更改。 RelativeLayout的大小更改将在代码中设置,并由AppBarLayout.OnOffsetChangedListener触发。我们将根据应用程序栏的垂直偏移量计算并更改RelativeLayout的大小。

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private RelativeLayout mRelativeLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mRelativeLayout = findViewById(R.id.relativeLayout);
        final AppBarLayout appBarLayout = findViewById(R.id.appBar);
        final int screenHeight = getResources().getDisplayMetrics().heightPixels;

        appBarLayout.post(new Runnable() {
            @Override
            public void run() {
                adjustRelLayoutHeight(mRelativeLayout, screenHeight - appBarLayout.getBottom());
            }
        });

        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                adjustRelLayoutHeight(mRelativeLayout, screenHeight - appBarLayout.getBottom());
            }
        });
    }

    private void adjustRelLayoutHeight(RelativeLayout layout, int newHeight) {
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) layout.getLayoutParams();
        lp.height = newHeight;
        layout.setLayoutParams(lp);
    }

    private static final String TAG = "MainActivity";
}

这里是结果:

enter image description here

更新:以下是另一种方法,使用ViewTreeObserver.OnPreDrawListener(),避免了额外的绘制。然而,效果是相同的:

MainActivity.java(另一种方法)

public class MainActivity extends AppCompatActivity {
    private RelativeLayout mRelativeLayout;
    private int mCoordinatorHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mRelativeLayout = findViewById(R.id.relativeLayout);
        final AppBarLayout appBarLayout = findViewById(R.id.appBar);

        final CoordinatorLayout coordinatorLayout =
            (CoordinatorLayout) findViewById(R.id.coordinatorLayoutProfile);
        // Wait for just before drawing the view to get its height.
        coordinatorLayout.getViewTreeObserver()
            .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    // Remove the listener so we don't go into an infinite loop.
                    coordinatorLayout.getViewTreeObserver().removeOnPreDrawListener(this);
                    mCoordinatorHeight = coordinatorLayout.getHeight();
                    adjustRelLayoutHeight(mRelativeLayout, mCoordinatorHeight - appBarLayout.getBottom());
                    return false; // abort drawing
                }
            });

        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                adjustRelLayoutHeight(mRelativeLayout, mCoordinatorHeight - appBarLayout.getBottom());
            }
        });
    }

    private void adjustRelLayoutHeight(RelativeLayout layout, int newHeight) {
        if (newHeight <= 0) {
            // no-op if height is invalid
            return;
        }
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) layout.getLayoutParams();
        if (lp.height != newHeight) {
            lp.height = newHeight;
            layout.setLayoutParams(lp);
        }
    }

    private static final String TAG = "MainActivity";
}

1

不要使用带有layout_behavior="@string/appbar_scrolling_view_behavior"的RelativeLayout,而应选择NestedScrollingView或RecyclerViw以使一切按预期工作。

正如这里所述

滚动内容应放置在RecyclerView、NestedScrollView或支持嵌套滚动的其他视图中。

考虑到您的布局,我猜您需要将RelativeLayout放在NestedScrollingView内,并将layout_behavior分配给NestedScrollingView,并从RelativeLayout中删除layout_behavior。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:toolbarId="@+id/toolbar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>

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

    <NestedScrollView android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height= "match_parent">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:text="The text on the top"
                android:textSize="32sp"/>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:text="The text on the bottom"
                android:textSize="32sp"/>
        </RelativeLayout>
    </NestedScrollView>

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

编辑 2017年11月4日下午4:58

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:fitsSystemWindows="true">

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:fitsSystemWindows="true">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:fitsSystemWindows="true"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.design.widget.CollapsingToolbarLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                app:contentScrim="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|exitUntilCollapsed"
                app:toolbarId="@+id/toolbar">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="pin"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

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


        <android.support.v4.widget.NestedScrollView android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignParentTop="true"
                    android:text="The text on the top"
                    android:textSize="32sp"/>

            </RelativeLayout>

        </android.support.v4.widget.NestedScrollView>

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="The text on the bottom"
        android:textSize="32sp"/>

</LinearLayout>

现在它的功能如下所示。

Result View


我已经尝试了您的解决方案,但结果是两个文本重叠在同一位置 - RelativeLayout 没有填满 ActionBar 下面的整个空间,而只是包裹着文本。 - Piotr Aleksander Chmielowski
谢谢,但它仍然没有解决主要问题,即折叠内容而不是滚动。我正在寻找一种解决方案,可以让我在一个RelativeLayout上保留两个TextView,并在工具栏折叠时更改布局高度。 - Piotr Aleksander Chmielowski
1
哦,那看起来可以通过自定义CoordinatorBehaviour实现。我无法为您提供确切的解决方案,但请查看Ian Lake发布的这篇文章https://medium.com/google-developers/intercepting-everything-with-coordinatorlayout-behaviors-8c6adc140c26。也许它会给您一些有价值的提示。 - Eugene Brusov
我需要在AppBarLayout展开时缩小Scichart。这可能吗?对我来说似乎不起作用。 - filthy_wizard

0

我认为你需要在 Relative 全部代码的结尾处关闭你的 Coordinator layout。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:toolbarId="@+id/toolbar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:text="The text on the top"
            android:textSize="32sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="The text on the bottom"
            android:textSize="32sp"/>
    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

2
他已经关闭了CoordinatorLayout。请现在检查编辑后的问题 :) - Ranjithkumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接