【问题标题】:Collapsing layout during scrolling in Android在Android中滚动时折叠布局
【发布时间】:2025-12-02 20:40:01
【问题描述】:

我希望自定义视图在滚动期间折叠并带有过渡。

我有AppBarLayout,里面有一个Toolbar。下面有一个我想折叠的自定义视图。

自定义视图下方有一个NestedScrollViewLinearLayout

工具栏为绿色,自定义布局为粉色,线性滚动为灰色:

向下滚动后:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

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

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


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="170dp"
        android:layout_marginTop="?attr/actionBarSize"
        android:background="@drawable/background"
        android:gravity="center">
    </RelativeLayout>

    <ScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="170dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <include
            layout="@layout/linear"
            android:layout_marginBottom="20dp"
            android:layout_marginTop="20dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </ScrollView>

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

我应该使用自定义行为和CoordinatorLayout 还是使用带有翻译动画的NestedScroll 进行翻译?

【问题讨论】:

  • 对我来说,我会将您的自定义视图包装到 CollapsingToolbarLayout 中并使用自定义行为。或者,您可能还想使用 OnOffsetChangedListenerAppBarLayout 进行此转换。
  • @rom4ek 是否可以在CollapsingToolbarLayout 的自定义位置放置两个图像视图?
  • 您可以将它们保存在您现在拥有的 RelativeLayout 中。只需将这个RelativeLayout 放在CollapsingToolbarLayout 中。
  • @rom4ek 但上部工具栏(带抽屉的)保持不变,CollapsingToolbarLayout 用于在 AppBarLayout 内部使用
  • 是的,你是对的。但是您不需要将工具栏保留在AppBarLayout 中。你可以把它从AppBarLayout 中拉出来,然后放在你的xml 中AppBarLayout 之后。所以你的AppBarLayout 将只包含一个CollapsingToolbarLayout,里面有你的自定义视图。检查我的回答*.com/a/44647978/3225458,这不是你想要实现的,但你至少可以从中理解xml结构。

标签: android android-coordinatorlayout android-collapsingtoolbarlayout coordinator-layout nestedlayout


【解决方案1】:

【讨论】:

    【解决方案2】:

    我已经设法在没有任何库的情况下做到了这一点。关键是要有两种应用栏布局 - 一种具有占位符和隐藏在自定义视图下的折叠工具栏布局,另一种是普通的。

    然后我创建了两种行为 - 一种用于更改嵌套布局高度,第二种用于操作自定义视图中的内部视图。

    这是我的布局:

    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    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="wrap_content">
    
        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:titleEnabled="false">
    
            <View
                android:id="@+id/vieItemDetailsPlaceholder"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#00000000" />
    
        </android.support.design.widget.CollapsingToolbarLayout>
    
    </android.support.design.widget.AppBarLayout>
    
    <android.support.design.widget.AppBarLayout
        android:id="@+id/second_app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/second_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </android.support.design.widget.AppBarLayout>
    
    <android.support.v4.widget.NestedScrollView
        android:id="@+id/detailContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="com.example.detail.view.Det ailScrollBehavior">
    
        <include
            layout="@layout/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp" />
    
    </android.support.v4.widget.NestedScrollView>
    
    <!-- second layout with behavior -->
    <include layout="@layout/two_circles_layout" />
    
    </android.support.design.widget.CoordinatorLayout>
    

    DetailScrollBehavior:

    public class DetailScrollBehavior extends Behavior<NestedScrollView> {
    
        private final Context context;
    
        public DetailScrollBehavior(Context context, AttributeSet attrs) {
            this.context = context;
        }
    
        @Override
        public boolean layoutDependsOn(CoordinatorLayout parent, NestedScrollView child, View dependency) {
            return dependency.getId() != R.id.ablItemDetailsSecondToolbar && dependency instanceof AppBarLayout;
        }
    
        @Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, NestedScrollView child, View dependency) {
            int minHeight = context.getResources().getDimensionPixelSize(R.dimen.some_min_height);
            int placeholderHeight = getPlaceholderHeight(dependency);
            int actionBarHeight = getActionBarHeight(context.getTheme());
    
            if (placeholderHeight < minHeight + actionBarHeight) {
                placeholderHeight = minHeight + actionBarHeight;
            }
    
            child.setPadding(0, placeholderHeight, 0, 0);
    
            return true;
        }
    }
    

    two_circles_layout的一部分:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/relDetailsContainer"
        android:layout_width="match_parent"
        android:layout_height="@dimen/team_vs_details_height"
        android:layout_marginTop="?attr/actionBarSize"
        android:background="@drawable/background"
        android:gravity="center"
        app:layout_behavior="com.example.DetailBehavior"
        tools:showIn="@layout/activity_item_detail">
    
    
        [ ... ]
    
    </RelativeLayout>
    

    【讨论】:

    • 能否请您发布 two_circles_layout.xml 的内容和自定义行为?
    • 你有任何教程视频/写的来学习这些东西吗?找了好久?
    • 你能把资源放到以下几行:- (app:layout_behavior="com.example.detail.view.DetailScrollBehavior") - (layout="@layout/content") - (layout=" @layout/two_circles_layout") 他们都给出错误:(
    • @LidorEliyahuShelef 添加了
    • @pixel in the two_circles_layout in the [ . . . ] area 是什么意思?我的意思是它是开始布局还是最终布局,或者是你在里面移动他的视图并改变它们的布局?