【问题标题】:RecyclerView with multiple onclick events on textviewsRecyclerView 在文本视图上有多个 onclick 事件
【发布时间】:2018-01-22 17:12:50
【问题描述】:

我想构建一个 RecyclerView,每行内有几列应该可以点击不同的事件。不幸的是,我无法确定在该行中单击了哪个 onclick,因为它们都调用相同的方法。处理这个问题的最佳方法是什么?我应该在行内声明多个视图并为每个视图分配一个 onclick 吗?

这是我的 recyclerview.xml 文件:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="Description"
            android:id="@+id/description_textview"
            android:layout_width="180dp"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@color/colorBlack"
            android:paddingLeft="4dp"
            />

        <TextView
            android:text="99"
            android:id="@+id/qty_textview"
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@color/colorBlack"
            android:layout_toRightOf="@id/description_textview"
            android:gravity="center"
            />

        <TextView
            android:text="N"
            android:id="@+id/accept_textview"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textStyle="bold"
            android:textColor="@color/colorBlack"
            android:layout_toRightOf="@id/qty_textview"
            android:gravity="center"
            />

    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/colorBackgroundGray"
        android:layout_below="@id/layout"
        style="?android:listSeparatorTextViewStyle"
        />

</RelativeLayout>

这是我的 recyclerview 持有者代码(普通 recyclerview)。我想用不同的列替换 onLongClick 事件:

private class RecyclerHolder2 extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
    private TextView descriptionTextView;
    private TextView qtyTextView;
    private TextView acceptTextView;
    private VerificationModel verificationModel;

    public RecyclerHolder2(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
        descriptionTextView = (TextView) itemView.findViewById(R.id.description_textview);
        qtyTextView = (TextView) itemView.findViewById(R.id.qty_textview);
        acceptTextView = (TextView) itemView.findViewById(R.id.accept_textview);
    }

    public void bindRecyclerData(VerificationModel newItem) {
        verificationModel = newItem;
        descriptionTextView.setText(verificationModel.getDescription());
        qtyTextView.setText(verificationModel.getQty());
        acceptTextView.setText(verificationModel.getAccept());
    }

    @Override
    public void onClick(View v) {
        boolean accepted = true;
        for (int i = 0; i < mVerifys.size(); i++) {
            if (mVerifys.get(i).equals(verificationModel)) {
                if (mVerifys.get(i).getAccept().equals("N")) {
                    mVerifys.get(i).setAccept("Y");
                    mVerifys.get(i).setSelected(true);
                    Timber.d(verificationModel.getDescription() + " was accepted");
                } else {
                    mVerifys.get(i).setAccept("N");
                    mVerifys.get(i).setSelected(false);
                    Timber.d(verificationModel.getDescription() + " was unaccepted");
                }
            }
            if (mVerifys.get(i).getAccept().equals("N")) {
                accepted = false;
            }
        }
        mRecyclerAdapter2.notifyDataSetChanged();
        if (accepted) {
            mAcceptedButton.setEnabled(true);
        }

    }

    @Override
    public boolean onLongClick (View v) {
        Timber.d(verificationModel.getDescription() + " will be adjusted");
        Intent intent = new Intent(VerificationDetailActivity.this, InvoiceAuthorizationActivity.class);
        startActivity(intent);
        return true;
    }
}

【问题讨论】:

标签: android onclick android-recyclerview


【解决方案1】:

现在,您正在像这样设置您的听众:

    itemView.setOnClickListener(this);
    itemView.setOnLongClickListener(this);

有两种不同的方法可以实现您的目标。

首先是对每个视图使用相同的View.OnClickListener,然后根据点击的视图的ID改变你所做的。

public RecyclerHolder2(View itemView) {
    super(itemView);
    ...
    descriptionTextView.setOnClickListener(this);
    descriptionTextView.setOnLongClickListener(this);
    qtyTextView.setOnClickListener(this);
    qtyTextView.setOnLongClickListener(this);
    acceptTextView.setOnClickListener(this);
    acceptTextView.setOnLongClickListener(this);
    ...
}

@Override
public void onClick(View v) {
    if (v.getId() == R.id.description_textview) {
        ...
    }
    else if (...) {
        ...
    }
}

第二个(也是我推荐的)是为每个视图使用不同的View.OnClickListener()。这将导致您编写更多代码,但更明显的是不同的点击会做不同的事情。 (如果您使用的是 RetroLambda,您最终可以省略大部分样板文件)。

private View.OnClickListener descriptionListener = new View.OnClickListener() {

    @Override
    public void onClick(View view) {
        ...
    }
};

private View.OnClickListener quantityListener = new View.OnClickListener() {

    @Override
    public void onClick(View view) {
        ...
    }
};

public RecyclerHolder2(View itemView) {
    super(itemView);
    ...
    descriptionTextView.setOnClickListener(descriptionListener);
    qtyTextView.setOnClickListener(quantityListener);
    ...
}

【讨论】:

    【解决方案2】:

    您可以从您的ViewHolder 调用getAdapterPosition(),这将返回项目在RecyclerView 中的位置。并使用该位置,您可以找到已单击的行。

    返回的位置是基于RecyclerView 中的总项目的位置,而不仅仅是屏幕上可见的项目。

    【讨论】:

    • 抱歉,我的问题可能不清楚。我已经有一个事件响应点击了哪一行。我想回复点击了哪一列。
    • 不应将clickListener 设置为itemView,而应将其设置为单个view(或列)。
    【解决方案3】:

    你应该听你想要的TextView。使用itemView.setOnClickListener(this); 您可以收听整个适配器项目。您应该使用acceptTextView.setOnClickListener(this);,因为您想收听特定视图并在onClick() 方法中检查单击的项目。

    switch(view.getId()) {
       case R.id.accept_textview:
           // do what you want when click accept textview
       break;
    }
    

    【讨论】:

      【解决方案4】:

      处理点击事件最简洁的方法是使用 Butterknife 库并为所有点击提供单独的方法。它删除了如此多的样板代码,并且非常易于使用。在这里查看如何使用 Butterknife - http://jakewharton.github.io/butterknife/

      另一种方式是为每个TextView提供不同的onClick方法。像这样

      android:onClick="textButton1Clicked"
      

      另一种方法是在 onclick 中获取 TextView 的 ID 并查看用户点击了哪个

       if (view.getID() == R.id.textView1) {
      
      } else (view.getID() == R.id.textView2) {
      
      } else (view.getID() == R.id.textView3) {
      
      }
      

      您还可以使用 switch 语句以获得更好的可维护性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-23
        • 1970-01-01
        • 2012-02-18
        • 1970-01-01
        • 1970-01-01
        • 2016-06-11
        相关资源
        最近更新 更多