RecyclerView從入門到深入


Android學(xué)習(xí)整理 - 系列


目錄:

  • 一 RecyclerView簡介
  • 二 RecyclerView為什么會出現(xiàn)
  • 三 基本使用方法
  • 四 高級用法
    1. Scrollbars

    2. Item間分割線

    3. Item顯示方式

    4. 自定義LayoutManager

    5. RecyclerView的點擊事件

    6. 高級效果 波紋點擊

    7. 添加 刪除時動畫

    8. 與某些View結(jié)合使用

    9. 滑動監(jiān)聽addOnScrollListener 可實現(xiàn)下拉刷新等

    10. ItemTouchHelper實現(xiàn)item刪除蠢涝,互相拉動

  • 五 RecyclerView多種布局顯示
  • 六 注意(未全)
  • 七 開源庫XRecyclerView

一 RecyclerView簡介

  • 官方對RecycleView的描述是在有限的窗口中大量顯示數(shù)據(jù)集
    靈活view,類似ListView,GridView

  • RecyclerView在support.V7包里钓试,個人覺得Google是為了用它來替代ListView

  • 可以實現(xiàn)
    1.ListView的功能(包括橫向)
    2.GridView的功能
    3.橫向ScrollView
    4.瀑布流
    5.方便添加animation(item的add remove時)


二 RecyclerView為什么會出現(xiàn)

優(yōu)點

  • 高度解耦汹族,隨意定制瑞凑。它提供的LayoutManager嗦随,ItemDecoration,ItemAnimator可以讓開發(fā)者自定義奇特的效果

  • RecyclerView封裝了ViewHolder

  • 通過設(shè)置LayoutManager可以設(shè)計Item的顯示的方式伸但,橫肾请,豎甚至瀑布流

  • 通過ItemDecoration可以控制Item間的間隔條,還有自定義間隔條

  • 通過ItemAnimator可以控制Item增刪的動畫

缺點

  • 短按長按點擊事件需要自己來實現(xiàn)(WTF)

雖然有缺點更胖,但是幾乎忽略不計铛铁,RecyclerView的隨意定制,其自帶的ViewHolder不再像ListView中ViewHolder作為View出現(xiàn)函喉,其“Recycle”的強大避归,一行代碼切換布局樣式的優(yōu)點使其勢必取代ListView

三 基本使用方法

當(dāng)前IDE:Android Studio 2.2正式版
jdk1.8.102
compileSdkVersion 25
buildToolsVersion "25.0.2"

gradle導(dǎo)包

compile 'com.android.support:recyclerview-v7:25.2.0'

然后layout布局文件中加入

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

code中需要

//設(shè)置布局管理器,必須
mRecyclerView.setLayoutManager(layout);
//設(shè)置RecycleView的Adapter管呵,必須
mRecyclerView.setAdapter(adapter)
//設(shè)置分割線梳毙,非必須
mRecyclerView.addItemDecoration(ItemDecoration);
//設(shè)置item的增刪動畫,非必須
mRecyclerView.setItemAnimator(animator);

現(xiàn)在先最簡單創(chuàng)建一個列表

新建Item的布局recycleview_item捐下,以TextView為根節(jié)點

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/recycle_textview"
          android:layout_width="match_parent"
          android:layout_height="50dp"
          android:gravity="center"
          android:textSize="20sp"/>

新建一個RecyclerView.Adapter適配器TestRecycleViewAdapter

public class TestRecycleViewAdapter extends RecyclerView.Adapter<TestRecycleViewAdapter.ViewHolderA> {
    private Context mContext;
    private List<String> mList;

    public TestRecycleViewAdapter(Context context, List<String> list) {
        mContext = context;
        mList = list;
    }

    @Override
    public ViewHolderA onCreateViewHolder(ViewGroup parent, int viewType) {
        //此處動態(tài)加載ViewHolder的布局文件并返回holder
        View view = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false);
        ViewHolderA holderA = new ViewHolderA(view);
        return holderA;
    }

    @Override
    public void onBindViewHolder(ViewHolderA holder, int position) {
        //此處設(shè)置Item中view的數(shù)據(jù)
        holder.mTextView.setText(mList.get(position));
    }

    @Override
    public int getItemCount() {
        //生成的item的數(shù)量
        return mList.size();
    }

    //Item的ViewHolder以及item內(nèi)部布局控件的id綁定
    class ViewHolderA extends RecyclerView.ViewHolder{

        TextView mTextView;
        public ViewHolderA(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.recycle_textview);
        }
    }
}

用Android Studio生成Adapter結(jié)構(gòu)技巧

  1. 先新建一個類TestRecycleViewAdapter
  2. 繼承自RecyclerView.Adapter<這里填ViewHolder名字的>账锹,現(xiàn)在出現(xiàn)紅線,先不管它
  3. 然后在TestRecycleViewAdapter 內(nèi)部寫內(nèi)部類ViewHolderA 繼承自 RecyclerView.ViewHolder坷襟,這個時候會自動生成構(gòu)造函數(shù)
  4. 接著將ViewHolder的名字ViewHolderA填入第2步粗體處奸柬,注意這里是內(nèi)部類所以正確填入是TestRecycleViewAdapter.ViewHolderA
  5. 接著點紅線,然后IDE會自己生成所需的3個方法

Activity中代碼是這樣

public class MainActivity extends AppCompatActivity {
    private List<String> list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.activity_main_recycle_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        initData();
        //實例化并傳輸數(shù)據(jù)給adapter
        TestRecycleViewAdapter adapter = new TestRecycleViewAdapter(getApplicationContext(), list);
        mRecyclerView.setAdapter(adapter);
    }

    /**
     *  添加數(shù)據(jù)
     * */
    private void initData() {
        list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            list.add("item" + i);
        }
    }
}

這樣子一個最基本的RecyclerView就寫好了婴程,效果圖

最基本的RecycleView

可以看到默認(rèn)沒有Scrollbars廓奕,沒有item之間的間隔線,沒有item點擊效果档叔,實際上這些我們需要自定義(雖然有點麻煩)


四 高級用法

1 Scrollbars

  • 只需要在RecycleView根節(jié)點加上
    android:scrollbars="vertical"
    默認(rèn)為none桌粉,還有橫向horizontal樣式的

2 Item間分割線

  • 可以給item設(shè)置margin,不過感覺好丑
    只要在item的layout里加上
          android:layout_marginTop="3dp"http://只需要這一行
          android:background="#cf1616"http://顯示成紅色比較明顯
android:layout_marginTop="3dp
  • 另外就是高大上的ItemDecoration了衙四,直接在code中加上
 mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

這里的context要注意用Activity的Context铃肯,假如用了Application的Context會顯示默認(rèn)的樣式,謝謝@且聽風(fēng)吟9527的提醒
context使用場景圖

數(shù)字1:啟動Activity在這些類中是可以的传蹈,但是需要創(chuàng)建一個新的task押逼,一般情況不推薦;
數(shù)字2:在這些類中去layout inflate是合法的惦界,但是會使用系統(tǒng)默認(rèn)的主題樣式挑格,如果你自定義了某些樣式可能不會被使用;
數(shù)字3:在Receiver為null時允許沾歪,在4.2或以上的版本中恕齐,用于獲取黏性廣播的當(dāng)前值。(可以無視);
ContentProvider显歧、BroadcastReceiver之所以在上述表格中,是因為在其內(nèi)部方法中都有一個context用于使用确镊。

2.png

但是我們不能僅限于此士骤,
默認(rèn)實現(xiàn)類DividerItemDecoration類中源代碼部分如下


public class DividerItemDecoration extends RecyclerView.ItemDecoration {
    public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
    public static final int VERTICAL = LinearLayout.VERTICAL;
    //關(guān)鍵在這里,看到有個屬性定義成了listDivider 
    private static final int[] ATTRS = new int[]{ android.R.attr.listDivider };

    .......


public DividerItemDecoration(Context context, int orientation) {
        //這里調(diào)用了屬性值listDivider
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    ........

所以蕾域,自定義間隔線步驟如下:

在Style文件里加上name="android:listDivider"的item
<item name="android:listDivider">@drawable/divider_backgroud</item>

書寫divider_bg.xml文件拷肌,shape文件為漸變xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:centerColor="#b3b35f"
        android:endColor="#515187"
        android:startColor="#b34747"
        android:type="linear" />
    <size android:height="5dp"/>
</shape>

這樣一個自定義間隔線樣式就好了

自定義間隔線

網(wǎng)絡(luò)與瀑布流的間隔線個人水平暫時弄不好.......(擱置中、旨巷、巨缘、、QAQ)


3 Item顯示方式

GridLayout

只需要將

mRecyclerView.setLayoutManager(layoutManager);

layoutManager設(shè)為

mRecyclerView.setLayoutManager(new GridLayoutManager(this, 5));

就可以實現(xiàn)5列的網(wǎng)格布局

11.png

我們看到網(wǎng)格樣式看起來像流式的List采呐,那是因為沒有左右間隔線的問題(其實是水平不行)若锁,
左右間隔線弄不出來QAQ,現(xiàn)在只能在recycleview_item.xml里面增加屬性做一個假的間隔線QAQ

android:layout_marginStart="1dp"
2.png

瀑布流

同上

mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
3.png

感覺上和網(wǎng)格布局沒啥差別斧吐,因為這上面的item我們使用了固定的高度又固,我們可以在適配器的onBindViewHolder方法中隨機設(shè)置item高度

  • 先在adapter的里聲明
private List<Integer> mHeight;
  • 在構(gòu)造方法里隨機生成高度值
mHeight = new ArrayList<Integer>();
        for (int i = 0; i < mList.size(); i++) {
            mHeight.add((int) (80 + Math.random() * 300));
        }
  • 接著在onBindViewHolder方法里
ViewGroup.LayoutParams lp = holder.mTextView.getLayoutParams();
 lp.height = mHeight.get(position);
瀑布流

類似的,不止有豎屏的效果煤率,橫屏的只要修改
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL));
就可以快速實現(xiàn)類似的效果


4 自定義LayoutManager

請參考
RecyclerView自定義LayoutManager,打造不規(guī)則布局

另外
對LayoutManager的分析,創(chuàng)建一個 RecyclerView LayoutManager


5 RecycleView的點擊事件

RecycleView并沒有提供類似setOnItemClickListener()這樣的注冊監(jiān)聽器方法,而是需要我們自己給子項view注冊響應(yīng)事件

我們只需要在Adapter的onBindViewHolder方法里添加

public void onBindViewHolder(ViewHolderA holder, final int position) {
        .....
         .....
        holder.mTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext, "item"+position,Toast.LENGTH_SHORT).show();
            }
        });

       .....
    }

這樣就輕松實現(xiàn)了TextView的點擊事件劫哼,同理划乖,長按的類似如此

點擊事件

RecycleView的強大之處也在這里,就算是ViewHolder里的View多層嵌套了幾個view都可以輕松的實現(xiàn)點擊事件


6 高級效果 波紋點擊

實現(xiàn)方法昼捍,在item布局文件根節(jié)點加上

android:foreground="?android:attr/selectableItemBackground"
波紋點擊效果

7 添加 刪除時動畫

在adapter里新添加方法

public void addData(int position){
        mList.add(position, "新增" + position);
      //通知適配器item內(nèi)容插入
        notifyItemInserted(position);
    }
public void RemoveData(int position){
        mList.remove(position);
       //通知適配器item內(nèi)容刪除
        notifyItemRemoved(position);
    }

然后在Activity里添加action欄菜單

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.menu_add:
            adapter.addData(1);
            break;
            case R.id.menu_remove:
                adapter.RemoveData(1);
            break;
        }
        return true;
    }

menu文件

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/menu_remove"
        android:icon="@android:drawable/alert_light_frame"
        android:title="remove"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/menu_add"
        android:icon="@android:drawable/ic_input_add"
        android:orderInCategory="100"
        android:title="add"
        app:showAsAction="ifRoom"/>
</menu>

然后识虚,這個是默認(rèn)的動畫,現(xiàn)在有很多開源庫端三,具體可以Google

mRecyclerView.setItemAnimator(new DefaultItemAnimator());
add remove animator

8 與某些View結(jié)合使用

  • 可以被SwipeRefreshLayout實現(xiàn)Android原生下拉刷新舷礼,也可以實現(xiàn)第三方下拉刷新
  • item可以使用CardView,恩郊闯,超漂亮

9 滑動監(jiān)聽addOnScrollListener 可實現(xiàn)下拉刷新等

實現(xiàn)這個借口的倆個方法

  • onScrollStateChanged
  • onScrolled
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            //標(biāo)記當(dāng)前是否向最后一項滑動
            boolean isSlidingToLast = false;

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                //獲取當(dāng)前的LayoutManager
                LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
                //當(dāng)不滾動的時候
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    //得到最后一個完全顯示的item的position
                    int lastViusalItem = manager.findLastCompletelyVisibleItemPosition();
                    //總的ITemPosition
                    int totalItemCount = manager.getItemCount();
                    //當(dāng)前是否向下滑妻献,是否滾動到LastItem
                    if (lastViusalItem == (totalItemCount - 1) && isSlidingToLast) {
                        // 這里就是下拉加載更多功能的邏輯
                        //往item的List里添加數(shù)據(jù),并通知適配器更新
                        adapter.addListData(lastViusalItem);

                    }
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //如果dy>0則當(dāng)前向下滑state
                if (dy > 0) {
                    isSlidingToLast = true;
                } else if (dy < 0) {
                    isSlidingToLast = false;
                }
            }
        });

adapter里添加

public void addListData(int position){
        for (int i = 0; i <6; i++) {
            mList.add("底部添加" + i);
        }
        //通知適配器item內(nèi)容刪除
        notifyItemChanged(position);
    }

這里的LayoutManager對象manager還可以獲取到很多參數(shù)团赁,比如

可以用tm來實現(xiàn)更多邏輯功能

自動加載

10 ItemTouchHelper實現(xiàn)item刪除育拨,互相拉動

一個大神寫的

Android實現(xiàn)RecyclerView側(cè)滑刪除和長按拖拽-ItemTouchHelper
,講的很清楚欢摄,這里不再詳解熬丧,貼上測試的代碼,僅做記錄

在setAdapter后面添加

      ItemTouchHelper.Callback mCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.DOWN|ItemTouchHelper.UP, ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                int fromPosition = viewHolder.getAdapterPosition();//得到拖動ViewHolder的position
                int toPosition = target.getAdapterPosition();//得到目標(biāo)ViewHolder的position
                if (fromPosition < toPosition){
//                向下
                    for (int i = fromPosition; i < toPosition; i++) {
                        Collections.swap(list, i, i+1);
                    }
                }else {
                    for (int i = fromPosition; i < toPosition; i++) {
                        //                向上
                        Collections.swap(list, i, i-1);
                    }
                }
                mTestRecycleViewAdapterMulType.notifyItemMoved(fromPosition, toPosition);
                //返回true表示執(zhí)行拖動
                return true;
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                int position = viewHolder.getAdapterPosition();
                list.remove(position);
                mTestRecycleViewAdapterMulType.notifyItemRemoved(position);
            }
        };

        ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(mCallback);
        mItemTouchHelper.attachToRecyclerView(mRecyclerView);

效果

1.gif

五 RecycleView多種布局顯示

先看效果

多布局

RecycleView.Adapter也提供了getItemViewType方法怀挠,此方法和ListView加載多布局一樣析蝴。

這里需要注意的是這里的范型不再是自己寫的ViewHolder

public class TestRecycleViewAdapterMulType extends RecyclerView.Adapter<RecyclerView.ViewHolder>

重寫adapter的getItemViewType

 public int getItemViewType(int position) {
        if (position == 0) {
            //111代表頂部item
            return 111;
        } else if (position == getItemCount() - 1) {
            //111代表di部item
            return 112;
        }
        //111代表中間item
        return 110;
    }

自定義3個ViewHolder害捕,分別表示top ,bottom 和中間的item布局

/**
     * 代表頂部item
     */
    class ViewHolderA extends RecyclerView.ViewHolder {
        ImageView mImageViewA;

        public ViewHolderA(View itemView) {
            super(itemView);
            mImageViewA = (ImageView) itemView.findViewById(R.id.top_imageview);
        }
    }

    /**
     * 代表di部item
     */
    class ViewHolderB extends RecyclerView.ViewHolder {
        ImageView mImageViewB;

        public ViewHolderB(View itemView) {
            super(itemView);
            mImageViewB = (ImageView) itemView.findViewById(R.id.bottom_imageview);
        }
    }

    /**
     * 代表中間item
     */
    class ViewHolderC extends RecyclerView.ViewHolder {
        TextView mTextView;

        public ViewHolderC(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.recycle_textview);
        }
    }

在onCreateViewHolder方法里

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = null;
        RecyclerView.ViewHolder holder = null;
        //此處動態(tài)加載ViewHolder的布局文件并返回holder
        switch (viewType) {
            case 111:
                //111代表頂部item
                view = LayoutInflater.from(mContext).inflate(R.layout.top, parent, false);
                holder = new ViewHolderA(view);
                break;
            case 112:
                //112代表頂部item
                view = LayoutInflater.from(mContext).inflate(R.layout.bottom, parent, false);
                holder = new ViewHolderB(view);
                break;
            case 110:
                //112代表中間item
                view = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false);
                holder = new ViewHolderC(view);
                break;
        }
        return holder;
    }

最后是onBindViewHolder闷畸,在這里分別設(shè)置不同布局item數(shù)據(jù)

@Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
//        //這樣寫也行
//        if(holder instanceof ViewHolderA){
//            ViewHolderA holderA = (ViewHolderA) holder;
//            holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
//        }else if(holder instanceof ViewHolderB).....
//        .....
        switch (getItemViewType(position)) {
            case 111:
                ViewHolderA holderA = (ViewHolderA) holder;
                holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
                break;
            case 112:
                ViewHolderB holderB = (ViewHolderB) holder;
                holderB.mImageViewB.setImageResource(R.mipmap.ic_launcher);
                break;
            case 110:
                ViewHolderC holderC = (ViewHolderC) holder;
                holderC.mTextView.setText(mList.get(position));
                break;
        }
    }

貼一下完整Adapter代碼

**
 * Created by NIWA on 2017/3/9.
 */

public class TestRecycleViewAdapterMulType extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context mContext;
    private List<String> mList;

    public TestRecycleViewAdapterMulType(Context context, List<String> list) {
        mContext = context;
        mList = list;
        
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = null;
        RecyclerView.ViewHolder holder = null;
        //此處動態(tài)加載ViewHolder的布局文件并返回holder
        switch (viewType) {
            case 111:
                //111代表頂部item
                view = LayoutInflater.from(mContext).inflate(R.layout.top, parent, false);
                holder = new ViewHolderA(view);
                break;
            case 112:
                //112代表頂部item
                view = LayoutInflater.from(mContext).inflate(R.layout.bottom, parent, false);
                holder = new ViewHolderB(view);
                break;
            case 110:
                //112代表中間item
                view = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false);
                holder = new ViewHolderC(view);
                break;
        }
        return holder;
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
//        //這樣寫也行
//        if(holder instanceof ViewHolderA){
//            ViewHolderA holderA = (ViewHolderA) holder;
//            holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
//        }else if(holder instanceof ViewHolderB).....
//        .....
        switch (getItemViewType(position)) {
            case 111:
                ViewHolderA holderA = (ViewHolderA) holder;
                holderA.mImageViewA.setImageResource(R.mipmap.ic_launcher);
                break;
            case 112:
                ViewHolderB holderB = (ViewHolderB) holder;
                holderB.mImageViewB.setImageResource(R.mipmap.ic_launcher);
                break;
            case 110:
                ViewHolderC holderC = (ViewHolderC) holder;
                holderC.mTextView.setText(mList.get(position));
                break;
        }
    }

    @Override
    public int getItemCount() {
        //生成的item的數(shù)量
        return mList.size();
    }


    /**
     * 代表頂部item
     */
    class ViewHolderA extends RecyclerView.ViewHolder {
        ImageView mImageViewA;

        public ViewHolderA(View itemView) {
            super(itemView);
            mImageViewA = (ImageView) itemView.findViewById(R.id.top_imageview);
        }
    }

    /**
     * 代表di部item
     */
    class ViewHolderB extends RecyclerView.ViewHolder {
        ImageView mImageViewB;

        public ViewHolderB(View itemView) {
            super(itemView);
            mImageViewB = (ImageView) itemView.findViewById(R.id.bottom_imageview);
        }
    }

    /**
     * 代表中間item
     */
    class ViewHolderC extends RecyclerView.ViewHolder {
        TextView mTextView;

        public ViewHolderC(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.recycle_textview);
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            //111代表頂部item
            return 111;
        } else if (position == getItemCount() - 1) {
            //因為item是從0開始尝盼,所以最后一項應(yīng)該是getItemCount() - 1
            //111代表di部item
            return 112;
        }
        //111代表中間item
        return 110;
    }

}

最后在Activity里

mTestRecycleViewAdapterMulType = new TestRecycleViewAdapterMulType(getApplicationContext(), list);
        mRecyclerView.setAdapter(mTestRecycleViewAdapterMulType);

heiheihei

六 注意

    1. 刷新數(shù)據(jù)的幾個方法
notifyItemInserted();
notifyItemRangeInserted();

notifyItemChanged();
notifyItemRangeChanged();

notifyItemRemoved();
notifyItemRangeRemoved();

七 開源庫

1. XRecyclerView

據(jù)我所知,支付寶用了這個庫佑菩,比較輕量級別

  • 用法和原生RecycleView一樣
  • 封裝好了下拉刷新盾沫,上拉加載,刷新動畫
  • 增加頭部殿漠,甚至增加倆個headerView

2.BaseRecyclerViewAdapterHelper

用了之后你才發(fā)現(xiàn)RecyclerView的Adapter也可以寫的這么優(yōu)雅赴精,功能很全,ListView時代的感覺绞幌。


當(dāng)然一切開源庫蕾哟,不要過度依賴開源庫,一切都要建立在踏實的基礎(chǔ)上啊奄,以上多加練習(xí)渐苏。


The End

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市菇夸,隨后出現(xiàn)的幾起案子琼富,更是在濱河造成了極大的恐慌,老刑警劉巖庄新,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鞠眉,死亡現(xiàn)場離奇詭異,居然都是意外死亡择诈,警方通過查閱死者的電腦和手機械蹋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羞芍,“玉大人哗戈,你說我怎么就攤上這事『煽疲” “怎么了唯咬?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畏浆。 經(jīng)常有香客問我胆胰,道長,這世上最難降的妖魔是什么刻获? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任蜀涨,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厚柳。我一直安慰自己氧枣,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布别垮。 她就那樣靜靜地躺著挑胸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宰闰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天簿透,我揣著相機與錄音移袍,去河邊找鬼。 笑死老充,一個胖子當(dāng)著我的面吹牛葡盗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啡浊,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼觅够,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了巷嚣?” 一聲冷哼從身側(cè)響起喘先,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎廷粒,沒想到半個月后窘拯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡坝茎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年涤姊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤放。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡思喊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出次酌,到底是詐尸還是另有隱情恨课,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布和措,位于F島的核電站庄呈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏派阱。R本人自食惡果不足惜诬留,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧文兑,春花似錦盒刚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至籍铁,卻和暖如春涡上,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拒名。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工吩愧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人增显。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓雁佳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親同云。 傳聞我的和親對象是個殘疾皇子糖权,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 最近做了一個Android UI相關(guān)開源項目庫匯總,里面集合了OpenDigg 上的優(yōu)質(zhì)的Android開源項目庫...
    OpenDigg閱讀 17,199評論 6 222
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點贊按鈕進度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,766評論 22 665
  • https://segmentfault.com/a/1190000005356568
    灰斗兒閱讀 326評論 0 0
  • 家有二貨狗及驕傲無比公主貓各一只炸站,都是土得不能再土的品種星澳,這些遍地都是的物種就如同路邊的野草般在農(nóng)村這兒大都不太受...
    云中瑞麟閱讀 460評論 0 0