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

在Kotlin中,给RecyclerView的ItemView添加按监听器(setOnLongClickListener)需要配合`RecyclerView.ItemTouchHelper`使用。下面是一个简单的示例,展示如何在Adapter中实现: 首先,你需要在Adapter类里创建一个ViewHolder,并设置按监听器: ```kotlin class YourAdapter(private val data: List<Data>) : RecyclerView.Adapter<YourAdapter.ViewHolder>() { inner class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) { val itemView: View = itemView.findViewById(R.id.your_item_view_id) // 按监听器 init { itemView.setOnLongClickListener { view -> // 当按时触发的操作 performLongPressAction(view) true // 返回true表示处理了这个事件,RecyclerView就不会再继续传递下去 } } // 实现你的long press action private fun performLongPressAction(view: View) { // 这里你可以执行具体的按操作,比如弹出提示框、删除元素等 Toast.makeText(context, "按了!", Toast.LENGTH_SHORT).show() } } // ...其他Adapter的方法... } ``` 在这个例子中,当你按`your_item_view_id`时,会调用`performLongPressAction`方法,并显示一个Toast提示。 注意,在实际应用中,你还需要配置`ItemTouchHelper`来启用按手势,并关联到你的Adapter: ```kotlin val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.itemAnimator.enabled = false // 关闭动画以便于按 // 创建 ItemTouchHelper 实例 val touchHelper = ItemTouchHelper( ItemTouchHelper.SimpleCallback( ItemTouchHelper.START | ItemTouchHelper.END, YourAdapterItemType.DragOrMove // 设置允许拖动或仅移动 ) { adapter, view, motion, dragFlags -> val viewHolder = adapter.getItemViewHolder(view) if (viewHolder is YourAdapter.ViewHolder) { viewHolder.performLongPressAction(view) } }, yourAdapter ) touchHelper.attachToRecyclerView(recyclerView) ``` 这里假设`YourAdapterItemType`是你自定义的数据类型,用于区分哪些类型的项可以按。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值