Android——RecyclerView入門學(xué)習(xí)之RecyclerView.Adapter(三)

學(xué)習(xí)資料:

之前使用RecyclerView.Adapter,基本就類似套用公式,死步驟,對(duì)Adapter感到既熟悉又陌生。從去年我開始接觸學(xué)習(xí)Android之時(shí),RecyclerView已經(jīng)開始大量被運(yùn)用,逐步取代ListView。遂,正好,那就先直接學(xué)習(xí)RecyclerView.Adapter相關(guān)知識(shí)


1. RecyclerView.Adapter適配器

RecyclerView.Adapter,一個(gè)抽象類,并支持泛型

public static abstract class Adapter<VH extends ViewHolder> {
   ...
}

定義一個(gè)MyRecyclerViewAdapter繼承RecyclerView.Adapter后,Android Stuido提醒需要重寫3個(gè)方法,在重寫3個(gè)方法前,一般會(huì)先定義一個(gè)Holder繼承RecycelrView.ViewHolder,之后直接在MyRecyclerViewAdapter上,指定泛型就是RecyclerHolder

3個(gè)需要必須重寫的方法:

方法1:public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)

方法2:public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)

方法3:public int getItemCount()

在指定了泛型為RecyclerHoler后,方法2也會(huì)根據(jù)泛型改變onBindViewHolder(RecyclerHolder holder, int position)


1.1 onCreateViewHolder(ViewGroup parent, int viewType)創(chuàng)建Holder

源碼:

/**
 * Called when RecyclerView needs a new {@link ViewHolder} of the given type to represent an item.
 * 
 * @param parent The ViewGroup into which the new View will be added after it is bound to an adapter position.
 * @param viewType The view type of the new View.
 *
 * @return A new ViewHolder that holds a View of the given view type.
 */
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
  • ViewGroup parent:可以簡(jiǎn)單理解為item的根ViewGroupitem的子控件加載在其中
  • int viewTypeitem的類型,可以根據(jù)viewType來(lái)創(chuàng)建不同的ViewHolder,來(lái)加載不同的類型的item

這個(gè)方法就是用來(lái)創(chuàng)建出一個(gè)新的ViewHolder,可以根據(jù)需求的itemType,創(chuàng)建出多個(gè)ViewHolder。創(chuàng)建多個(gè)itemType時(shí),需要getItemViewType(int position)方法配合


1.2 onBindViewHolder(RecyclerHolder holder, int position)綁定ViewHolder

源碼:

**
*Called by RecyclerView to display the data at the specified position.
*This method should update the contents of the {@link ViewHolder#itemView} to reflect the item at the given position.
* 
*@param holder The ViewHolder which should be updated to represent the contents of the item at the given position in the data set.
*@param position The position of the item within the adapter's data set.
*/

public abstract void onBindViewHolder(VH holder, int position);
  • VH holder:就是在onCreateViewHolder()方法中,創(chuàng)建的ViewHolder
  • int positionitem對(duì)應(yīng)的DataList數(shù)據(jù)源集合的postion

postion就是adapter positionRecycelrViewitem的數(shù)量,就是根據(jù)DataList數(shù)據(jù)源集合的數(shù)量來(lái)創(chuàng)建的


1.3 getItemCount()獲取Item的數(shù)目

源碼:

/**
 * Returns the total number of items in the data set held by the adapter.
 *
 * @return The total number of items in this adapter.
 */
public abstract int getItemCount();

這個(gè)方法的返回值,便是RecyclerView中實(shí)際item的數(shù)量。有些情況下,當(dāng)增加了HeaderView或者FooterView后,需要注意考慮這個(gè)返回值


1.4 簡(jiǎn)單shi yong

一個(gè)最簡(jiǎn)單的RecyclerViewAdapter

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.RecyclerHolder> {
    private Context mContext;
    private List<String> dataList = new ArrayList<>();

    public MyRecyclerViewAdapter(RecyclerView recyclerView) {
        this.mContext = recyclerView.getContext();
    }

    public void setData(List<String> dataList) {
        if (null != dataList) {
            this.dataList.clear();
            this.dataList.addAll(dataList);
            notifyDataSetChanged();
        }
    }

    @Override
    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout, parent, false);
        return new RecyclerHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position) {
        holder.textView.setText(dataList.get(position));
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    class RecyclerHolder extends RecyclerView.ViewHolder {
        TextView textView;

        private RecyclerHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv__id_item_layout);
        }
    }
}

我的個(gè)人習(xí)慣是單獨(dú)使用一個(gè)setData()方法將DataList傳遞進(jìn)Adapter,看到網(wǎng)上有一些博客中會(huì)通過(guò)構(gòu)造方法傳遞。我一般會(huì)在網(wǎng)絡(luò)請(qǐng)求前就初始化Adapter,當(dāng)異步網(wǎng)絡(luò)請(qǐng)求拿到解析過(guò)的JSON數(shù)據(jù)后,調(diào)用這個(gè)方法將數(shù)據(jù)加載進(jìn)Adapter,即使做了分頁(yè),也可以比較方。但感覺這種方法終究會(huì)浪費(fèi)一點(diǎn)性能

注意,在 onCreateViewHolder()方法中:

View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout, parent, false);

inflate()方法使用的是3個(gè)參數(shù)的方法。


1.4.1 問(wèn)題

以前使用2個(gè)參數(shù)的方法inflate(@LayoutRes int resource, @Nullable ViewGroup root),下面的形式

View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout,null);

遇到的一個(gè)問(wèn)題

2個(gè)參數(shù)方法遇到的問(wèn)題

兩種方法,使用的是同一套布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv__id_item_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:textAllCaps="false"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</LinearLayout>

item內(nèi)的TextView的寬是match_parent,但使用兩個(gè)參數(shù)的方法時(shí),看起來(lái)卻是wrap_content的效果


1.4.2嘗試從源碼中找問(wèn)題

兩個(gè)參數(shù)的方法源碼

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
        return inflate(resource, root, root != null);
}

兩個(gè)參數(shù)的方法內(nèi)部調(diào)用了3個(gè)參數(shù)的方法,此時(shí)inflate(resourceId, null, false)rootnullattachToRootfalse

最終來(lái)到了這里,只保留了部分代碼:

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    ...
    
    View result = root;
    
    ...
    
    // Temp is the root view that was found in the xml
    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

    ViewGroup.LayoutParams params = null;
    ...
    
    if (root != null) {
    
        ...
        
        params = root.generateLayoutParams(attrs);
        
        ...               
    }
    
    ...
    
    rInflateChildren(parser, temp, attrs, true);
    
    ...
    
    if (root == null || !attachToRoot) {
        result = temp;
    }
 }

使用兩個(gè)參數(shù)的inflate()方法,ViewGroup.LayoutParams params最終為null;而如果使用3個(gè)參數(shù)的方法,最終params = params = root.generateLayoutParams(attrs)

這里為了減少出現(xiàn)問(wèn)題的出現(xiàn),就使用3個(gè)參數(shù)的方法inflate(R.layout.id_rv_item_layout, parent, false)

這里看源碼也就看了這小段一段,inflate()方法的完整過(guò)程還是比較復(fù)雜的,比較淺顯的知道問(wèn)題出在哪里后,沒有深挖


1.4 點(diǎn)擊事件

完整代碼:

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.RecyclerHolder> {
    private Context mContext;
    private List<String> dataList = new ArrayList<>();
    private onRecyclerItemClickerListener mListener;

    public MyRecyclerViewAdapter(RecyclerView recyclerView) {
        this.mContext = recyclerView.getContext();
    }


    /**
     * 增加點(diǎn)擊監(jiān)聽
     */
    public void setItemListener(onRecyclerItemClickerListener mListener) {
        this.mListener = mListener;
    }

    /**
     * 設(shè)置數(shù)據(jù)源
     */
    public void setData(List<String> dataList) {
        if (null != dataList) {
            this.dataList.clear();
            this.dataList.addAll(dataList);
            notifyDataSetChanged();
        }
    }

    public List<String> getDataList() {
        return dataList;
    }

    @Override
    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout, parent, false);
        // View view = LayoutInflater.from(mContext).inflate(R.layout.id_rv_item_layout,null);
        return new RecyclerHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerHolder holder, int position) {
        holder.textView.setText(dataList.get(position));
        holder.textView.setOnClickListener(getOnClickListener(position));
    }

    private View.OnClickListener getOnClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mListener && null != v) {
                    mListener.onRecyclerItemClick(v, dataList.get(position), position);
                }
            }
        };
    }


    @Override
    public int getItemCount() {
        return dataList.size();
    }

    class RecyclerHolder extends RecyclerView.ViewHolder {
        TextView textView;

        private RecyclerHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv__id_item_layout);
        }
    }

    /**
     * 點(diǎn)擊監(jiān)聽回調(diào)接口
     */
    public interface onRecyclerItemClickerListener {
        void onRecyclerItemClick(View view, Object data, int position);
    }
}

定義一個(gè)接口onRecyclerItemClickerListener,這樣可以在Actiivty設(shè)置監(jiān)聽對(duì)象,之后為TextView設(shè)置點(diǎn)擊監(jiān)聽事件,在TextView的點(diǎn)擊事件方法中,使用onRecyclerItemClick()進(jìn)行回調(diào)


在Activity中使用:

//設(shè)置點(diǎn)擊事件
adapter.setItemListener(new MyRecyclerViewAdapter.onRecyclerItemClickerListener() {
    @Override
    public void onRecyclerItemClick(View view, Object data, int position) {
        String s = (String) data;
        adapter.getDataList().set(position, s + "---->hi");
            adapter.notifyItemChanged(position);
        }
});

在監(jiān)控對(duì)象回調(diào)方法中,使用了notifyItemChanged(position)來(lái)進(jìn)行局部刷新

點(diǎn)擊進(jìn)行局部刷新

但這種方式會(huì)new出一大堆View.OnClickListener,還有一種思路是利用RecycelrViewonTouchListenerGestureDetector手勢(shì)來(lái)進(jìn)行設(shè)置,可以看看三種方式實(shí)現(xiàn)RecyclerView的Item點(diǎn)擊事件


1.5 一系列的notifyData方法

一共有10個(gè)方法

方法 作用
notifyDataSetChanged() 通知RecycelrView進(jìn)行全局刷新
notifyItemChanged(int position) 通知RecycelrViewadapter position處局進(jìn)行部刷新
notifyItemRemoved(int position) 通知RecyclerView移除在adapter position處的item
notifyItemMoved(int fromPosition, int toPosition) 通知RecyclerView移除從fromPositiontoPositionitem
notifyItemRangeRemoved(int positionStart, int itemCount) 通知RecyclerView移除從positionStart開始的itemCount個(gè)item
notifyItemChanged(int position, Object payload) 通知RecyclerView改變指定positionitemobject
notifyItemRangeChanged(int positionStart,int itemCount) 通知RecyclerViewpositionStart開始改變itemCount個(gè)item
notifyItemRangeChanged(int positionStart,int itemCount,Object payload) 通知RecyclerViewpositionStart開始改變itemCount個(gè)item的對(duì)象
notifyItemInserted(int position) 通知RecyclerViewposition處插入一個(gè)item
notifyItemRangeInserted(int positionStart, int itemCount) 通知RecyclerViewpositionStart開始插入itemCount個(gè)item

有些情況下,方法需要考慮組合使用,否則可能出現(xiàn)position錯(cuò)亂,例如

在Adapter中移除或者插入item

/**
 * 移除指定Position的Item
 */
public void remove(int position) {
    if (dataList.size() == 0) return;
    dataList.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position, dataList.size() - position);
}

//在Activity中使用 ,設(shè)置點(diǎn)擊事件
adapter.setItemListener(new MyRecyclerViewAdapter.onRecyclerItemClickerListener() {
    @Override
    public void onRecyclerItemClick(View view, Object data, int position) {
        adapter.remove(position);
        // String s = (String) data;
        // adapter.inserted(position,s+"---->hi");
    }
});

//在指定位置插入一個(gè)item
public void inserted(int position, String s) {
    if (dataList.size() == 0) return;
    dataList.add(position, s);
    notifyItemInserted(position);
    notifyItemRangeChanged(position, dataList.size() - position);
}

notifyItemRemoved(position)雖然通知移除了RecycelrViewposition位置上的itemA,但itemA之后的一系列item也需要進(jìn)行改變,也需要通知RecyclerView進(jìn)行改變

但這兩個(gè)方法性能上都有問(wèn)題,卡頓比較明顯,應(yīng)該會(huì)有更好的動(dòng)態(tài)改變或者動(dòng)態(tài)插入item的方法,以后學(xué)到了再補(bǔ)充


1.5 簡(jiǎn)易的封裝

通用的ViewHolder:

public class BaseViewHolder extends RecyclerView.ViewHolder {
    private final SparseArray<View> sparseArray;

    public BaseViewHolder(View itemView) {
        super(itemView);
        this.sparseArray = new SparseArray<>(8); //一般一個(gè)Item 不會(huì)超過(guò)8種控件
    }

    public <T extends View> T getView(int viewId) {
        View view = sparseArray.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            sparseArray.put(viewId, view);
        }
        return (T) view;
    }

    public BaseViewHolder setText(int viewId, String text) {
        TextView tv = getView(viewId);
        if (tv != null) {
            tv.setText(text);
        }
        return this;
    }
}

主要思路就是使用SparseArray<View>將控件存起來(lái)


適配器:

public abstract class CommonBaseAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
    protected List<T> data = new ArrayList<>();
    protected int itemLayoutId;
    protected Context mContext;
    private onRecyclerItemClickerListener mListener;

    public CommonBaseAdapter(RecyclerView rv, @LayoutRes int itemLayoutId) {
        this.itemLayoutId = itemLayoutId;
        this.mContext = rv.getContext();
    }

    public void setData(List<T> data) {
        if (data != null) {
            this.data.clear();
            this.data.addAll(data);
            notifyDataSetChanged();
        }
    }

    /**
     *  增加點(diǎn)擊監(jiān)聽
     */
    public void setItemListener(onRecyclerItemClickerListener mListener) {
        this.mListener = mListener;
    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //這里使用3個(gè)參數(shù)的方法
        View view = LayoutInflater.from(mContext).inflate(itemLayoutId, parent, false);
        return new BaseViewHolder(view);
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        bindViewData(holder, data.get(position), position);
        holder.itemView.setOnClickListener(getOnClickListener(position));
    }

    private View.OnClickListener getOnClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener != null && v != null) {
                    mListener.onRecyclerItemClick(v, data.get(position), position);
                }
            }
        };
    }

    @Override
    public int getItemCount() {
        return this.data.size();
    }

    public abstract void bindViewData(BaseViewHolder holder, T item, int position);

    interface onRecyclerItemClickerListener {
        void onRecyclerItemClick(View view, Object data, int position);
    }
}

內(nèi)部提供一個(gè)抽象方法bindViewData(),子類重寫抽象方法來(lái)做一些具體的操作。

封裝的很簡(jiǎn)單,但平常學(xué)習(xí)使用也能減少一些重復(fù)代碼。網(wǎng)上有很多強(qiáng)大的封裝,可以再深入學(xué)習(xí)一下為RecyclerView打造通用Adapter讓RecyclerView更加好用


使用:

public class RecyclerViewAdapter extends CommonBaseAdapter<String> {

    public RecyclerViewAdapter(RecyclerView rv, @LayoutRes int itemLayoutId, @IdRes int resId) {
        super(rv, itemLayoutId);

    }

    @Override
    public void bindViewData(BaseViewHolder holder, String item, int position) {
        holder.setText(R.id.textViewId, item);
    }
}

Activity中就可以進(jìn)行使用

這個(gè)簡(jiǎn)易的封裝并沒有對(duì)添加加載圖片的方法。加載圖片的方法一開始也我封裝在了這個(gè)CommonBaseAdapter中,但后來(lái)發(fā)現(xiàn)直接封裝在這里并不是好的思路

圖片需要做的處理比較多,而且主流的庫(kù)有3個(gè),為了易于維護(hù),還是將圖片的操作單獨(dú)再封裝在一個(gè)工具類中,在CommonBaseAdapter中使用操作圖片的工具類比較好


1.6 添加HeaderView和FooterViewiew

學(xué)的鴻洋大神的代碼和思路,涉及到了裝飾模式。還有一種添加方式是直接通過(guò)使用多種item直接在現(xiàn)有的CommonBaseAdapter來(lái)修改,但感覺這種思路需要對(duì)CommonBaseAdapter改動(dòng)的代碼太多,點(diǎn)擊事件的position也需要考慮,不如鴻洋大神的這種思路易于開發(fā)和維護(hù)

代碼:

public class HeaderAndFooterAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    private CommonBaseAdapter mAdapter;

    private static final int HEADER_VIEW_TYPE = 2 << 6;
    private static final int FOOTER_VIEW_TYPE = 2 << 5;

    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();
    private SparseArrayCompat<View> mFooterViews = new SparseArrayCompat<>();

    public HeaderAndFooterAdapter(CommonBaseAdapter mAdapter) {
        this.mAdapter = mAdapter;
    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (null != mHeaderViews.get(viewType)) {
            return new HeaderAndFooterHolder(mHeaderViews.get(viewType));
        } else if (null != mFooterViews.get(viewType)) {
            return new HeaderAndFooterHolder(mFooterViews.get(viewType));
        }
        return mAdapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        if (isHeaderViewPosition(position)) return;
        if (isFooterViewPosition(position)) return;
        mAdapter.onBindViewHolder(holder, position - getHeaderViewCount());
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderViewPosition(position)) {
            return mHeaderViews.keyAt(position);
        } else if (isFooterViewPosition(position)) {
            return mFooterViews.keyAt(position-getHeaderViewCount()-getAdapterItemCount());
        }
        return mAdapter.getItemViewType(position - getHeaderViewCount());
    }

    @Override
    public int getItemCount() {
        return getHeaderViewCount() + getFooterViewCount() + getAdapterItemCount();
    }

    /**
     * 加入HeaderView
     */
    public void addHeaderView(View view) {
        mHeaderViews.put(mHeaderViews.size() + HEADER_VIEW_TYPE, view);
    }

    /**
     * 加入FooterView
     */
    public void addFootView(View view) {
        mFooterViews.put(mFooterViews.size() + FOOTER_VIEW_TYPE, view);
    }

    /**
     * HeaderView 的數(shù)目
     */
    public int getHeaderViewCount() {
        return mHeaderViews.size();
    }

    /**
     * FooterView 的數(shù)目
     */
    public int getFooterViewCount() {
        return mFooterViews.size();
    }

    /**
     * 是不是HeaderView的Position
     */
    private boolean isHeaderViewPosition(int position) {
        return position < getHeaderViewCount();
    }


    /**
     * 是不是FooterView的Position
     */
    private boolean isFooterViewPosition(int position) {
        return position >= getHeaderViewCount() + getAdapterItemCount();
    }

    /**
     * 得到Adapter中Item的數(shù)目
     */
    private int getAdapterItemCount() {
        return mAdapter.getItemCount();
    }

    private class HeaderAndFooterHolder extends BaseViewHolder {
        private HeaderAndFooterHolder(View itemView) {
            super(itemView);
        }
    }
}

封裝的思路:
add進(jìn)來(lái)的view進(jìn)行保存,當(dāng)加載item時(shí),利用itemType對(duì)view進(jìn)行類型判斷,如果是HeaderView或者FooterView就創(chuàng)建HeaderAndFooterHolder,然后綁定只是用來(lái)顯示并沒有對(duì)HeaderView或者FooterView做其他更多事件的處理


使用也比較方便:

//數(shù)據(jù)適配器
RecyclerViewAdapter adapter = new RecyclerViewAdapter(rv, R.layout.id_rv_item_layout, R.id.tv__id_item_layout);
//頭View適配器
HeaderAndFooterAdapter headerAndFooterAdapter = new HeaderAndFooterAdapter(adapter);
//HeaderView
TextView headerView = new TextView(this);
headerView.setBackgroundColor(Color.BLACK);
headerView.setTextColor(Color.WHITE);
headerView.setWidth(1080);
headerView.setTextSize(50);
headerView.setText("我是頭");
headerAndFooterAdapter.addHeaderView(headerView);
//設(shè)置適配器
rv.setAdapter(headerAndFooterAdapter);
//添加數(shù)據(jù)
addData(adapter);
添加HeaderView

RecyelrView設(shè)置的適配器是headerAndFooterAdapter,而添加數(shù)據(jù)使用的是adapterHeaderAndFooterAdapter是支持添加多個(gè)HeaderView


1.6.1 GridLayoutManger和StaggeredGridLayoutManager跨列問(wèn)題

上面添加HeaderView時(shí),使用的LinerLayoutManager,當(dāng)使用GridLayoutManger時(shí),便會(huì)有問(wèn)題

HeaderView不能單獨(dú)占據(jù)一行

GridLayoutManager遇到問(wèn)題

加入針對(duì)GridLayoutManager跨列處理的代碼:

/**
 *當(dāng)RecyelrView開始觀察Adapter會(huì)被回調(diào)
 */
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    mAdapter.onAttachedToRecyclerView(recyclerView);
    final RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
    if (manager instanceof GridLayoutManager) {
        final GridLayoutManager gridLayoutManager = (GridLayoutManager) manager;
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                int viewType = getItemViewType(position);
                //如果是HeaderView或者是FooterView,設(shè)置占據(jù)gridLayoutManager.getSpanCount()列
                if (null != mHeaderViews.get(viewType) || null != mFooterViews.get(viewType)) {
                    return gridLayoutManager.getSpanCount();
                }
                return 1;
            }
        });
    }
}

跨列處理

當(dāng)布局管理器為GridLayouManger時(shí),對(duì)當(dāng)前要的添加的item進(jìn)行判斷,如果是HeaderView或者是FooterView,就進(jìn)行跨列處理,單獨(dú)占據(jù)一行


加入針對(duì)StaggeredGridLayoutManager跨列處理的代碼:

/**
 * 一個(gè)item通過(guò)adapter開始顯示會(huì)被回調(diào)
 */
@Override
public void onViewAttachedToWindow(BaseViewHolder holder) {
    super.onViewAttachedToWindow(holder);
    int position = holder.getLayoutPosition();
    if (isHeaderViewPosition(position)||isFooterViewPosition(position)){
        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
        if (null != lp && lp instanceof StaggeredGridLayoutManager.LayoutParams){
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
            p.setFullSpan(true);//占滿一行
        }
    }
}

瀑布流跨列

當(dāng)布局管理器為StaggeredGridLayoutManager時(shí),對(duì)當(dāng)前要的添加的item進(jìn)行判斷,如果是HeaderView或者是FooterView,就設(shè)置setFullSpan(true),占滿一行


2. 最后

RecyclerView.Adapter暫時(shí)大致就學(xué)習(xí)這些

本人很菜,有錯(cuò)誤請(qǐng)指出

共勉 :)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 過(guò)去的這一兩年, RecyclerView越來(lái)越引起了我們Android開發(fā)人員的注意,RecyclerView的...
    OlivineVip閱讀 1,292評(píng)論 0 14
  • 又到了更新博文的時(shí)間了,最近在看一本很不錯(cuò)的心理學(xué)書籍,名字叫做 《拖延心理學(xué)》,封面長(zhǎng)下面這樣子 書的內(nèi)容主要是...
    ec95b5891948閱讀 57,605評(píng)論 38 472
  • 本文已授權(quán)微信公眾號(hào):鴻洋(hongyangAndroid)在微信公眾號(hào)平臺(tái)原創(chuàng)首發(fā)。 轉(zhuǎn)載請(qǐng)標(biāo)明出處: http...
    專屬守護(hù)閱讀 1,524評(píng)論 0 2
  • 初識(shí)Android時(shí),我對(duì)ListView、GradView中的Adapter一直半懂非懂,每次寫Adapter都...
    blink_dagger閱讀 6,015評(píng)論 4 10
  • 本周的周檢視完成情況: 1.專業(yè)閱讀1h 要求一周四天, 實(shí)際6天已達(dá)到 量變會(huì)引起質(zhì)變 2.文學(xué)閱讀1h 要求一...
    KUNGFUBUNNY閱讀 141評(píng)論 0 1