7

I would like to have custom view collapsed with a transition during scrolling.

I have AppBarLayout with a Toolbar inside. Below that there is a custom view that I want to collapse.

Below custom view there is a NestedScrollView with LinearLayout.

Toolbar is green, custom layout is pink and scroll with linear is gray:

toolbar custom view and

After scrolling down:

scrolled down

<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>

Should I go with custom behavior and CoordinatorLayout or translation with NestedScroll with translation animation?

pixel
  • 24,905
  • 36
  • 149
  • 251
  • As for me, I would wrap your custom view into `CollapsingToolbarLayout` and go with custom behavior. Or you might want to use `OnOffsetChangedListener` of `AppBarLayout` for this transition as well. – romtsn Jul 01 '17 at 12:31
  • @rom4ek would it be possible to have two image views placed in custom place on `CollapsingToolbarLayout`? – pixel Jul 01 '17 at 21:10
  • You can keep them in the same `RelativeLayout` that you have right now. Just place this `RelativeLayout` inside `CollapsingToolbarLayout`. – romtsn Jul 01 '17 at 21:15
  • @rom4ek but upper toolbar (that with drawer) remains intact, and `CollapsingToolbarLayout` is meant to be used inside `AppBarLayout` – pixel Jul 02 '17 at 12:23
  • yes, you're right. But you don't need to keep the toolbar inside `AppBarLayout`. You can pull it out of `AppBarLayout`, and place right after `AppBarLayout` in your xml. So your `AppBarLayout` will just contain a `CollapsingToolbarLayout` with your custom view inside. Check my answer https://stackoverflow.com/a/44647978/3225458, it's not exactly what you want to achieve, but you can understand the xml structure from it, at least. – romtsn Jul 03 '17 at 15:07
  • @rom4ek yes, then I can use behaviors, but unexpected side efect is that my toolbar loses functionalities of clicking in up button and shadow that should be under toobar is shown under system window at top – pixel Jul 03 '17 at 15:48
  • @rom4ek - I figured it out. You need to wrap this `Toolbar` into additional `AppBarLayout` – pixel Jul 03 '17 at 15:54
  • cool, glad to help. I'd try to implement this behavior, but don't have enough time right now:( – romtsn Jul 03 '17 at 16:20
  • @rom4ek you have library for such things? :) – pixel Jul 03 '17 at 19:51
  • No, I don't have such a library, but have some plans for it now:) – romtsn Jul 04 '17 at 13:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/148326/discussion-between-pixel-and-rom4ek). – pixel Jul 04 '17 at 13:40

2 Answers2

1

Use Observable ScrollView library https://github.com/ksoichiro/Android-ObservableScrollView

Ramees
  • 68
  • 4
  • 16
1

I've managed to do this without any library. The key was to have two app bar layouts - one with a placeholder and collapsing toolbar layout that was hidden under custom view, and the second normal one.

Then I've created two behaviors - one for changing nested layout height and second to manipulate inner views inside custom view.

Here is my layout:

<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;
    }
}

and part of 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>
pixel
  • 24,905
  • 36
  • 149
  • 251
  • 1
    Could you please post the two_circles_layout.xml content and custom behaviors? – Ivan Apr 04 '19 at 20:10
  • do you have any tutorial video / written in to learn this stuff? I've been looking for a long time? – Lidor Eliyahu Shelef Jan 19 '21 at 19:27
  • can you the resource to the lines: - (app:layout_behavior="com.example.detail.view.DetailScrollBehavior") - (layout="@layout/content") - (layout="@layout/two_circles_layout") All of them gives errors :( – Lidor Eliyahu Shelef Jan 19 '21 at 19:37
  • @LidorEliyahuShelef added – pixel Jan 20 '21 at 10:59
  • @pixel in the `two_circles_layout` in the `[ . . . ]` area what was meant to be? I mean is it the start layout or the final layout or it's the layout youre moving his view inside and changing them? – Lidor Eliyahu Shelef Jan 20 '21 at 11:26
  • Those layout elements like circles etc, I redacted them since they are not key of the answer – pixel Jan 20 '21 at 12:23
  • It is key b/c the `DetailScrollBehavior` have red errors, and we need to know which one means what, and also the `DetailScrollBehavior` doesn't recognizes the `getPlaceholderHeight` and the `getActionBarHeight` methods. plus you didnt say what the `@layout/content` b/c it gives and error there also – Lidor Eliyahu Shelef Jan 21 '21 at 13:16