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


当前回答

我知道有很多答案,但我想我也可以提供我的实现。(完整的细节可以在我回答的另一个问题中找到)。

所以,要添加一个点击监听器,你的内部ViewHolder类需要实现View.OnClickListener。这是因为你将设置一个OnClickListener到ViewHolder的构造函数的itemView参数。让我来告诉你我的意思:

public class ExampleClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView text1, text2;

    ExampleClickViewHolder(View itemView) {
        super(itemView);

        // we do this because we want to check when an item has been clicked:
        itemView.setOnClickListener(this);

        // now, like before, we assign our View variables
        title = (TextView) itemView.findViewById(R.id.text1);
        subtitle = (TextView) itemView.findViewById(R.id.text2);
    }

    @Override
    public void onClick(View v) {
        // The user may not set a click listener for list items, in which case our listener
        // will be null, so we need to check for this
        if (mOnEntryClickListener != null) {
            mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
        }
    }
}

唯一需要添加的其他东西是适配器的自定义接口和setter方法:

private OnEntryClickListener mOnEntryClickListener;

public interface OnEntryClickListener {
    void onEntryClick(View view, int position);
}

public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
    mOnEntryClickListener = onEntryClickListener;
}

这样,新的支持单击的适配器就完成了。

现在,让我们用它…

    ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
    clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
        @Override
        public void onEntryClick(View view, int position) {
            // stuff that will happen when a list item is clicked
        }
    });

这基本上就是设置普通适配器的方法,除了使用您创建的setter方法来控制当用户单击特定列表项时要做什么。

你也可以看看我在GitHub上做的一组关于Gist的例子:

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07

其他回答

有更简单的方法。只需要在根视图上应用onBindViewHolder中的click。

考虑这是你对适配器的看法,

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linearlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

        <TextView
            android:id="@+id/textview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="1dp"
            android:textSize="15sp" />
</LinearLayout>

然后在适配器中执行以下操作

//get the layout and make view holder
@Override
public RVAdapter.ViewHolder1 onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout, null);
    ViewHolder1 viewHolder = new ViewHolder1(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(RVAdapter.ViewHolder1 holder, int position) {

    //apply on click on your root view
    holder.linearlayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Do on click stuff
        }
    });
}

//make references to views in layout including root view
public class ViewHolder1 extends RecyclerView.ViewHolder {

    protected LinearLayout linearlayout = null
    protected TextView textview = null;

    public CareerLinksViewHolder(View itemView) {
        super(itemView);

        this.linearlayout = (LinearLayout) itemView.findViewById(R.id.linearlayout);
        this.tvCompName = (TextView) itemView.findViewById(R.id.textview);
    }
}

在ViewHolder中设置点击监听器,如下所示:

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView title, year, genre;

    public MyViewHolder(View view) {
        super(view);

        title = (TextView) view.findViewById(R.id.title);
        genre = (TextView) view.findViewById(R.id.genre);
        year = (TextView) view.findViewById(R.id.year);

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, ""+getAdapterPosition(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

我的方式

活动课上:

    public class MyActivity extends AppCompatActivity implements EmployeeAdapter.ClickListener {
    ...
    @Override
    public void onClick(int position) { ... }
    ...
    }

适配器类:

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    ...
    @Override
    public void onBindViewHolder(){
         holder.textView1.setOnClickListener(v -> clickListener.onClick(position));
    }
    ...
    public interface ClickListener {
        void onClick(int position);
    }
    ...
    }

别白费力气了!这个特定用例的代码包含在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.

让我们看看如何在Jetpack / AndroidX中实现这一点

你需要像这样在viewmodel类中创建一个观察对象

private MutableLiveData<Integer> adapterItem = new MutableLiveData<>();

public MutableLiveData<Integer> getAdapterItem() {
    return adapterItem;
}

public void setAdapterItem(int adapterItem) {
    this.getAdapterItem().setValue(adapterItem);
}

然后在适配器类中,确保将viewmodel引用作为构造函数的参数传递,然后在vieholder上实现clicklistener

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        if(itemView != null){
            itemView.setOnClickListener(v -> {
                int adapterPosition = getAdapterPosition();
                viewModel.setAdapterItem(adapterPosition);
            });

        };
    }

然后从活动课上观察变化

    viewModel.getAdapterItem().observe(this, position -> {
        Log.w(TAG, "clicked: " + ridesArray.get(position));
    });