Android RecyclerView使用詳解及實現多選

這裏要說的是RecyclerView的使用,希望能助你完全理解RecyclerView,把它運用到項目中,當然這裏也會提供你簡便的寫法,要知道每次都寫個adapter費時又費力,只能說本人很懶,於是在網上找方法,聰明的你應該知道是怎麼做了吧,不錯,就是打造一個通用的adapter。這裏先賣個關子,要知道就繼續往下看吧。

概述

RecyclerView 是Android L版本中新添加的一個可用來替換ListView和GridView的SDK,它的靈活性與可替代性比ListView和GridView更好。能夠在有限的窗口中展示大數據集合的靈活視圖,這就是所謂的RecyclerView吧。

如果你想使用RecyclerView,你將需要使用以下幾點:

*RecyclerView.Adapter – 處理數據收集並將其綁定到視圖
*ViewHolder – 持有所有的用於綁定數據或者需要操作的View
*LayoutManager – 負責擺放視圖等相關操作
*ItemDecoration – 負責繪製Item附近的分割線
*ItemAnimator – 爲item的一般操作添加動畫效果,比如添加或刪除條目

這裏寫圖片描述

想看最原始的使用方法,想知道更多的細節,請看這裏
如果你實在看不懂英文的話,這篇文章也能很好的說明使用方法,請看這裏

RecyclerView的簡單使用方法

這裏只給出單種item的示例代碼,更多使用方法()可看萬能適配器,這裏很感謝鴻神的開源,他的博客都很不錯,值得學習,各位客官,下面就請聽我步步道來:

  • 添加依賴
    在AS的 build.gradle 中添加依賴,然後同步一下就可以引入依賴包(記得換上你的最新版本):
dependencies {
    ...
    compile 'com.android.support:recyclerview-v7:23.3.0'
}
  • 佈局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"/>
</RelativeLayout>
  • 通用的ViewHolder
    這裏也適用於listview
public class ViewHolder extends RecyclerView.ViewHolder
{
    private SparseArray<View> mViews;
    private int mPosition;
    private View mConvertView;
    private Context mContext;
    private int mLayoutId;

    public ViewHolder(Context context, View itemView, ViewGroup parent, int position)
    {
        super(itemView);
        mContext = context;
        mConvertView = itemView;
        mPosition = position;
        mViews = new SparseArray<View>();
        mConvertView.setTag(this);

    }


    public static ViewHolder get(Context context, View convertView,
                                 ViewGroup parent, int layoutId, int position)
    {
        if (convertView == null)
        {
            View itemView = LayoutInflater.from(context).inflate(layoutId, parent,
                    false);
            ViewHolder holder = new ViewHolder(context, itemView, parent, position);
            holder.mLayoutId = layoutId;
            return holder;
        } else
        {
            ViewHolder holder = (ViewHolder) convertView.getTag();
            holder.mPosition = position;
            return holder;
        }
    }


    /**
     * 通過viewId獲取控件
     *
     * @param viewId
     * @return
     */
    public <T extends View> T getView(int viewId)
    {
        View view = mViews.get(viewId);
        if (view == null)
        {
            view = mConvertView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    public View getConvertView()
    {
        return mConvertView;
    }

    /**
     * 設置TextView的值
     *
     * @param viewId
     * @param text
     * @return
     */
    public ViewHolder setText(int viewId, String text)
    {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    public ViewHolder setImageResource(int viewId, int resId)
    {
        ImageView view = getView(viewId);
        view.setImageResource(resId);
        return this;
    }

    public ViewHolder setImageBitmap(int viewId, Bitmap bitmap)
    {
        ImageView view = getView(viewId);
        view.setImageBitmap(bitmap);
        return this;
    }

    public ViewHolder setImageDrawable(int viewId, Drawable drawable)
    {
        ImageView view = getView(viewId);
        view.setImageDrawable(drawable);
        return this;
    }

    public ViewHolder setBackgroundColor(int viewId, int color)
    {
        View view = getView(viewId);
        view.setBackgroundColor(color);
        return this;
    }

    public ViewHolder setBackgroundRes(int viewId, int backgroundRes)
    {
        View view = getView(viewId);
        view.setBackgroundResource(backgroundRes);
        return this;
    }

    public ViewHolder setTextColor(int viewId, int textColor)
    {
        TextView view = getView(viewId);
        view.setTextColor(textColor);
        return this;
    }

    public ViewHolder setTextColorRes(int viewId, int textColorRes)
    {
        TextView view = getView(viewId);
        view.setTextColor(mContext.getResources().getColor(textColorRes));
        return this;
    }

    @SuppressLint("NewApi")
    public ViewHolder setAlpha(int viewId, float value)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        {
            getView(viewId).setAlpha(value);
        } else
        {
            // Pre-honeycomb hack to set Alpha value
            AlphaAnimation alpha = new AlphaAnimation(value, value);
            alpha.setDuration(0);
            alpha.setFillAfter(true);
            getView(viewId).startAnimation(alpha);
        }
        return this;
    }

    public ViewHolder setVisible(int viewId, boolean visible)
    {
        View view = getView(viewId);
        view.setVisibility(visible ? View.VISIBLE : View.GONE);
        return this;
    }

    public ViewHolder linkify(int viewId)
    {
        TextView view = getView(viewId);
        Linkify.addLinks(view, Linkify.ALL);
        return this;
    }

    public ViewHolder setTypeface(Typeface typeface, int... viewIds)
    {
        for (int viewId : viewIds)
        {
            TextView view = getView(viewId);
            view.setTypeface(typeface);
            view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
        }
        return this;
    }

    public ViewHolder setProgress(int viewId, int progress)
    {
        ProgressBar view = getView(viewId);
        view.setProgress(progress);
        return this;
    }

    public ViewHolder setProgress(int viewId, int progress, int max)
    {
        ProgressBar view = getView(viewId);
        view.setMax(max);
        view.setProgress(progress);
        return this;
    }

    public ViewHolder setMax(int viewId, int max)
    {
        ProgressBar view = getView(viewId);
        view.setMax(max);
        return this;
    }

    public ViewHolder setRating(int viewId, float rating)
    {
        RatingBar view = getView(viewId);
        view.setRating(rating);
        return this;
    }

    public ViewHolder setRating(int viewId, float rating, int max)
    {
        RatingBar view = getView(viewId);
        view.setMax(max);
        view.setRating(rating);
        return this;
    }

    public ViewHolder setTag(int viewId, Object tag)
    {
        View view = getView(viewId);
        view.setTag(tag);
        return this;
    }

    public ViewHolder setTag(int viewId, int key, Object tag)
    {
        View view = getView(viewId);
        view.setTag(key, tag);
        return this;
    }

    public ViewHolder setChecked(int viewId, boolean checked)
    {
        Checkable view = (Checkable) getView(viewId);
        view.setChecked(checked);
        return this;
    }

    /**
     * 關於事件的
     */
    public ViewHolder setOnClickListener(int viewId,
                                         View.OnClickListener listener)
    {
        View view = getView(viewId);
        view.setOnClickListener(listener);
        return this;
    }

    public ViewHolder setOnTouchListener(int viewId,
                                         View.OnTouchListener listener)
    {
        View view = getView(viewId);
        view.setOnTouchListener(listener);
        return this;
    }

    public ViewHolder setOnLongClickListener(int viewId,
                                             View.OnLongClickListener listener)
    {
        View view = getView(viewId);
        view.setOnLongClickListener(listener);
        return this;
    }

    public void updatePosition(int position)
    {
        mPosition = position;
    }

    public int getLayoutId()
    {
        return mLayoutId;
    }
}
  • 通用的Adapter
public abstract class CommonAdapter<T> extends RecyclerView.Adapter<ViewHolder>
{
    protected Context mContext;
    protected int mLayoutId;
    protected List<T> mDatas;
    protected LayoutInflater mInflater;

    private OnItemClickListener mOnItemClickListener;

    public void setOnItemClickListener(OnItemClickListener onItemClickListener)
    {
        this.mOnItemClickListener = onItemClickListener;
    }

    public CommonAdapter(Context context, int layoutId, List<T> datas)
    {
        mContext = context;
        mInflater = LayoutInflater.from(context);
        mLayoutId = layoutId;
        mDatas = datas;
    }

    @Override
    public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType)
    {
        ViewHolder viewHolder = ViewHolder.get(mContext, null, parent, mLayoutId, -1);
        setListener(parent, viewHolder, viewType);
        return viewHolder;
    }

    protected int getPosition(RecyclerView.ViewHolder viewHolder)
    {
        return viewHolder.getAdapterPosition();
    }

    protected boolean isEnabled(int viewType)
    {
        return true;
    }


    protected void setListener(final ViewGroup parent, final ViewHolder viewHolder, int viewType)
    {
        if (!isEnabled(viewType)) return;
        viewHolder.getConvertView().setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if (mOnItemClickListener != null)
                {
                    int position = getPosition(viewHolder);
                    mOnItemClickListener.onItemClick(parent, v, mDatas.get(position), position);
                }
            }
        });


        viewHolder.getConvertView().setOnLongClickListener(new View.OnLongClickListener()
        {
            @Override
            public boolean onLongClick(View v)
            {
                if (mOnItemClickListener != null)
                {
                    int position = getPosition(viewHolder);
                    return mOnItemClickListener.onItemLongClick(parent, v, mDatas.get(position), position);
                }
                return false;
            }
        });
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position)
    {
        holder.updatePosition(position);
        convert(holder, mDatas.get(position));
    }

    public abstract void convert(ViewHolder holder, T t);

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

}

對了,別忘了給item添加點擊處理

public interface OnItemClickListener<T> {
    void onItemClick(ViewGroup parent, View view, T t, int position);
    boolean onItemLongClick(ViewGroup parent, View view, T t, int position);
}
  • RecyclerView的使用

初始化組件

mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
//創建默認的線性LayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//如果可以確定每個item的高度是固定的,設置這個選項可以提高性能
mRecyclerView.setHasFixedSize(true);
//設置分割線
mRecyclerView..addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));

分割線

public class DividerItemDecoration extends RecyclerView.ItemDecoration{
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
    private Drawable mDivider;
    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation){
        if(orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST){
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        if(mOrientation == VERTICAL_LIST){
            drawVertical(c, parent);
        }else{
            drawHorizontal(c, parent);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent){
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for(int i = 0; i < childCount; i++){
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)child.getLayoutParams();
            final int left = child.getRight() - params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left,top,right,bottom);
            mDivider.draw(c);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent)
    {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++)
        {
            final View child = parent.getChildAt(i);
            RecyclerView v = new RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if(mOrientation == VERTICAL_LIST){
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        }else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

設置adapter,這裏的String可根據你項目要求換成你所需的Bean都行

mRecyclerView.setAdapter(new CommonAdapter<String>(this, R.layout.item_list, mDatas)
{
    @Override
    public void convert(ViewHolder holder, String s)
    {
        holder.setText(R.id.id_item_list_title, s);
    }
});

以上就是RecyclerView的簡便使用了,如果要在一個頁面再新建一個RecyclerView,只需要在activity或fragment中直接setAdapter()調用通用適配器,這樣可以簡便很多,那麼有了上面的代碼後,你知道怎麼添加多選功能嗎?如不清楚,再聽我慢慢道來:

  1. 首先在ViewHolder中添加選中的實現方式,這裏以點擊某view實現,供實現adapter時調用
/**
* 選擇item
* 實現多選
*/
  public ViewHolder setSelectListener(int viewId,
                                View.OnClickListener listener)
{
    View view = getView(viewId);
    view.setOnClickListener(listener);
    return this;
}
  1. 在CommonAdapter類中添加幾個方法,以供調用者切換選中效果或者清除選中效果等。。
private SparseBooleanArray selectedItems;//記錄選中的position

/**
 * 判讀是否選中
 */
public boolean isSelected(int position){
    return getSelectedItems().contains(position);
}

/**
 * 切換選中或取消選中
 */
public void switchSelectedState(int position){
    if(selectedItems.get(position, false)){
        selectedItems.delete(position);
    }else{
        selectedItems.put(position,true);
    }
    notifyItemChanged(position);
}

/**
 * 清除所有選中item的標記
 */
public void clearSelectedState(){
    List<Integer> selection = getSelectedItems();
    selectedItems.clear();
    for(Integer i : selection){
        notifyItemChanged(i);
    }
}

/**
 * 全選
 */
public void selectAllItems(){
    clearSelectedState();
    for(int i = 0; i < getItemCount(); i++){
        selectedItems.put(i,true);
        notifyItemChanged(i);
    }
}

/**
 * 獲取item數目
 */
public int getSelectedItemCount(){
    return selectedItems.size();
}

/**
 * 獲取選中的items
 */
public List<Integer> getSelectedItems(){
    List<Integer> items = new ArrayList<>(selectedItems.size());
    for(int i = 0; i < selectedItems.size(); i++){
        items.add(selectedItems.keyAt(i));
    }
    return items;
}

最後在setAdapter時實現你多選的效果

//設置選中狀態
if(omsAdapter.isSelected(holder.getItemPosition())) {
                    holder.setImageResource(R.id.img_isSelect, R.drawable.choiced_ic);
                }else{
                    holder.setImageResource(R.id.img_isSelect, R.drawable.no_choice_ic);
                }

//設置選中事件
holder.setSelectListener(R.id.img_isSelect, new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        omsAdapter.switchSelectedState(holder.getItemPosition());//切換選中
                    }
                });

以上就是本次博客的所有內容了,有誤請各位客官指出,在下會繼續虛心學習,雖然本人有點懶,但是隻要有簡便方法實現所需功能又不失性能,則會選擇去重構。

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