19

I am working on one android app in which I am using CoordinatorLayout,AppBarLayout and CollapsingToolbarLayout to use the advance collapse bar functionality.

I am using recyclerview to show the number of items in the fragment. When I'm scrolling up recyclerview it smoothly collapse AppBarLayout but when I scroll down and reach at on the first item of the recyclerview it automatically stop scrolling without expanding `AppBarLayout'.

Then again I need to scroll down again to make AppBarLayout visible. So my requirement is that on scrolling down when I reach to top of recyclerview it must expand `AppBarLayout'.

How can we do this. Any idea ? Please see video of same https://www.dropbox.com/s/va5jk27ikytk5ax/app_collapsebar_issue.mp4?dl=0

Here is my layout of same :-

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:fitsSystemWindows="true">

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

    <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:id="@+id/coordinator"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:fitsSystemWindows="true"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        >

        <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="220dp"
        android:background="@drawable/offer_image"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <!--    <com.flaviofaria.kenburnsview.KenBurnsView
            android:id="@+id/image"
            android:layout_width="match_parent"
            android:layout_height="220dp"
            android:src="@drawable/offer_image" />-->
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">


            <com.flaviofaria.kenburnsview.KenBurnsView
            android:id="@+id/image"
            android:layout_width="match_parent"
            android:layout_height="220dp"

            android:src="@drawable/offer_image" />

            <FrameLayout
            android:id="@+id/collapse_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#B3c85a00">

            </FrameLayout>

            <FrameLayout
            android:id="@+id/centerCircle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center">

            <ImageView
                android:id="@+id/imageViewCenter"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/offer" />
            </FrameLayout>

            <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar" />

            <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:layout_marginBottom="15dp"
            app:tabIndicatorColor="#FFFFFF"
            app:tabMode="scrollable" />
            <!--</FrameLayout>-->
        </android.support.design.widget.CollapsingToolbarLayout>
        </android.support.design.widget.AppBarLayout>

        <!--<FrameLayout-->

        <!--android:layout_width="match_parent"-->
        <!--android:layout_height="match_parent"-->
        <!-- -->
        <!--android:visibility="visible">-->

        <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        style="@style/floating_action_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:src="@drawable/ic_share_white_24dp"
        android:visibility="gone"
        app:backgroundTint="#FF9800"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp" />

        <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="left|bottom|fill_vertical"
        android:layout_marginTop="0dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v4.view.ViewPager>
        <!--</FrameLayout>-->

        <!--<include layout="@layout/content_scrolling" />-->

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

    <RelativeLayout
        android:id="@+id/bannerView"
        android:layout_width="match_parent"
        android:layout_height="58dp"
        android:layout_gravity="bottom|center"
        android:background="@drawable/curved_white_with_blue_border"
        android:visibility="gone">

        <TextView
        android:id="@+id/bannerText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerInParent="true"
        android:layout_centerVertical="true"
        android:gravity="center"
        android:padding="3dp"
        android:text="Banner"
        android:visibility="gone" />

        <ImageView
        android:id="@+id/bannerImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:gravity="center"
        android:padding="3dp"
        android:scaleType="fitXY"
        android:visibility="gone" />

        <ImageView
        android:id="@+id/bannerClose"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_centerVertical="true"
        android:src="@drawable/cross_icon" />
    </RelativeLayout>


    <LinearLayout
        android:id="@+id/socialTabs"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:layout_gravity="bottom|center"
        android:layout_marginBottom="5dp"
        android:background="@color/White"
        android:orientation="horizontal"
        android:visibility="gone">

        <ImageView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:src="@drawable/follow" />

        <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:background="@color/White">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="46dp"
            android:layout_gravity="center"
            android:gravity="center"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:weightSum="3">

            <ImageView
            android:id="@+id/facebookImageView"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:src="@drawable/fb_follow" />

            <ImageView
            android:id="@+id/googlePlusImageView"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:layout_weight="1"
            android:adjustViewBounds="true"
            android:src="@drawable/google_follow" />

            <ImageView
            android:id="@+id/twitterImageView"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_weight="1"
            android:adjustViewBounds="true"
            android:src="@drawable/twitter_follow" />
        </LinearLayout>
        </FrameLayout>
    </LinearLayout>
    </FrameLayout>

    <ExpandableListView
    android:id="@+id/left_drawer"
    android:layout_width="265dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="#fff"
    android:choiceMode="singleChoice"
    android:divider="@null"
    android:dividerHeight="0dp"
    android:drawSelectorOnTop="true"
    android:groupIndicator="@null"
    android:scrollbars="@null" />

</android.support.v4.widget.DrawerLayout>
Kushminder Garg
  • 518
  • 1
  • 6
  • 14

1 Answers1

9

I've just put together a sample app that seems to demonstrate the behaviour you're after. The AppBar will automatically expand whenever the RecyclerView beneath it is scrolled to the top, rather than stopping and waiting for another swipe to open the AppBar.

The most relevant components reside in a custom RecyclerView class. I've added a few explanatory comments:

public class ScrollFeedbackRecyclerView extends RecyclerView {

    private WeakReference<Callbacks> mCallbacks;

    public ScrollFeedbackRecyclerView(Context context) {
        super(context);
        attachCallbacks(context);
    }

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

    /*If the first completely visible item in the RecyclerView is at
    index 0, then we're at the top of the list, so we want the AppBar to expand 
    **if the AppBar is also collapsed** (otherwise the AppBar will constantly 
    attempt to expand).
    */
    @Override
    public void onScrolled(int dx, int dy) {
        if(((LinearLayoutManager)getLayoutManager()).findFirstCompletelyVisibleItemPosition() == 0) {
            Log.e(getClass().getSimpleName(), "index 0 visible");
            if(mCallbacks.get().isAppBarCollapsed()) {
                mCallbacks.get().setExpanded(true);
            }
        }
        super.onScrolled(dx, dy);
    }

    /* the findFirstCompletelyVisibleItem() method is only available with 
    LinearLayoutManager and its subclasses, so test for it when setting the 
    LayoutManager
    */
    @Override
    public void setLayoutManager(LayoutManager layout) {
        if(!(layout instanceof LinearLayoutManager)) {
            throw new IllegalArgumentException(layout.toString() + " must be of type LinearLayoutManager");
        }
        super.setLayoutManager(layout);
    }

    private void attachCallbacks(Context context) {

        try {
            mCallbacks = new WeakReference<>((Callbacks)context);
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement " +
                    "ScrollFeedbackRecyclerView.Callbacks");
        }

    }

    /* Necessary to interact with the AppBarLayout in the hosting Activity
    */
    interface Callbacks {

        boolean isAppBarCollapsed();
        void setExpanded(boolean expanded);

    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity implements ScrollFeedbackRecyclerView.Callbacks{

    private AppBarLayout mAppBarLayout;
    private Toolbar mToolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ScrollFeedbackRecyclerView mRecyclerView = (ScrollFeedbackRecyclerView) findViewById(R.id.rv_container);
        RecyclerViewAdapter mAdapter = new RecyclerViewAdapter();

        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        mAppBarLayout = (AppBarLayout) findViewById(R.id.app_bar);
        mToolbar = (Toolbar) findViewById(R.id.toolbar);

    }

    /* When collapsed, calling getY() on the AppBar will return a negative number. 
    Adding this number to getHeight() will return the same value as the toolbar's 
    height if the AppBar is fully collapsed.
    */
    @Override
    public boolean isAppBarCollapsed() {
        final int appBarVisibleHeight = (int) (mAppBarLayout.getY() + mAppBarLayout.getHeight());
        final int toolbarHeight = mToolbar.getHeight();
        return (appBarVisibleHeight == toolbarHeight);
    }

    @Override
    public void setExpanded(boolean expanded) {
        mAppBarLayout.setExpanded(expanded, true);
    }
}
PPartisan
  • 8,173
  • 4
  • 29
  • 48
  • Hi, in method `isAppBarCollapsed()` variable `toolbarHeight` always contains value less value from `appBarVisibleHeight` - both values are never equal. – Ihor Levkivskyi Oct 29 '16 at 16:17
  • @IgorLevkivskiy Just tested out the repository in my answer and it stills seems to work. `isAppBarCollapsed()` returns true if the AppBar is fully collapsed. – PPartisan Oct 29 '16 at 18:48
  • It is strange behavior on different API. Did you try your code on different APi? If I run this code on 19 API - works fine, but if I run the same code on API 22 - it works wrong. I suppose problem could be in statusbar... But I'm not sure. – Ihor Levkivskyi Oct 29 '16 at 20:46
  • @IgorLevkivskiy I tested on emulators at API 16, 19 and 23 and they worked, though what you're saying about the status bar would make sense. (**Edit:** Just changed the emulator API 22 and that worked as well, so perhaps it's device specific) – PPartisan Oct 29 '16 at 21:14
  • Yeah my problem was in length of statusbar. Simply I add this height to `appBarVisibleHeight`. Simply I pass value of height to `isAppBarCollapsed()` Thanks – Ihor Levkivskyi Oct 30 '16 at 18:49
  • I obtained new problem. When I scroll up to AppBar RecyclerView stopped below AppBar but not expand and when I continue scroll AppBar expanded - http://gifyu.com/images/ZAPISEKRANA10-30-20163-08-43PM.gif. What I want to do -http://gifyu.com/images/ZAPISEKRANA10-30-20162-41-42PM.gif - When I long scroll up, AppBar automatically expand – Ihor Levkivskyi Oct 30 '16 at 19:51