Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android]使用RecyclerView替代ListView(三)

[Android]使用RecyclerView替代ListView(三)

編輯:關於Android編程

修改布局如下:      1 <?xml version="1.0" encoding="utf-8"?>  2   3 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  4               android:orientation="vertical"  5               android:layout_width="match_parent"  6               android:layout_height="match_parent">  7   8     <android.support.v7.widget.Toolbar  9             android:id="@+id/recycler_view_pinned_toolbar" 10             android:layout_height="wrap_content" 11             android:layout_width="match_parent" 12             android:background="?attr/colorPrimary" 13             /> 14     <android.support.v4.widget.SwipeRefreshLayout 15             android:id="@+id/recycler_view_pinned_srl" 16             android:layout_width="match_parent" 17             android:layout_height="wrap_content" 18             > 19  20         <com.wangjie.androidbucket.support.recyclerview.pinnedlayout.PinnedRecyclerViewLayout 21                 android:id="@+id/recycler_view_pinned_layout" 22                 android:layout_width="match_parent" android:layout_height="match_parent"> 23             <android.support.v7.widget.RecyclerView 24                     android:id="@+id/recycler_view_pinned_rv" 25                     android:scrollbars="vertical" 26                     android:layout_width="match_parent" 27                     android:layout_height="match_parent" 28                     android:background="#bbccaa" 29                     /> 30             <Button 31                     android:id="@+id/recycler_view_pinned_add_btn" 32                     android:layout_width="wrap_content" android:layout_height="wrap_content" 33                     android:layout_centerVertical="true" 34                     android:background="#abcabc" 35                     android:text="add" 36                     /> 37  38         </com.wangjie.androidbucket.support.recyclerview.pinnedlayout.PinnedRecyclerViewLayout> 39  40     </android.support.v4.widget.SwipeRefreshLayout> 41  42 </LinearLayout>   可以看到RecyclerView是被一個PinnedRecyclerViewLayout(https://github.com/wangjiegulu/AndroidBucket/blob/master/src/com/wangjie/androidbucket/support/recyclerview/pinnedlayout/PinnedRecyclerViewLayout.java)包含在裡面的。這個在項目AndroidBucket(https://github.com/wangjiegulu/AndroidBucket)中。先看看代碼中怎麼使用吧,具體實現待會說。   1 pinnedLayout.initRecyclerPinned(recyclerView, layoutManager, LayoutInflater.from(context).inflate(R.layout.recycler_view_item_float, null)); 2 pinnedLayout.setOnRecyclerViewPinnedViewListener(this); 如上,使用方式很簡單:   Line1:初始化綁定PinnedRecyclerViewLayout和RecyclerView,並設置需要被頂上去的pinnedView   Line2:設置OnRecyclerViewPinnedViewListener,作用是在頂部被頂上去替換掉的時候,會回調重新渲染數據,傳入的OnRecyclerViewPinnedViewListener是this,顯然,此Activity實現了這個接口,實現代碼如下:      1 // 渲染pinnedView數據  2     @Override  3     public void onPinnedViewRender(PinnedRecyclerViewLayout pinnedRecyclerViewLayout, View pinnedView, int position) {  4         switch (pinnedRecyclerViewLayout.getId()) {  5             case R.id.recycler_view_pinned_layout:  6                 TextView nameTv = (TextView) pinnedView.findViewById(R.id.recycler_view_item_float_name_tv);  7                 nameTv.setText(personList.get(position).getName());  8                 TextView ageTv = (TextView) pinnedView.findViewById(R.id.recycler_view_item_float_age_tv);  9                 ageTv.setText(personList.get(position).getAge() + "歲"); 10                 break; 11         } 12     }   然後,我們來看看PinnedRecyclerViewLayout是怎麼實現的。       1 /**   2  * Author: wangjie   3  * Email: [email protected]   4  * Date: 2/2/15.   5  */   6 public class PinnedRecyclerViewLayout extends RelativeLayout {   7    8     private static final String TAG = PinnedRecyclerViewLayout.class.getSimpleName();   9   10     public static interface OnRecyclerViewPinnedViewListener {  11         void onPinnedViewRender(PinnedRecyclerViewLayout pinnedRecyclerViewLayout, View pinnedView, int position);  12     }  13   14     private OnRecyclerViewPinnedViewListener onRecyclerViewPinnedViewListener;  15   16     public void setOnRecyclerViewPinnedViewListener(OnRecyclerViewPinnedViewListener onRecyclerViewPinnedViewListener) {  17         this.onRecyclerViewPinnedViewListener = onRecyclerViewPinnedViewListener;  18     }  19   20     public PinnedRecyclerViewLayout(Context context) {  21         super(context);  22         init(context);  23     }  24   25     public PinnedRecyclerViewLayout(Context context, AttributeSet attrs) {  26         super(context, attrs);  27         init(context);  28     }  29   30     public PinnedRecyclerViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {  31         super(context, attrs, defStyleAttr);  32         init(context);  33     }  34   35     private void init(Context context) {  36     }  37   38     private View pinnedView;  39     private ABaseLinearLayoutManager layoutManager;  40   41     public void initRecyclerPinned(RecyclerView recyclerView, ABaseLinearLayoutManager layoutManager, View pinnedView) {  42         this.pinnedView = pinnedView;  43         this.layoutManager = layoutManager;  44         this.addView(this.pinnedView);  45         RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);  46         this.pinnedView.setLayoutParams(lp);  47         layoutManager.getRecyclerViewScrollManager().addScrollListener(recyclerView, new OnRecyclerViewScrollListener() {  48             @Override  49             public void onScrollStateChanged(RecyclerView recyclerView, int newState) {  50             }  51   52             @Override  53             public void onScrolled(RecyclerView recyclerView, int dx, int dy) {  54                 refreshPinnedView();  55             }  56         });  57         pinnedView.setVisibility(GONE);  58     }  59   60     // 保存上次的position  61     private int lastPosition = RecyclerView.NO_POSITION;  62   63     public void refreshPinnedView() {  64         if (null == pinnedView || null == layoutManager) {  65             Logger.e(TAG, "Please init pinnedView and layoutManager with initRecyclerPinned method first!");  66             return;  67         }  68         if (VISIBLE != pinnedView.getVisibility()) {  69             pinnedView.setVisibility(VISIBLE);  70         }  71         int curPosition = layoutManager.findFirstVisibleItemPosition();  72         if (RecyclerView.NO_POSITION == curPosition) {  73             return;  74         }  75         View curItemView = layoutManager.findViewByPosition(curPosition);  76         if (null == curItemView) {  77             return;  78         }  79         // 如果當前的curPosition和上次的lastPosition不一樣,則說明需要重新刷新數據,避免curPosition一樣的情況下重復刷新相同數據  80         if (curPosition != lastPosition) {  81             if (null != onRecyclerViewPinnedViewListener) {  82                 onRecyclerViewPinnedViewListener.onPinnedViewRender(this, pinnedView, curPosition);  83             }  84             lastPosition = curPosition;  85         }  86   87         int displayTop;  88         int itemHeight = curItemView.getHeight();  89         int curTop = curItemView.getTop();  90         int floatHeight = pinnedView.getHeight();  91         if (curTop < floatHeight - itemHeight) {  92             displayTop = itemHeight + curTop - floatHeight;  93         } else {  94             displayTop = 0;  95         }  96         RelativeLayout.LayoutParams lp = (LayoutParams) pinnedView.getLayoutParams();  97         lp.topMargin = displayTop;  98         pinnedView.setLayoutParams(lp);  99         pinnedView.invalidate(); 100     } 101  102  103 }       這個PinnedRecyclerViewLayout 是繼承RelativeLayout的,因為我們需要在裡面添加一個被頂上去的pinnedView,需要覆蓋在RecyclerView上面。   Line44:把傳進來的pinnedView增加到PinnedRecyclerViewLayout 裡面   Line47~56:在ABaseLinearLayoutManager中增加一個滾動的監聽器,因為我們需要在滾動的時候動態的改變pinnedView的位置,這樣才能模擬頂上去的效果。並滾動時調用refreshPinnedView來刷新pinnedView的位置。   Line57:因為在調用initRecyclerPinned方法時,RecyclerView可能還沒有數據源,所以不需要顯示這個pinnedView,等到真正滾動的時候再顯示就可以了。   refreshPinnedView()方法的作用是在滾動的同時用來刷新pinnedView的位置和顯示的數據:   Line71~78:通過layoutManager獲取當前第一個顯示的數據position,然後根據position獲取當前第一個顯示的View。   Line79~85:如果當前的curPosition和上次的lastPosition不一樣,則說明需要重新刷新數據,避免curPosition一樣的情況下重復刷新相同數據。   Line87~95:根據當前第一個顯示的View,根據它的top、它的高度和pinnedView的高度計算出pinnedView需要往上移動的距離(畫個幾何圖一目了然了)。   Line96~99:刷新pinnedView的位置
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved