AppBarLayout.OnOffsetChangedListener的使用

先看看官网对于AppBarLayout.OnOffsetChangedListener的解释:

Interface definition for a callback to be invoked when an AppBarLayout's vertical offset changes.

AppBarLayout垂直方向上的偏移量发生改变时,为触发一个回调方法定义的接口。

触发的回调方法是:

[onOffsetChanged](https://developer.android.com/reference/android/support/design/widget/AppBarLayout.OnOffsetChangedListener.html#onOffsetChanged(android.support.design.widget.AppBarLayout, int))(AppBarLayout appBarLayout, int verticalOffset)

再来看看对于[onOffsetChanged](https://developer.android.com/reference/android/support/design/widget/AppBarLayout.OnOffsetChangedListener.html#onOffsetChanged(android.support.design.widget.AppBarLayout, int))的解释:

Called when the AppBarLayout's layout offset has been changed. This allows child views to implement custom behavior based on the offset (for instance pinning a view at a certain y value).

AppBarLayout的布局偏移量发生改变时被调用。这个方法允许子view根据偏移量实现自定义的行为(比如在特定Y值的时候固定住一个View)。

解释的非常清楚了,不过我们需要点例子才好理解。

就以stackoverflow上的一个问题为例吧。

http://stackoverflow.com/questions/30779667/android-collapsingtoolbarlayout-and-swiperefreshlayout/30785823#30785823 

问题描述

当我把CollapsingToolbarLayout,CollapsingToolbarLayout以及SwipeRefreshLayout用在一起的时候:

<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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"><android.support.design.widget.CoordinatorLayout
    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/appbar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/collapse_toolbar_height"
    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="match_parent"
        app:contentScrim="?attr/colorPrimary"
        android:fitsSystemWindows="true"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginEnd="64dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">
        <ImageView
            android:id="@+id/toolbar_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax" />
        <include
            layout="@layout/activity_main_toolbar"/>
    </android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout>
    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <cz.yetanotherview.webcamviewer.app.helper.EmptyRecyclerView
            android:id="@+id/mainList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical" />
    </android.support.v4.widget.SwipeRefreshLayout>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floating_action_button"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        android:layout_margin="16dp"
        app:fabSize="mini"
        android:src="@drawable/ic_action_edit"
        android:onClick="assignSelectedWebCamsToCategory"/>
    <com.github.clans.fab.FloatingActionMenu
        android:id="@+id/floating_action_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="bottom|end"
        android:paddingRight="10dp"
        android:paddingBottom="8dp"
        android:paddingLeft="10dp"
        fab:menu_shadowColor="#37000000"
        fab:menu_colorNormal="#DA4336"
        fab:menu_colorPressed="#E75043"
        fab:menu_colorRipple="#99FFFFFF"
        fab:menu_icon="@drawable/fab_add"
        fab:menu_buttonSpacing="10dp"
        fab:menu_labels_textColor="@color/very_dark_grey"
        fab:menu_labels_textSize="14sp"
        fab:menu_labels_colorNormal="@color/white"
        fab:menu_labels_colorPressed="@color/next_grey"
        fab:menu_labels_colorRipple="#99FFFFFF"
        fab:menu_labels_margin="8dp"
        fab:menu_backgroundColor="@color/black_transparent">
        <com.github.clans.fab.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_action_content_import"
            fab:fab_size="mini"
            fab:fab_label="@string/pref_import_from_server"
            fab:fab_colorNormal="@color/white"
            app:fab_colorPressed="@color/next_grey"
            app:fab_colorRipple="#99FFFFFF"
            android:onClick="showSelectionDialog"/>
        <com.github.clans.fab.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_action_content_manually"
            fab:fab_size="mini"
            fab:fab_label="@string/create_manually"
            fab:fab_colorNormal="@color/white"
            app:fab_colorPressed="@color/next_grey"
            app:fab_colorRipple="#99FFFFFF"
            android:onClick="showAddDialog"/>
        <com.github.clans.fab.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_action_content_suggestion"
            fab:fab_size="mini"
            fab:fab_label="@string/submit_suggestion"
            fab:fab_colorNormal="@color/white"
            app:fab_colorPressed="@color/next_grey"
            app:fab_colorRipple="#99FFFFFF"
            android:onClick="showSuggestionDialog"/>
    </com.github.clans.fab.FloatingActionMenu></android.support.design.widget.CoordinatorLayout><include
    layout="@layout/activity_main_drawer"/></android.support.v4.widget.DrawerLayout>

java代码:

 swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
 swipeRefreshLayout.setOnRefreshListener(this);

如何才能让滑动刷新只发生在collapsing toolbar完全展开并且 scrollview (或者recyclerview)在顶部 的时候呢?类似于g+和Inbox中的效果。

错误的效果:

enter image description here

正确的效果:

enter image description here

回答:

可以尝试为AppBarLayout添加 offset change listener同时根据情况启用或者关闭滑动刷新,需要增加的代码在这里:

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

关键改动:

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) {
        if (i == 0) {
            mSwipeRefreshLayout.setEnabled(true);
        } else {
            mSwipeRefreshLayout.setEnabled(false);
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        appBarLayout.addOnOffsetChangedListener(this);
    }
    @Override
    protected void onPause() {
        super.onPause();
        appBarLayout.removeOnOffsetChangedListener(this);
    }}