RecyclerView之ViewHolder封裝實現點擊、長按、headerView和多選功能

多選效果圖:

這裏寫圖片描述

BaseRecyclerViewHolder類:

package com.danxx.brisktvlauncher.adapter;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Base RecyclerViewHolder
 * Created by Danxingxi on 2016/3/31.
 */
public abstract class BaseRecyclerViewHolder extends RecyclerView.ViewHolder {

    public BaseRecyclerViewHolder(View itemView) {
        super(itemView);
    }

    protected abstract View getView();

    /**
     * 爲item添加動畫
     * @param view 需要添加動畫的item
     * @param scale 是否得到焦點
     */
    public void animItem(View view,boolean scale){
        float toValue = 1.0f;
        if(scale) {  //得到焦點
            toValue = 1.1f;
            ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, "scaleX", toValue);
            ObjectAnimator animatorY = ObjectAnimator.ofFloat(view, "scaleY", toValue);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setDuration(300);
            animatorSet.playTogether(animatorX, animatorY);
            animatorSet.start();
        }else{   //失去焦點
            ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, "scaleX", toValue);
            ObjectAnimator animatorY = ObjectAnimator.ofFloat(view, "scaleY", toValue);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setDuration(300);
            animatorSet.playTogether(animatorX, animatorY);
            animatorSet.start();
        }
    }
}

BaseRecyclerViewAdapter類:

package com.danxx.brisktvlauncher.adapter;

import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Danxingxi on 2016/3/31.
 */
public abstract class BaseRecyclerViewAdapter< T > extends RecyclerView.Adapter<BaseRecyclerViewHolder>{
    /**header view type**/
    public static final int TYPE_HEADER = 0;
    /**item view type**/
    public static final int TYPE_NORMAL = 1;
    private View mHeaderView;
    public OnItemClickListener<T> mOnItemClickListener;
    /**保存處於選中狀態的itemView的position**/
    private SparseBooleanArray selectedItems;
//    private List<Model> mData = new ArrayList<Model>();
//
//    public void setData(List<? extends Model> data){
//        mData.clear();
//        mData.addAll(data);
//    }
    public BaseRecyclerViewAdapter(){
        selectedItems = new SparseBooleanArray();
    }
    private List< T > mData = new ArrayList< T >();

    public void setData(List< T > data){
        mData.clear();
        mData.addAll(data);
    }


    public T getItemData(int position) {
        T res = null;
        /**計算正確的位置**/
        int realPos  = (mHeaderView == null ? position : position - 1);
        if(realPos < mData.size()) {
            res = mData.get(realPos);
        }

        return res;
    }

    public void clearData(){
        if(mData != null){
            mData.clear();
        }
    }

    public void setOnItemClickListener(OnItemClickListener li) {
        mOnItemClickListener = li;
    }

    /**
     * add header view
     * @param headerView
     */
    public void setHeaderView(View headerView) {
        mHeaderView = headerView;
        notifyItemInserted(0);
    }

    /**
     *  get header view
     * @return
     */
    public View getHeaderView() {
        return mHeaderView;
    }

    @Override
    public int getItemViewType(int position) {
        if(mHeaderView == null) return TYPE_NORMAL;
        if(position == 0) return TYPE_HEADER;
        return TYPE_NORMAL;
    }

    /**
     * itemView的選中狀態和非選中狀態切換並及時更新UI狀態
     * 選中狀態調用時就切換爲非選中狀態,反之對調狀態
     * @param position 用戶點擊的itemView的位置
     */
    public void toggleSelection(int position) {
        if (selectedItems.get(position, false)) {
            selectedItems.delete(position);
        } else {
            selectedItems.put(position, true);
        }
        /*這個更新UI會使焦點閃爍一下*/
//        notifyItemChanged(position);
    }

    /**
     * 判斷這個位置的item是處於選中狀態
     * @param position Position of the item to check
     * @return true if the item is selected, false otherwise
     */
    public boolean isSelected(int position) {
        return getSelectedItems().contains(position);
    }


    /**
     * 清除所有Item的選中狀態
     */
    public void clearSelection() {
        List<Integer> selection = getSelectedItems();
        selectedItems.clear();
        notifyDataSetChanged();
//        for (Integer i : selection) {
//            notifyItemChanged(i);
//        }
    }

    /**
     * 獲得所有選中狀態item的position集合
     * @return
     */
    public List<Integer> getSelectedItems() {
        List<Integer> items = new ArrayList<> (selectedItems.size());
        for (int i = 0; i < selectedItems.size(); ++i) {
            /*我們使用keyAt可以取到position,當然也可以使用valueAt取到value值,顯然這個集合中的value都爲true*/
            items.add(selectedItems.keyAt(i));
        }
        return items;
    }
    /**
     * 獲得item的位置
     * @param holder
     * @return
     */
    public int getRealPosition(BaseRecyclerViewHolder holder) {
        int position = holder.getLayoutPosition();
        return mHeaderView == null ? position : position - 1;
    }

    @Override
    public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(mHeaderView != null && viewType == TYPE_HEADER) return new HeaderViewHolder(mHeaderView);
        return createItem(parent ,viewType);
    }

    @Override
    public void onBindViewHolder(final BaseRecyclerViewHolder holder, int position) {
        /**如果是header view就直接返回,不需要綁定數據**/
        if(getItemViewType(position) == TYPE_HEADER) return;
        final int pos = getRealPosition(holder);
        final T data = mData.get(pos);
        bindData(holder ,pos);

        if(mOnItemClickListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClickListener.onItemClick(pos, data);
                }
            });
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    mOnItemClickListener.onItemLongClick(pos, data);
                    return false;
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return mHeaderView == null ? mData.size() : mData.size() + 1;
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);

        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return getItemViewType(position) == TYPE_HEADER
                            ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }

    @Override
    public void onViewAttachedToWindow(BaseRecyclerViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
        if(lp != null
                && lp instanceof StaggeredGridLayoutManager.LayoutParams
                && holder.getLayoutPosition() == 0) {
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
            p.setFullSpan(true);
        }
    }

    /**
     * 創建item view
     * @param parent
     * @param viewType
     * @return
     */
    protected  abstract BaseRecyclerViewHolder createItem(ViewGroup parent, int viewType);

    /**
     * 綁定數據
     * @param holder
     * @param position
     */
    protected abstract void bindData(BaseRecyclerViewHolder holder, int position);

    /**
     *header view ViewHolder
     */
    class HeaderViewHolder extends BaseRecyclerViewHolder {

        public HeaderViewHolder(View itemView) {
            super(itemView);
        }

        @Override
        protected View getView() {
            return null;
        }
    }

    /**
     * item 點擊事件接口
     * @param <T>
     */
    public interface OnItemClickListener<T> {
        /**單擊監聽**/
        void onItemClick(int position, T data);
        /**長按監聽**/
        void onItemLongClick(int position, T data);
    }
}

用法請參考:https://github.com/Dawish/BriskTVLauncher/blob/master/app/src/main/java/com/danxx/brisktvlauncher/ui/ActivityManagerApp.java

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