Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expand AppBarLayout when scrolling down reaches at top of the RecyclerView

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>
like image 905
Kushminder Garg Avatar asked Dec 30 '15 07:12

Kushminder Garg


1 Answers

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);
    }
}
like image 93
PPartisan Avatar answered Sep 18 '22 17:09

PPartisan