Android開發筆記:RecyclerView(一)先學會使用

對RecyclerView一直處於一種朦朧的理解狀態,最近項目經常使用RecyclerView,本系列主要從淺入深的總結自己對RecyclerView的理解


前言

       面對一個新控件,首先要學會使用,然後再逐步學習其原理,RecyclerView作爲ListView 的替代,靈活性更強,我把它理解爲一個插線板,需要什麼功能就插入什麼,非常方便。

      初學Android時,習慣於控件直接綁定內容,例如TextView,直接可以設置文字信息,對於ListView和RecyclerView這種展示大量數據的控件非常不理解,所以對控件的使用也非常不熟悉。使用控件時,我們主要會處理三個主體:Layout(View)、adapter、ItemModel。三個主體理解到位了,對於此類控件的使用變會的容易些。

Layout不用過多解釋,要使用這類控件,一般最少要涉及2個layout,一個作爲Activity的Layout,一個作爲列表Item的layout

ItemModel,可以把他看做數據,即每個列表要展示的內容。

adapter就是將內容綁定到view 的工具。可以理解爲MVC模式

 

RecyclerView的使用

首先再Android studio中導入RecyclerView,網上有一萬種方法,讀者可以自行查閱。

導入RecyclerView後,便要創建上面說的三種主體,首先是Layout,創建一個Activity的Layout,如下,Activity中只包含了一個RecyclerView。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="com.example.recyclerviewt.MainActivity">

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

    </android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

另外一個Layout爲RecyclerView每一個列表的視圖,本文每個Item顯示一個數字,所以界面只包含了一個TextView:

<?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="match_parent">

    <TextView
        android:id="@+id/view_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="40sp"
        android:gravity="center"
        />

</LinearLayout>

然後創建adapter繼承RecyclerView.Adapter, 需要重寫三個方法,分別是onCreateViewHolder、onBindViewHolder、getItemCount

viewHolder

ViewHolder可以理解爲一個View的容器,列表在滾動的時候,爲了避免不斷的findViewByID影響效率,將view存放在ViewHolder中進行復用,例如每頁展示7個Items,當向上滑動時,item1劃出界面,就可以將item的viewholder複用,更新爲下方可見的item內容,避免不斷的findViewByID

public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        public ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView)itemView.findViewById(R.id.view_text);
        }
    }

onCreateViewHolder

onCreateViewHolder的作用就是創建ViewHolder,在列表剛打開時,由於之前沒有創建過ViewHolder,無法複用,所以需要重新創建,新建一個item的view,放到ViewHolder容器中。

public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_item_view,parent,false);
        MyAdapter.ViewHolder viewHolder = new MyAdapter.ViewHolder(view);
        return viewHolder;
    }

onBindViewHolder

上面講了每個ViewHolder在複用時需要更新裏面View的內容,相當於把新的View內容與VIewHolder連接起來,所以每次需要在ViewHolder中更新view時都會調用這個方法

@Override
    public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, int position) {
        holder.textView.setText(Items.get(position).toString());
    }

adapter創建好後,需要準備ItemModel,本文每個列表只顯示數字,所以不需要新建數據結構,只是生成了20個數字。

Activity

和其他控件一樣,在使用時需要在Activity中進行綁定,對於RecyclerView需要設置其排列方向、動畫、以及與adapter進行綁定,完整的Activity如下:



public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private MyAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager ;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initRV();
    }

    private void initRV(){
        mAdapter = new MyAdapter(initData());
        mLayoutManager = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
        mRecyclerView = (RecyclerView) findViewById(R.id.RVContent);
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.HORIZONTAL));
    }

    private ArrayList<Integer> initData(){
        ArrayList<Integer> data = new ArrayList<>();
        for(int i=0;i<20;i++){
            data.add(i);
        }
        return data;
    }
}

我調整了TextView的寬高和顏色,並設置排列方式爲水平排列,效果如下:

設置間隔

RecyclerView和ListView不同,爲了保證RecyclerView的靈活性,item之間的間隔的設計也獨立了出來,通過調用adapter的addItemDecortion方法添加間隔。

1.系統自帶的間隔線:

addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.HORIZONTAL))

2.自定義間隔

系統自帶的分割線是通過DividerItemDecoration類進行實現的,查看源碼可以看到,這個類是通過繼承RecyclerView.ItemDecoration實現間隔的樣式:

public class DividerItemDecoration extends ItemDecoration

我們也可以通過繼承來實現自己的間隔,需要重寫onDraw和getItemOffsets方法,onDraw主要實現我們要在間隔中繪製的內容,getItemOffsets用來設置每個Item周圍的間隔大小,本文自定義一種空白間隔,不繪製內容,第一個和最後一個item的兩邊間距50,中間的item間距12,自定義ItemDecoration如下:

class mItemDecoration extends RecyclerView.ItemDecoration{
        @Override
        public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) parent.getLayoutManager();
            Context context = MainActivity.this;
            if(parent.getChildAdapterPosition(view) == 0){
                outRect.left = dip2px(context,50);
                outRect.right = dip2px(context,12);
            } else if(parent.getChildAdapterPosition(view) == linearLayoutManager.getItemCount()-1){
                outRect.right = dip2px(context,50);
                outRect.left = dip2px(context,12);
            } else{
                outRect.left = dip2px(context,12);
                outRect.right = dip2px(context,12);
            }
        }

    }

不繪製內容,所以沒有重寫onDraw方法,需要間隔,所以只重寫了getItemOffsets方法,方法中outRect表示每個Item外圍的寬度,默認爲0,通過getChildAdapterPosition()方法可以得到當前繪製的間隔是哪個Item的。recyclerView設置爲自定義的間隔效果如下:

這樣一個簡單的RecyclerVIew的使用就完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章