2015-06-11 118 views
46

我用CollapsingToolbarLayout,RecyclerView和SwipeRefreshLayout在一起:安卓:CollapsingToolbarLayout和SwipeRefreshLayout卡住

XML:

<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> 

代碼:

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

如何允許刷卡刷新動作只有當摺疊式工具佈局完全展開頂部和滾動視圖(recyclerview)?類似於Google+或收件箱應用中的行爲。

錯誤:

enter image description here

好:

enter image description here

回答

22

最後,

我發現SwipeRefreshLayout工作而不支持庫版本23.1.1任何 「黑客」

在佈局只需使用:

<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> 

和代碼:

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 
    } 
}); 

而且不要忘記使用:

swipeRefreshLayout.setRefreshing(false); 

使用你的代碼邏輯之後;)

+1

隨着新的支持庫23.2.0再次成爲問題:https://code.google.com/p/android/issues/detail?id=201775 – Tomas

+1

23.2解決方法:http://stackoverflow.com/questions/35641630/recyclerviews-and-swiperefreshlayout-using-support-library-23-2-0/35643170#35643170 – Tomas

+2

如果SwipeRefreshLayout不是直接位於CoordinatorLayout中,該怎麼辦?我有一個使用SwipeRefreshLayout的片段的ViewPager –

79

更新:這個問題在支持庫(23.1的最新版本已經解決了。 1+)。如果您使用的是舊版本的支持庫,請升級或繼續閱讀。

如果您使用支持庫的舊版本,添加偏移變化監聽到你的AppBarLayout啓用或禁用您的刷卡相應地刷新佈局。額外的代碼可在這裏:

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) { 
     //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); 
    } 
} 
+12

如果在'SwipeRefreshLayout'是'Fragment'這將是一個'ViewPager'裏面裏面? – AndyRoid

+2

@AndyRoid我已經在GitHub上更新了我的設計支持示例以包含此代碼。除了偵聽onOffsetChanged之外,您還需要爲「Activity」重寫dispatchTouchEvent。然後在'Fragment'中包含一個公共函數來啓用/禁用'SwipeRefreshLayout'。完整的代碼在這裏可用:https://github.com/blackcj/DesignSupportExample – blackcj

+0

不錯的工作blackcj我會檢查出來,看看它是否一切看起來不錯!編輯:根據我在Repo中看到的例子,目前看起來很清楚,但尚未在設備上進行測試。會及時向大家發佈。 – AndyRoid

5

如果我理解正確的話,你要開始刷新工具欄擴展後才吧?所以首先需要打開CollapsingToolbarLayout,然後開始刷新。我用下面的代碼管理它:

 <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> 

,然後在你的片段/活性,使其實現AppBarLayout.OnOffsetChangedListener(現在,當工具欄完全展開的清爽啓用):

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

覆蓋在onPause()&的onResume()在@blackcj答案:

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

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

然後設置LinearLayoutManager您recyclerView:

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

對我來說這是一名魅力,第一appBarlayout被擴大,然後才swipeRefreshLayout觸發耳目一新。

+0

需要使用添加到nestedscrollview的片段來完成它。我很難過。 –

+0

@ user1232726嗯..有什麼問題?如果您將FrameLayout放入NestedScrollView中,然後從您的代碼開始事務將您的片段放入framelayout中,它應該可以工作,不是嗎? – hkop

+0

您好我嘗試在nestedScrollview中放置framelayout,並嘗試用片段包含swiperefreshlayout和recycleView替換它裏面但不起作用,recycleView不顯示。 (刪除swipeRefreshlayout,通常recycleview顯示) –

-1

Above Answer非常適合AppCompatActivity但如果您使用Fragment那麼下面的代碼將幫助你。

只要把NestedScrollView在XML的fragment

<android.support.v4.widget.NestedScrollView 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:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_gravity="fill_vertical" 
    android:clipToPadding="false" 
    android:isScrollContainer="false" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    <!-- A RecyclerView with some commonly used attributes --> 
     <android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/album_timeline_swipe_refresh_layout" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 

      <android.support.v7.widget.RecyclerView 
       android:id="@+id/album_timeline_recyclerview" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:clickable="true" /> 
     </android.support.v4.widget.SwipeRefreshLayout> 

</android.support.v4.widget.NestedScrollView> 
+1

不適合我... – xiaoyee

+1

不要爲我工作 –

0

我不得不做出的RecyclerView的SwipeRefreshLayout的主要子,以消除使用支持庫23.2.0的問題。無法固定它具有包括內部佈局的SwipeRefreshLayout

<android.support.v4.widget.SwipeRefreshLayout 
     android:id="@+id/my_swipeRefreshLayout" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <!--<include layout="@layout/my_RecyclerView_layout"/> issue for me here --> 

     <android.support.v7.widget.RecyclerView 
      android:id="@+id/my_recyclerView" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 
     </android.support.v7.widget.RecyclerView> 

    </android.support.v4.widget.SwipeRefreshLayout>