標籤:
RecyclerView的使用(Android開發必備,替換掉ListView) 當有人看了你寫的代碼,說你現在還在使用ListView?是不是感覺快跟不上時代了啊!不錯,今天就帶給大家一個ListView的最新升級控制項RecyclerView,Android 5.0推出的新控制項,不過它在support-v7包,可以往下相容,當你學會了RecyclerView之後,發現了它的強大,你就會替換到ListView和GridView了。
RecyclerView簡介:
RecyclerView是support-v7包中的新控制項,是ListView的升級版,使用方法和基本原理和ListView類似,區別是,RecycleView強行把ListView中的 getView ()方法拆分,把其中的ViewHolder單獨封裝起來,只需要實現自定定義的ViewHolder就行了,改組件會幫我們自動回收複用每一個item。
RecyclerView相對於ListView的優點:
1、可以使用布局管理器LayoutManager來管理RecyclerView的顯示方式:水平、垂直、網路、網格交錯布局;
2、自訂item的分割條,實現自訂(不知道是優點還是缺點,見仁見智吧 ( ̄▽ ̄)");
3、可以控制item的添加和刪除的動畫,非常自由,可以自訂動畫,配合具體情境,效果非常棒;
4、可以動態在指定位置添加和刪除某一項,而列表不會回到頂部,動態update列表資料(非常需要); 5、缺點:就是沒有OnItemClickListenter(),需要自己在RecycleView內部自訂欄表項的點擊事件或則長按事件(按需求自己添加); 6、在Material Design中和CardView(和RecycleView同時出現的新控制項)配合使用,顯示效果非常突出(現在很多新的主流App都使用了這種結構,後面會有demo展示)。
RecycleView的基本使用步驟:
1、類比對象和擷取對象集合資料(這裡只是類比資料)
package com.world.hello.recycleview;/** * 類比對象資料 * Created by chengguo on 2016/5/30. */public class SampleModel { private String message; public SampleModel(String message) { this.message = message; } public void setMessage(String s) { message = s; } public String getMessage() { return message; }}
package com.world.hello.recycleview;import java.util.ArrayList;/** * 類比資料集合 * Created by chengguo on 2016/5/30. */public class DemoApp { //擷取要顯示的資料(初始化資料) public static ArrayList<SampleModel> getSampleData(int size) { ArrayList<SampleModel> sampleData = new ArrayList<SampleModel>(size); for (int i = 0; i < size; i++) { sampleData.add(new SampleModel("新的清單項目 " + i)); } return sampleData; }}
2、繪製清單項目之間的分割條
使用RecyclerView控制項通常需要指定清單項目的分割條。定製分割條的原理是編寫一個RecyclerView.ItemDecoration的子類,並實現onDrawOver方法,在該方法中需要繪製所有清單項目之間的分割條。如下所示:
package com.world.hello.recycleview;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.drawable.Drawable;import android.support.v7.widget.RecyclerView;import android.view.View;/** * 定製分割線 * Created by chengguo on 2016/5/30. */public class SampleDivider extends RecyclerView.ItemDecoration { //預設分割條Drawable資源的Id private static final int[] ATTRS = {android.R.attr.listDivider}; //分割條的Drawable對象 private Drawable mDicider; public SampleDivider(Context context) { TypedArray ta = context.obtainStyledAttributes(ATTRS); //擷取分割條的drawable對象 mDicider = ta.getDrawable(0); //回收ta所佔用的空間 ta.recycle(); } /** * 在改方法中繪製了所有清單項目之間的分割條 * * @param c * @param parent */ @Override public void onDrawOver(Canvas c, RecyclerView parent) { //擷取清單項目距離左邊源的距離 int left = parent.getPaddingLeft(); //擷取清單項目距離右邊源的距離 int right = parent.getWidth() - parent.getPaddingRight(); //擷取列表的總數 int childCount = parent.getChildCount(); //開始繪製這些清單項目之間的分割線 for (int i = 0; i < childCount; i++) { //擷取當前的列表 View child = parent.getChildAt(i); //擷取當前清單項目的布局參數資訊 RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); //計算分割條左上方的的縱座標 int top = child.getBottom() + params.bottomMargin; //計算分割條右下角的縱座標 int bottom = top + mDicider.getIntrinsicHeight(); //設定分割條繪製的位置 mDicider.setBounds(left,top,right,bottom); //開始繪製當前清單項目下方的分割條 mDicider.draw(c); } }}
3、實現Adapter類
就像ListView的adapter一般會繼承BaseAdapter一樣,RecyclerView也提供了這樣的一個基類RecyclerView.Adapter,改基類支援泛型,泛型用於指定清單項目中控制項。如下:
package com.world.hello.recycleview;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import java.util.ArrayList;import java.util.Random;/** * recycleView的adapter * Created by chengguo on 2016/5/30. */public class SampleRecycleAdapter extends RecyclerView.Adapter<SampleRecycleAdapter.ViewHolder>{ //儲存清單項目資料 private final ArrayList<SampleModel> sampleData = DemoApp.getSampleData(30); //建立清單項目中顯示的控制項對象(需要使用Adapter指定泛型) @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //擷取清單項目控制項LinearLayer對象 View rowView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,parent,false); return new ViewHolder(rowView); } //在該方法中設定清單項目中顯示的值 @Override public void onBindViewHolder(ViewHolder holder, int position) { SampleModel rowData = sampleData.get(position); holder.textViewSample.setText(rowData.getMessage()); holder.itemView.setTag(rowData); } //設定清單項目總和 @Override public int getItemCount() { return sampleData.size(); } //刪除指定清單項目的資料 public void removeData(int position){ sampleData.remove(position); //通知recycleView某個清單項目被刪除了 notifyItemRemoved(position); } //在指定的位置添加一個新的清單項目 public void addItem(int position){ //使用隨機數字 sampleData.add(position,new SampleModel("新增清單項目"+ new Random().nextInt(100))); notifyItemInserted(position); } /** * ViewHolder用於儲存清單項目中顯示的控制項,(這裡只有一個TextView做樣本) */ public static class ViewHolder extends RecyclerView.ViewHolder{ private TextView textViewSample; public ViewHolder(View itemView) { super(itemView); textViewSample = (TextView) itemView.findViewById(R.id.text_view); } }
}
注意:SampleRecyclerAdapter類中所有使用@Override的方法都是覆蓋的父類的同名方法。這些方法中和ListView對應的Adapter中的方法有些不同,在新Adapter中沒有了getView()方法,而是使用onCreateViewHolder和OnBindViewHolder方法。前者用於擷取清單項目控制項,後者用於指定在控制項中顯示的資料。 還有就是以前資料發生變化時,只能調用notifyDataSetChanged()方法通知數據是否發生變化,現在可以使用notifyItemRemoved()方法告訴具體哪個位置的資料被移除,使用notifyItemInserted()方法通知某一個新的清單項目背添加。還有很多新的Api非常實用,如下面圖片,就不一一介紹了;
4、在Activity中使用RecyclerView
recycleView是Android Support library中的控制項,所以需要在Android studio中的app的gradle中添加下面的依賴
compile ‘com.android.support:design:23.4.0‘
然後就可以使用RecycleView這個控制項了,這裡實現了RecycleView的動態添加和刪除操作。稍微要比listview複雜點,要設定RecycleView的相片順序 、item間的分割線、item增加和刪除的動畫;具體使用代碼如下:
package com.world.hello.recycleview;import android.app.Activity;import android.os.Bundle;import android.support.design.widget.FloatingActionButton;import android.support.v7.widget.DefaultItemAnimator;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;import android.view.animation.AnimationUtils;import android.widget.Button;public class MainActivity extends Activity { //頂部刪除按鈕 private Button mDeleteBar; //recyclerView private RecyclerView mRecyclerView; //添加item按鈕,這裡也是使用Design庫裡面的一個新控制項,就當做一個按鈕使用。只是樣式很好看 private FloatingActionButton mAddBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDeleteBar = (Button) findViewById(R.id.delete_btn); mAddBtn = (FloatingActionButton) findViewById(R.id.add_item); //擷取到recyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); //建立LinearLayoutManager final LinearLayoutManager layoutManager = new LinearLayoutManager(this); //為RecyclerView指定布局管理器對象 mRecyclerView.setLayoutManager(layoutManager); //建立清單項目分割線對象 final RecyclerView.ItemDecoration itemDecoration = new SampleDivider(this); //RecyclerView控制項指定分割線對象 mRecyclerView.addItemDecoration(itemDecoration); //建立SampleRecyclerAdapter final SampleRecycleAdapter sampleRecycleAdapter = new SampleRecycleAdapter(); //為RecyclerView控制項指定Adapter mRecyclerView.setAdapter(sampleRecycleAdapter); //設定Item增加、移除動畫 mRecyclerView.setItemAnimator(new DefaultItemAnimator()); //為右下角按鈕添加點擊事件 mAddBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //擷取第一個可視的清單項目的位置,再加上2個位置,為了示範方便 int positionToAdd = layoutManager.findFirstCompletelyVisibleItemPosition() + 2; //在該位置的後面插入新的清單項目 sampleRecycleAdapter.addItem(positionToAdd); } }); //為頂部的刪除面板添加點擊事件 mDeleteBar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //擷取第一個可視的清單項目的位置,再加上2個位置,為了示範方便 int positionToRemove = layoutManager.findFirstCompletelyVisibleItemPosition() + 2; //刪除第一個可視的清單項目 sampleRecycleAdapter.removeData(positionToRemove); //刪除完成後隱藏刪除面板 hideDeleteBar(); } }); //為RecyclerView控制項設定滾動事件 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { //滾動狀態變化事件的方法 @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } //滾動事件方法(判斷上下或者左右滾動) @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { //如果是垂直顯示的列表, dy>0 表示向上滾動,否則表示向下滾動 //如果是水平顯示的列表,dx > 0 表示向右滾動,否則表示向左滾動 if (dy > 0) { //向上滾動時,隱藏刪除面板, if (mDeleteBar.getVisibility() == View.VISIBLE) { hideDeleteBar(); } } else { //向下滾動時,顯示顯示面板 if (mDeleteBar.getVisibility() == View.GONE) { showDeleteBar(); } } } }); } /** * 顯示刪除欄,使用動畫效果 */ private void showDeleteBar() { mDeleteBar.startAnimation(AnimationUtils.loadAnimation(this, R.anim.translate_show)); mDeleteBar.setVisibility(View.VISIBLE); } /** * 隱藏刪除欄,使用動畫效果 */ private void hideDeleteBar() { mDeleteBar.startAnimation(AnimationUtils.loadAnimation(this, R.anim.translate_hide)); mDeleteBar.setVisibility(View.GONE); }}
main_activity.xml檔案如下:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app ="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.world.hello.recycleview.MainActivity"> <Button android:id="@+id/delete_btn" android:layout_width="match_parent" android:layout_height="40dp" android:text="刪除一項" android:background="#4400ffee" android:textSize="14dp"/> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> <android.support.design.widget.FloatingActionButton android:id="@+id/add_item" android:layout_width="wrap_content" android:layout_height="wrap_content" app:borderWidth="0dp" app:rippleColor="#eeff0000" android:src="@android:drawable/ic_input_add" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_marginRight="33dp" android:layout_marginEnd="33dp" android:layout_marginBottom="38dp" /></RelativeLayout>
list_item.xml檔案如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="40dp" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:textColor="@android:color/black" android:textSize="16sp" /></LinearLayout>
如下:
點擊開啟連結下載demo,免積分
下一篇,將詳細講解。recycleView的排列方法、動畫和CardView結合的使用樣本!
RecyclerView的使用(Android開發必備,替換掉ListView)