androidswiperefreshlayoutandroid-appbarlayout

Enable SwipeRefreshLayout only when AppBarLayout expanded completely


How can I enable SwipeRefreshLayout only when AppBarLayout expanded completely. I need to enable a refreshing mode only on the next swipe gesture. Now, I try so

appBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
  @Override
  public void onOffsetChanged(AppBarLayout appBarLayout, final int verticalOffset) {
    refreshLayout.setEnabled(verticalOffset == 0);
  }
});

Of course, it works! But it works not so like I need. This code enables a refreshing mode immediately while user continues the swipe gesture. I need to enable it only on the next swipe after the AppBarLayout expansion.
Who knows how to make it?


Solution

  • Well, I was stumbling on the same problem. and here is what I've found. My solution isn't perfect, but it's working for me. Let's suppose we have an AppBarLayout and RecyclerView wrapped in SwipeRefreshLayout. Attention! Kotlin detected.

    recyclerView.setOnTouchListener { _, motionEvent ->
            if (motionEvent.action == MotionEvent.ACTION_CANCEL
                || motionEvent.action == MotionEvent.ACTION_UP) {
    
                // 0.5f is used because I have snap parameter for CollapsingToolbar
                // and it automatically collapses/expands
                // if user finishes his scroll action in the middle of collapsing
                // so if AppBar is going to be completely expanded
                // we need to enable SwipeRefreshLayout
                swipeRefreshLayout.isEnabled =
                    (appBarLayout.collapsingPercentage() < 0.5f)
            }
            false
        }
    
    /**
     * @return 1.0f if AppBarLayout is completely collapsed,
     * 0.0f if completely expanded, percentage of
     * total height collapsed when collapsing/expanding is in progress.
     */
    fun AppBarLayout.collapsingPercentage()
        = Math.abs(this.height - this.bottom) / this.totalScrollRange.toFloat()