为RecyclerView添加点击事件、长按事件

本篇展示手机内已安装的软件信息,并添加事件,效果如下
这里写图片描述

一、准备工作

  1. 保存App信息的bean

    public class AppInfo {
    
        public String name;         // 应用名
        public String packageName;  // 应用包名
        public Drawable icon;       // 应用图标
    
        public boolean isRom;       // 应用的安装位置
        public boolean isUser;      // 系统还是用户应用
    }
    
  2. 获取手机所有App的信息
    可以了解获取系统信息的相关API

    public class AppInfoProvider {
    
        /**
         * 获取已安装应用
         */
        public static ArrayList<AppInfo> getIntalledApps(Context ctx) {
            PackageManager pm = ctx.getPackageManager();
            List<PackageInfo> installedPackages = pm.getInstalledPackages(0);   // 获取所有已安装的包
    
            ArrayList<AppInfo> list = new ArrayList<AppInfo>();
            for (PackageInfo packageInfo : installedPackages) {
                AppInfo info = new AppInfo();
                String packageName = packageInfo.packageName;
                ApplicationInfo applicationInfo = packageInfo.applicationInfo;  // 应用信息
                String name = applicationInfo.loadLabel(pm).toString();
                Drawable icon = applicationInfo.loadIcon(pm);
    
                int uid = applicationInfo.uid;  // 当前应用的标识
    
                info.packageName = packageName;
                info.name = name + uid;
                info.icon = icon;
    
                // 状态机, 通过0/1状态来表示是否具备某些属性和功能
                int flags = applicationInfo.flags;  // 获取应用标记
                if ((flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == ApplicationInfo.FLAG_EXTERNAL_STORAGE) {
                    // 安装在sd
                    info.isRom = false;
                } else {
                    // 安装在手机内存
                    info.isRom = true;
                }
    
                if ((flags & ApplicationInfo.FLAG_SYSTEM) == ApplicationInfo.FLAG_SYSTEM) {
                    // 系统应用
                    info.isUser = false;
                } else {
                    // 用户应用
                    info.isUser = true;
                }
    
                list.add(info);
            }
    
            return list;
        }
    }
    
  3. activity_main

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        
        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </LinearLayout>
    
  4. 展示App信息的条目布局

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:padding="5dp">
    
        <ImageView
            android:id="@+id/iv_icon"
            android:layout_width="45dp"
            android:layout_height="45dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:src="@mipmap/ic_launcher"/>
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="2dp"
            android:layout_toRightOf="@+id/iv_icon"
            android:singleLine="true"
            android:text="名称"
            android:textColor="#000"
            android:textSize="18sp"/>
    
        <TextView
            android:id="@+id/tv_location"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/iv_icon"
            android:layout_alignLeft="@+id/tv_name"
            android:layout_marginTop="3dp"
            android:text="手机内存"
            android:textColor="#000"
            android:textSize="16sp"/>
    
    </RelativeLayout>
    
  5. 头布局

    <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_head"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#9e9e9e"
            android:padding="5dp"
            android:text="用户应用(0)"
            android:textColor="#fff"
            android:textSize="16sp"/>
    
    </LinearLayout>
    

二、适配器(★)

事件的添加需要我们手动进行,分别添加点击和长按接口,接口中添加抽象方法,参数为当前布局对象和点击的条目的位置,然后绑定到当前实现的View.OnClickListener接口的onClick()方法中,具体过程请看本篇最后第四章

public class AppAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements View.OnClickListener, View.OnLongClickListener {

    public static final int TYPE_HEAD = 0;
    public static final int TYPE_APPS = 1;
    
    // 这里数据源有两个(系统应用列表和用户应用列表)
    private ArrayList<AppInfo> mUserList;   // 所有已安装用户应用的集合
    private ArrayList<AppInfo> mSystemList; // 所有已安装系统应用的集合
    
    public AppAdapter(ArrayList<AppInfo> userList, ArrayList<AppInfo> systemList) {
        mUserList = userList;
        mSystemList = systemList;
    }

    @Override public int getItemViewType(int position) {
        if (position == 0 || position == mUserList.size() + 1) {
            return TYPE_HEAD;
        } else {
            return TYPE_APPS;
        }
    }

    @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = null;
        RecyclerView.ViewHolder holder = null;

        switch (viewType) {
            case TYPE_HEAD:
                view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_header, null);
                holder = new HeadHolder(view);
                break;

            case TYPE_APPS:
                view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_appinfo, null);

                /**
                 * 为展示应用信息的布局添加点击和长按事件监听
                 */
                view.setOnClickListener(this);
                view.setOnLongClickListener(this);

                holder = new AppsHolder(view);
                break;
        }
        
        return holder;
    }

    @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (getItemViewType(position)) {
            case TYPE_HEAD:
                if (0 == position) {
                    ((HeadHolder) holder).tvHead.setText("用户应用(" +mUserList.size() + ")");
                } else {
                    ((HeadHolder) holder).tvHead.setText("系统应用(" + mSystemList.size() + ")");
                }

                break;

            case TYPE_APPS:
                AppInfo info;
                if (position < mUserList.size() + 1) {
                    info = mUserList.get(position - 1);                         // 从用户应用列表中获取应用信息
                } else {
                    info = mSystemList.get(position - mUserList.size() - 2);    // 从系统应用列表中获取应用信息
                }

                // 设置控件内容
                ((AppsHolder) holder).tvName.setText(info.name);
                ((AppsHolder) holder).ivIcon.setImageDrawable(info.icon);

                if (info.isRom) {

                    ((AppsHolder) holder).tvLocation.setText("内置存储卡");
                } else {
                    ((AppsHolder) holder).tvLocation.setText("外部存储卡");
                }

                /**
                 * 将position保存在itemView的Tag中以便点击时获取
                 */
                holder.itemView.setTag(position); 
                break;
        }
    }

    @Override public int getItemCount() {
        return mUserList.size() + mSystemList.size() + 2; // 加上两条头布局条目
    }
    

    /****************************************
     * Holder
     */
    class HeadHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.tv_head) TextView tvHead;

        public HeadHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    class AppsHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.tv_name) TextView tvName;
        @BindView(R.id.iv_icon) ImageView ivIcon;
        @BindView(R.id.tv_location) TextView tvLocation;

        public AppsHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }


    /****************************************
     * Listener
     */
    /**
     * 手动添加点击事件
     */
    interface OnClickListener {
        void onClick(View view, int position);
    }
    
    private OnClickListener mOnClickListener = null;
    
    public void setOnClickListener(OnClickListener listener) {
        mOnClickListener = listener;
    }
    
    @Override public void onClick(View view) {
        if (null != mOnClickListener) {
            mOnClickListener.onClick(view, (int) view.getTag());
        }
    }
    
    /**
     * 手动添加长按事件
     */
    interface OnLongClickListener {
        void onLongClick(View view, int position);
    }
    private OnLongClickListener mOnLongClickListener = null;
    public void setOnLongClickListener(OnLongClickListener listener) {
        mOnLongClickListener = listener;
    }
    @Override public boolean onLongClick(View view) {
        if (null != mOnLongClickListener) {
            mOnLongClickListener.onLongClick(view, (int) view.getTag());
        }

        // 消耗事件,否则长按逻辑执行完成后还会进入点击事件的逻辑处理
        return true;    
    }
}

三、Activity中使用

重点看setAdapter之后的点击和长按事件的具体处理逻辑即可

public class AppsActivity extends AppCompatActivity {

    @BindView(R.id.rv) RecyclerView rv;
    private AppAdapter mAdapter;

    private LinearLayoutManager mLayoutManager;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_apps);
        ButterKnife.bind(this);

        initData(); // 初始化数据

        rv.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
        rv.setLayoutManager(mLayoutManager);
        rv.setItemAnimator(new DefaultItemAnimator());

        mAdapter = new AppAdapter(mUserList, mSystemList);
        rv.setAdapter(mAdapter);

        /**
         * 点击和长按事件的具体处理
         */
        mAdapter.setOnClickListener(new AppAdapter.OnClickListener() {
            @Override public void onClick(View view, int position) {
                if (position < mUserList.size() + 1) {
                    Toast.makeText(AppsActivity.this, mUserList.get(position - 1).name, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(AppsActivity.this, mSystemList.get(position - mUserList.size() - 2).name, Toast.LENGTH_SHORT).show();
                }
            }
        });
        mAdapter.setOnLongClickListener(new AppAdapter.OnLongClickListener() {
            @Override public void onLongClick(View view, int position) {
                if (position < mUserList.size() + 1) {
                    Toast.makeText(AppsActivity.this, "长按" + mUserList.get(position - 1).name, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(AppsActivity.this, "长按" + mSystemList.get(position - mUserList.size() - 2).name, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    
    private ArrayList<AppInfo> mList;       // 所有已安装应用的集合
    private ArrayList<AppInfo> mUserList;   // 所有已安装用户应用的集合
    private ArrayList<AppInfo> mSystemList; // 所有已安装系统应用的集合

    private void initData() {
        mList = AppInfoProvider.getIntalledApps(getApplicationContext());

        // 区分用户和系统应用,分别放在两个集合中
        mUserList = new ArrayList<AppInfo>();
        mSystemList = new ArrayList<AppInfo>();
        for (AppInfo info : mList) {
            if (info.isUser) {
                mUserList.add(info);
            } else {
                mSystemList.add(info);
            }
        }
    }
}

四、点击事件实现过程

  1. 定义点击事件接口

  2. onCreateViewHolder()中为每个条目添加点击事件

  3. onBindViewHolder()中设置被点击条目的position

  4. View.OnClickListeneronClick()方法中将事件传递给外面的调用者

    这里写图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
如果你想在 RecyclerView 中实现按删除功能,可以按照以下步骤: 1. 在 RecyclerView 的 Item 布局中添加一个删除按钮。 2. 在 RecyclerView 的 Adapter 中实现一个接口 OnItemLongClickListener,用来监听事件。 3. 在接口的方法中处理事件,弹出一个 Dialog 对话框,询问用户是否要删除该项数据。 4. 如果用户确定删除,则在 Adapter 中删除该项数据,并通知 RecyclerView 更新 UI。 下面是一个伪代码示例,仅供参考: ```java public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> { private List<MyData> mDataList; private Context mContext; private OnItemLongClickListener mOnItemLongClickListener; // 构造方法 public MyAdapter(List<MyData> dataList, Context context) { mDataList = dataList; mContext = context; } // 设置按监听器 public void setOnItemLongClickListener(OnItemLongClickListener listener) { mOnItemLongClickListener = listener; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // 创建 ViewHolder View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_layout, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { // 绑定数据 MyData data = mDataList.get(position); holder.mTextView.setText(data.getText()); holder.mDeleteButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 删除该项数据 mDataList.remove(position); notifyItemRemoved(position); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { // 触发事件 if (mOnItemLongClickListener != null) { mOnItemLongClickListener.onItemLongClick(position); } return true; } }); } @Override public int getItemCount() { // 获取数据项数量 return mDataList.size(); } // 定义按监听器接口 public interface OnItemLongClickListener { void onItemLongClick(int position); } } ``` 在 Activity 或 Fragment 中,你可以这样使用: ```java MyAdapter adapter = new MyAdapter(dataList, context); adapter.setOnItemLongClickListener(new MyAdapter.OnItemLongClickListener() { @Override public void onItemLongClick(int position) { // 弹出确认删除的对话框 AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("确认删除") .setMessage("确定要删除该项数据吗?") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 用户点击确定,删除该项数据 dataList.remove(position); adapter.notifyItemRemoved(position); } }) .setNegativeButton("取消", null) .show(); } }); recyclerView.setAdapter(adapter); ``` 上面的代码只是一个示例,具体实现方式可能因项目需求而异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值