RecyclerView 基本使用

原文首發 http://blog.lll0.net/post/recyclerview.html

強大而高效的 RecyclerView

ListView作為一個強大而有使用頻繁的控件,但是隨著我們業務的發展慢慢的就感覺 ListView 在某些業務場景中已經不能滿足我們的業務需求。舉個栗子:如果我們在一個頁面上需要加載不同的布局,在列表中間某一行加載一個廣告試圖,而這個廣告的布局和整個個列表的布局樣式是完全不一樣的。如果放在ListView 中,這種布局是不太好實現的。但是放在Google 提出的新控件 ReyclerView 中 實現這種布局是非常簡單的。

RecyclerView 是Android L版本中新添加的一個用來取代ListView的SDK,它的靈活性與可替代性比listview更好。

基本介紹

在使用RecyclerView中引入了幾個相關的類

  1. LayoutManager 用來確定每一個item如何進行排列擺放,何時展示和隱藏。回收或重用一個View的時候,LayoutManager會向適配器請求新的數據來替換舊的數據,這種機制避免了創建過多的View和頻繁的調用findViewById方法(與ListView原理類似)。Google 為我們提供了 幾個基礎的布局
    1. LinearLayoutManager 線性布局布局樣式和ListView一樣 呈現的是線性
    2. GridLayoutManager 表格布局與GridView 一樣
    3. StaggeredGridLayoutManager 瀑布流布局 這是新的布局 簡單描述就是加載的每個item在頁面上占有的空間都是不一樣的布局
  2. RecyclerView.Adapter RecyclerView 的適配器 數據的加載和item 的綁定都是通過這個類來實現。在使用的時候需要繼承該類來進行相應的處理
  3. RecyclerView.ViewHolder 同樣是使用中需要繼承該類,然后進行把數據和item里面的布局進行綁定

在使用的時候 其實不用考慮復用的問題。

簡單使用

1.添加依賴在build.gradle 中添加依賴 ,然后同步一下 引入依賴需要的包

dependencies {
     compile 'com.android.support:recyclerview-v7:25.1.1' 
}

2.布局中使用RecylerView

<?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="net.lll0.bus.ui.test_activity.RecyclerViewTestActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="368dp"
        android:layout_height="551dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp" />
</android.support.constraint.ConstraintLayout>

3.創建布局之后需要在Activity中獲得這個控件,并聲明LayoutManagerAdapter,代碼如下

 mRecycler = (RecyclerView) findViewById(R.id.recycler);
 mRecycler.setLayoutManager(new LinearLayoutManager(mActitivity));
 recyclerViewAdapter = new RecyclerViewAdapter(beans,mActitivity);
 mRecycler.setAdapter(recyclerViewAdapter);

4.Adapter的創建

package net.lll0.bus.adapter.test;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import net.lll0.bus.suzhoubus.R;
import net.lll0.bus.adapter.RecyclerViewHolder;

import java.util.List;

/**
 * Created by liang on 2017/8/24.
 */

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolder> {

    private String typeView01 = "item1";
    private String typeView02 = "item2";
    /**
     * 加載不同的兩種方式
     * 1. 傳入不同的數據源,對應的位置加載不同的布局
     * 2. 傳入一個數據源,但是通過數據源里面特殊的字段判斷加載什么布局
     */
    private List<Bean> bean;
    private Context mContext;
    public RecyclerViewAdapter(List<Bean> bean, Context mContext) {
        this.bean = bean;
        this.mContext = mContext;
    }
    @Override
    public int getItemViewType(int position) {
        //通過這個區分加載不同 view
        //通過判斷特殊的字段加載不同的布局

        return bean.get(position).type;
    }
    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //通過 getTtemViewType 返回的 內容加載不同 的布局

        //假設加載 三中布局分別對應 1 2 3

        if (1 == viewType) {
            return new RecyclerViewHolder(mContext,LayoutInflater.from(mContext).inflate(R.layout.item, parent, false), viewType);
        } else if (2 == viewType) {
            return new RecyclerViewHolder(mContext,LayoutInflater.from(mContext).inflate(R.layout.item_lineinfo, parent, false), viewType);
        } else if (3 == viewType) {
            return new RecyclerViewHolder(mContext,LayoutInflater.from(mContext).inflate(R.layout.nav_header_home, parent, false), viewType);
        }
        return null;
    }
    @Override
    public void onBindViewHolder(RecyclerViewHolder holder, int position) {
        //onCreateViewHolder 為不同的布局綁定對應的數據
        Bean bean = this.bean.get(position);
        int type = bean.type;
        if (1 == type) {
            holder.setText(R.id.textView2,"textView2");
            holder.setText(R.id.textView3,"textView3");
        } else if (2 == type) {
            holder.setText(R.id.lineinfo_index,position+"");
        } else if (3 == type) {
        }
    }
    @Override
    public int getItemCount() {
        //主要是計算 加載數據的總數
        return bean.size();
    }
}

5.RecyclerView.ViewHolder 子類的實現 ,這是一個通用的ViewHolder

package net.lll0.bus.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
/**
 * Created by liang on 2016/2/15.
 */
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
    private SparseArray<View> mViews;//集合類,layout里包含的View,以view的id作為key,value是view對象
    private Context mContext;//上下文對象
    private int type;

    public RecyclerViewHolder(Context ctx, View itemView) {
        super(itemView);
        mContext = ctx;
        mViews = new SparseArray<View>();
    }
    public RecyclerViewHolder(Context ctx, View itemView,int type) {
        super(itemView);
        mContext = ctx;
        mViews = new SparseArray<View>();
        this.type = type;
    }
    public View getItemView() {
        return itemView;
    }
    /*
     * 通過空間id在SparseArray集合中找出用戶View
     * @param viewId  控件的id
     * @param <T>  具體的是那個控件
     * @return  當然是返回你要找的控件了
     */
    private <T extends View> T findViewById(int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }
    /**
     * 通過findViewById以及控件id的到用戶的空間對象
     *
     * @param viewId
     * @return
     */
    public View getView(int viewId) {
        return findViewById(viewId);
    }
    public TextView getTextView(int viewId) {
        return (TextView) getView(viewId);
    }
    public Button getButton(int viewId) {
        return (Button) getView(viewId);
    }
    public ImageView getImageView(int viewId) {
        return (ImageView) getView(viewId);
    }
    public ImageButton getImageButton(int viewId) {
        return (ImageButton) getView(viewId);
    }
    public EditText getEditText(int viewId) {
        return (EditText) getView(viewId);
    }
    public RecyclerViewHolder setText(int viewId, String value) {
        TextView view = findViewById(viewId);
        view.setText(value);
        return this;
    }
    public RecyclerViewHolder setBackground(int viewId, int resId) {
        View view = findViewById(viewId);
        view.setBackgroundResource(resId);
        return this;
    }
    public int getType() {
        return type;
    }
    public void setType(int type) {
        this.type = type;
    }
    /**
     * 通過該方法可以的到對應控件的點擊事件
     *
     * @param viewId   控件的id
     * @param listener 需要實現的監聽器
     * @return
     */
    public RecyclerViewHolder setClickListener(int viewId, View.OnClickListener listener) {
        View view = findViewById(viewId);
        view.setOnClickListener(listener);
        return this;
    }
}

運行

只要實現以上代碼,就能實現具體的內容。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容