Android: CollapsingToolbarLayout and SwipeRefreshLayout get stuck Android: CollapsingToolbarLayout and SwipeRefreshLayout get stuck android android

Android: CollapsingToolbarLayout and SwipeRefreshLayout get stuck


Update: This issue has been resolved in the latest version of the support library (23.1.1+). If you are using an older version of the support library either upgrade or continue reading.

If you're using an older version of the support library, add an offset change listener to your AppBarLayout to enable or disable your swipe to refresh layout accordingly. Additional code available here:

https://gist.github.com/blackcj/001a90c7775765ad5212

Relevant changes:

public class MainActivity extends AppCompatActivity implements AppBarLayout.OnOffsetChangedListener {    ...    private AppBarLayout appBarLayout;    private SwipeRefreshLayout mSwipeRefreshLayout;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ...        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.contentView);        appBarLayout = (AppBarLayout) findViewById(R.id.appBarLayout);    }    @Override    public void onOffsetChanged(AppBarLayout appBarLayout, int i) {        //The Refresh must be only active when the offset is zero :        mSwipeRefreshLayout.setEnabled(i == 0);    }    @Override    protected void onResume() {        super.onResume();        appBarLayout.addOnOffsetChangedListener(this);    }    @Override    protected void onPause() {        super.onPause();        appBarLayout.removeOnOffsetChangedListener(this);    }}


Finally,

I found that SwipeRefreshLayout works without any "hacks" from Support Library version 23.1.1.

Simply use in your layout:

 <android.support.v4.widget.SwipeRefreshLayout    android:id="@+id/swipe_refresh_layout"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:layout_behavior="@string/appbar_scrolling_view_behavior">        <android.support.v7.widget.RecyclerView            android:id="@+id/recycler_view"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:scrollbars="vertical" /></android.support.v4.widget.SwipeRefreshLayout>

and in code:

SwipeRefreshLayout swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);swipeRefreshLayout.setColorSchemeResources(R.color.green, R.color.red, R.color.yellow);swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {    @Override    public void onRefresh() {       //Your refresh code here    }});

And don't forget to use:

swipeRefreshLayout.setRefreshing(false);

after using your code logic ;)


If I understand you correctly, you want to start refreshing only after toolbar is expanded, right? So first CollapsingToolbarLayout needs to be opened and then start refreshing. I managed it by the following code:

     <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:app="http://schemas.android.com/apk/res-auto"        android:id="@+id/coordinator_layout"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:fitsSystemWindows="true">        <android.support.design.widget.AppBarLayout            android:id="@+id/app_bar_layout"            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:id="@+id/collapsing_toolbar"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:fitsSystemWindows="true"                app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed">                <LinearLayout                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:orientation="vertical">                      <!--PUT HERE WHAT EVER YOU WANT TO COLLAPSE, A TOOLBAR, ETC...-->                </LinearLayout>            </android.support.design.widget.CollapsingToolbarLayout>        </android.support.design.widget.AppBarLayout>     <android.support.v4.widget.SwipeRefreshLayout        android:id="@+id/swipe_refresh_layout"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:layout_behavior="@string/appbar_scrolling_view_behavior">            <android.support.v7.widget.RecyclerView                android:id="@+id/recycler_view"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:clipToPadding="false"                android:fadeScrollbars="false"                android:scrollbars="vertical"                app:layout_behavior="@string/appbar_scrolling_view_behavior" />    </android.support.v4.widget.SwipeRefreshLayout></android.support.design.widget.CoordinatorLayout>   

And then, in your fragment/activity make it implement AppBarLayout.OnOffsetChangedListener (Now the refreshing is enabled when toolbar is fully expanded):

    @Override    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {        if (collapsingToolbarLayout.getHeight() + verticalOffset < 2 * ViewCompat.getMinimumHeight(collapsingToolbarLayout)) {            swipeRefreshLayout.setEnabled(false);        } else {            swipeRefreshLayout.setEnabled(true);        }    }

Override onPause() & onResume() as in @blackcj answer:

  @Override    public void onResume() {        super.onResume();        appBarLayout.addOnOffsetChangedListener(this);    }    @Override    public void onPause() {        super.onPause();        appBarLayout.removeOnOffsetChangedListener(this);    }

Then set LinearLayoutManager to your recyclerView:

    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);    recyclerView.setLayoutManager(layoutManager);

For me this worked as a charm, first appBarlayout gets expanded and only then swipeRefreshLayout triggers refreshing.