有人使用RecyclerView找到了一种方法来设置一个onClickListener的项目在RecyclerView? 我想设置一个监听器为每个项目的布局,但这似乎有点太麻烦了 我确信有一种方法让RecyclerView监听onClick事件,但我不能完全弄清楚。


当前回答

我有一个很好的解决方案RecyclerView的onItemClickListener的项目和子项

步骤1—创建接口

public interface OnRecyclerViewItemClickListener
{
    /**
     * Called when any item with in recyclerview or any item with in item
     * clicked
     * 
     * @param position
     *            The position of the item
     * @param id
     *            The id of the view which is clicked with in the item or
     *            -1 if the item itself clicked
     */
    public void onRecyclerViewItemClicked(int position, int id);
}

步骤2-然后在适配器的onBindViewHolder方法中使用它,如下所示

/**
     * Custom created method for Setting the item click listener for the items and items with in items
     * @param listener OnRecyclerViewItemClickListener 
     */
    public void setOnItemClickListener(OnRecyclerViewItemClickListener listener)
    {
        this.listener = listener;
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position)
    {
    
        // viewHolder.albumBg.setBackgroundResource(_itemData[position]
        // .getImageUrl());
    
        viewHolder.albumName.setText(arrayList.get(position).getName());
        viewHolder.artistName.setText(arrayList.get(position).getArtistName());
        String imgUrl = arrayList.get(position).getThumbImageUrl();
    
        makeImageRequest(imgUrl, viewHolder);
        viewHolder.parentView.setOnClickListener(new View.OnClickListener()
        {
    
            @Override
            public void onClick(View v)
            {
                listener.onRecyclerViewItemClicked(position, -1);
            }
        });
        viewHolder.settingButton.setOnClickListener(new View.OnClickListener()
        {
    
            @Override
            public void onClick(View v)
            {
                listener.onRecyclerViewItemClicked(position, v.getId());
            }
        });
    
    }
    
    // class to hold a reference to each item of RecyclerView
    public static class ViewHolder extends RecyclerView.ViewHolder
    {
    
        public TextView albumName, artistName;
        public ImageView albumIcon, settingButton;
        public LinearLayout parentView;
    
        public ViewHolder(View itemLayoutView)
        {
            super(itemLayoutView);
            // albumBg = (LinearLayout) itemLayoutView
            // .findViewById(R.id.albumDlbg);
            albumName = (TextView) itemLayoutView.findViewById(R.id.albumName);
            artistName = (TextView) itemLayoutView
                    .findViewById(R.id.artistName);
            albumIcon = (ImageView) itemLayoutView.findViewById(R.id.albumIcon);
            parentView = (LinearLayout) itemLayoutView
                    .findViewById(R.id.albumDlbg);
            settingButton = (ImageView) itemLayoutView
                    .findViewById(R.id.settingBtn);
        }
    
    }

步骤3-在活动或片段中找到并设置回收器视图,您正在使用此

recyclerView = (RecyclerView) rootview.findViewById(R.id.vmtopsongs);

        lm = new LinearLayoutManager(mActivity);
        lm.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(lm);
        recyclerView.addItemDecoration(
                new HorizontalDividerItemDecoration.Builder(getActivity())
                        .paint(Utils.getPaint()).build());
        PopularSongsadapter mAdapter = new PopularSongsadapter(gallery,
                mActivity, true);
        // set adapter
        recyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(this);
        // set item animator to DefaultAnimator
        recyclerView.setItemAnimator(new DefaultItemAnimator());

步骤4-最后在使用recyclerview的activity或fragment中实现接口

@Override
    public void onRecyclerViewItemClicked(int position, int id)
    {
        if(id==-1){
            Toast.makeText(mActivity, "complete item clicked", Toast.LENGTH_LONG).show();
        }else{
            Toast.makeText(mActivity, "setting button clicked", Toast.LENGTH_LONG).show();
        }
    }

更新Kotlin语言 我已经更新了kotlin的代码,其中只有整个视图有点击监听器。你可以根据上面的java代码编辑界面和代码来设置子项点击监听器。

适配器

class RecentPostsAdapter(private val list: MutableList<Post>) :
    RecyclerView.Adapter<RecentPostsAdapter.ViewHolder>() {
    private lateinit var onItemClickListener: OnItemClickListener

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context)
                .inflate(R.layout.listitem_recent_post, parent, false)
        )
    }

    override fun getItemCount(): Int {
        return list.size
    }

    fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
        this.onItemClickListener = onItemClickListener
    }

    private fun getItem(position: Int): Post {
        return list[position]
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(getItem(position))
        holder.itemView.setOnClickListener(View.OnClickListener {
            onItemClickListener.onItemClick(
                position
            )
        })
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private var imageView: NetworkImageView? = null
        private var tvTitle: TextView? = null
        private var tvExcerpt: TextView? = null
        private var htmlSpanner: HtmlSpanner = HtmlSpanner()

        init {
            imageView = itemView.findViewById(R.id.niv_post_image)
            tvTitle = itemView.findViewById(R.id.tv_post_title)
            tvExcerpt = itemView.findViewById(R.id.tv_post_excerpt)
        }

        fun bind(post: Post) {
            tvTitle?.text = post.title
            tvExcerpt?.text = htmlSpanner.fromHtml(post.excerpt)
        }
    }

    interface OnItemClickListener {
        fun onItemClick(position: Int)
    }
}

活动或片段

recyclerView = view.findViewById(R.id.rvHomeRecentPosts)
        recyclerView.layoutManager = LinearLayoutManager(view.context)
        list = mutableListOf()
        recentPostsAdapter = RecentPostsAdapter(list)
        recyclerView.adapter = recentPostsAdapter
        recentPostsAdapter.setOnItemClickListener(object:RecentPostsAdapter.OnItemClickListener{
            override fun onItemClick(position: Int) {
                (activity as MainActivity).findNavController(R.id.nav_host_fragment).navigate(R.id.action_nav_home_to_nav_post_detail)
            }

        })

其他回答

对我来说,这是最好的方法:

class YourRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> implements View.OnClickListener { 
  ...
  @Override
  public void onClick(View view) {
        int itemPosition = vRecycle.getChildPosition(view);
        //And use itemPosition to get the item from your collection. This way you dont restrain the ViewHolder with a OnClick callback
    }
  ...
}

由于API已经发生了根本性的变化,如果你要为每个项目创建一个OnClickListener,这不会让我感到惊讶。不过也没那么麻烦。在你的RecyclerView的实现中。适配器<MyViewHolder>,你应该有:

private final OnClickListener mOnClickListener = new MyOnClickListener();

@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false);
    view.setOnClickListener(mOnClickListener);
    return new MyViewHolder(view);
}

onClick方法:

@Override
public void onClick(final View view) {
    int itemPosition = mRecyclerView.getChildLayoutPosition(view);
    String item = mList.get(itemPosition);
    Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();
}

别白费力气了!这个特定用例的代码包含在Android Studio附带的Master/Detail Flow启动器项目中。

从Android Studio选择:

文件>新建>新建项目.... 在Phone and Tablet选项卡中选择如下所示的Master/Detail Flow。

用Kotlin或Java创建项目。 利润。

我不会在这里包括谷歌的ootb演示项目的代码,但我会概述谷歌提供的示例中的主要设计方法:

the item OnClickListener is created ONLY ONCE, and is assigned to a field in your RecyclerView.Adapter implementation. in the onBindViewHolder() you should set the same, pre-created onClickListener object on your ViewHolder instance with holder.itemView.setOnClickListener(mOnClickListener) (AVOID creating a new instance on every method call!); if you need to capture clicks on some specific elements inside the ViewHolder then extend ViewHolder and expose the elements you need as fields so that you can attach whatever listeners you need in onBindViewHolder() — and once again, do NOT re-create the listeners on every method call — initialise them as instance fields and attach them as needed. you can use .setTag() in order to pass state to your viewHolder, e.g. holder.itemView.setTag(mValues.get(position)); as used in the demo.

我们可以使用Java弱引用来实现这一点。 从语义上讲,视图持有者应该响应click事件或将其委托给正确的响应器。

我们的目标:

Viewholder应该对响应事件的类一无所知,除非它实现了某个接口。 点击处理程序应该得到被点击的视图在RecyclerView中的位置。 我们应该能够辨别视图持有人中单击了哪个视图。 保持所有组件之间的松散耦合,不要造成任何保留周期。

步骤:

Create an interface to handle click responses. Implement this interface in the Activity that will handle the click. Add a member variable in the RecyclerView Adapter to hold the Weak Reference and a constructor that sets it. Do the same in the RecyclerView ViewHolder and add a member variable to keep track of position. Set your on click listeners on any view you'd like in the ViewHolder, then callback to the responder to handle them. Change your onBindViewHolder method to set the position when binding. Pass the responder down to the ViewHolder. In the responder, you can now use getId() on the view to figure out which view was clicked.

这里是一个要点,这样你就可以看到它们是如何组合在一起的: RecyclerView点击处理

我已经为android开发了一个轻量级的库,你可以访问github并遵循这个示例:

RecycleClick.addTo(YOUR_RECYCLE_VIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() {
    @Override
    public void onItemClicked(RecyclerView recyclerView, int position, View v) {
        // Your code here
    }
});