单击不在 Fragment 内的 RecyclerView 项目上工作

Posted

技术标签:

【中文标题】单击不在 Fragment 内的 RecyclerView 项目上工作【英文标题】:Click not working on RecyclerView items inside Fragment 【发布时间】:2017-03-29 10:30:45 【问题描述】:

我的应用程序使用以下结构:

Activity > ViewPager > FragmentStatePagerAdapter > Fragment > RecyclerView

过去我一直在相当舒适地使用 RecyclerViews,但由于某种原因,当我的 RecyclerView 项目放置在 Fragment 中时,我无法让我的 RecyclerView 项目注册点击事件。我的 ViewHolder 如下:

// ViewHolder Class for ExhibitAdapter
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener 
        public TextView itemTitleTextView;
        public TextView itemDescriptionTextView;
        public NetworkImageView itemCoverPhoto;

        public ViewHolder(View itemView) 
            super(itemView);
            itemCoverPhoto = (NetworkImageView) itemView.findViewById(R.id.exhibitThumbnailNIV);
            itemTitleTextView = (TextView) itemView.findViewById(R.id.exhibitNameTV);
            itemDescriptionTextView = (TextView) itemView.findViewById(R.id.exhibitDescriptionTV);
            itemView.setOnClickListener(this);
        


        @Override
        public void onClick(View view) 
            try 
                Log.d(TAG, "Exhibit clicked");
                Exhibit currentExhibit = exhibits.get(getAdapterPosition());
                intent.putExtra(ExhibitContentActivity.EXHIBIT_ID , currentExhibit.getId());
                intent.putExtra(ExhibitContentActivity.EXHIBIT_COVER_URL , currentExhibit.getCoverPhotoUrl());

                ActivityOptionsCompat options = ActivityOptionsCompat.
                        makeSceneTransitionAnimation((Activity) adapterContext, itemView.findViewById(R.id.exhibitThumbnailNIV), "profile");

                Log.i(TAG, "Attempting to launch detail activity with exhibit id: " + currentExhibit.getId());

                adapterContext.startActivity(intent, options.toBundle());

            
            catch(IndexOutOfBoundsException e) 
                Log.e(TAG, "* Error: Adapter position exceeded the no. of items.");
            
        

    

任何帮助将不胜感激。我尝试按照https://guides.codepath.com/android/Creating-and-Using-Fragments#fragment-listener 中列出的步骤创建片段交互侦听器,但我不确定如何在 RecyclerView 的适配器中实现它。提前致谢!

【问题讨论】:

你找到解决办法了吗? @MichaelA。是的,问题只是 1. 我的项目布局绘制时间太长了 2. 我正在处理 ViewHolder 类中的 onClick 逻辑。我通过在片段中创建一个侦听器接口来解决它,在 ViewHolder 的 onClick 中调用该侦听器的 onMyItemClick 方法,然后在我的主活动中实现该侦听器。这让我可以定义当一个项目被点击时要做什么,同时有效地将点击事件冒泡到我的主要活动中。 @ShahraizT。您好,您的解决方案是否有示例代码?我有同样的问题,你的解决方案就是我需要的。谢谢。 【参考方案1】:

您应该在 RecyclerView 适配器的 onBindViewHolder 方法中设置 onClickListener,而不是在 ViewHolder 中。问题是 ViewHolders 不是实际的视图(因此您不能单击一个),它们是绑定到视图并允许您将这些视图重用于多个列表项以减少应用程序的内存占用的持有者。

RecyclerView.Adapter 实现

public MyAdapter extends RecyclerView.Adapter<YourViewHolderClass> 
    .
    .
    .
    @Override
    public void onBindViewHolder(final YourViewHolderClass holder, int position) 
        holder.itemView.setOnClickListener (new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                // Do something!
            
        );
        // Do you other view binding operations
    
    .
    .
    .

确保在您的视图持有者本地存储itemView 的副本,以便您可以将 OnClickListener 绑定到列表项的容器。

RecyclerView.ViewHolder 实现

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener 
    public TextView itemTitleTextView;
    public TextView itemDescriptionTextView;
    public NetworkImageView itemCoverPhoto;
    public View itemView;

    public ViewHolder(View itemView) 
        super(itemView);
        this.itemView = itemView;
        itemCoverPhoto = (NetworkImageView) itemView.findViewById(R.id.exhibitThumbnailNIV);
        itemTitleTextView = (TextView) itemView.findViewById(R.id.exhibitNameTV);
        itemDescriptionTextView = (TextView) itemView.findViewById(R.id.exhibitDescriptionTV);
    

我希望这会有所帮助!

-汤姆

【讨论】:

感谢 Tom,但我的 onBindViewHolder 中没有 onClickListener 的原因是因为这会每次都创建一个新的 View.OnClickListener 并且会影响使用 RecyclerView 的性能优势。 ViewHolder 创建一次,因此将 onClickListener 附加到它是标准做法。这样,onBindView 中的数据会根据需要发生变化,我们也可以使用 onClick 功能。问题是,我的点击在片段内时不起作用。所以我猜点击次数需要随着我的活动而冒泡。【参考方案2】:

您的 itemView 内部是否有任何可聚焦的视图?如果是这样,请尝试将android:focusable="false"添加到视图的xml中,它在ListView中有效,但我不确定在RecyclerView中是否如此。

【讨论】:

以上是关于单击不在 Fragment 内的 RecyclerView 项目上工作的主要内容,如果未能解决你的问题,请参考以下文章

从 RecyclerView 单击 CardView 加载片段

单击抽屉的任何项目而不在android中关闭时更改导航抽屉内的视图和内容

ViewPager 内的 Fragment 中的 EditText 焦点上的视图混淆了

通过单击单个项目选择Recycler视图中的所有项目

如何突出显示 Recycler View 的选定项目?

Recycler View 不显示数据