RecyclerView上的快速点击(点击)会打开多个片段

Thu*_*oid 12 android android-adapter android-fragments onclicklistener android-recyclerview

我已经在我的ViewHolder上为我的RecyclerView实现了onClick监听器

但是当我执行非常快速的双击或鼠标点击时,它执行任务(在这种情况下打开一个单独的片段)两次或三次.

这是我的代码

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    TextView tvTitle, tvDescription;

    public ViewHolder(View itemView) {
        super(itemView);
        itemView.setClickable(true);
        itemView.setOnClickListener(this);

        tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
        tvDescription = (TextView) itemView.findViewById(R.id.tv_description);
    }

    @Override
    public void onClick(View v) {
        mListener.onClick(FRAGMENT_VIEW, getAdapterPosition()); // open FRAGMENT_VIEW
    }
}
Run Code Online (Sandbox Code Playgroud)

关于如何防止这种行为的任何想法?

小智 18

你可以像这样修改它.

public class ViewHolder extends RecyclerView.ViewHolder implements
        View.OnClickListener {
    TextView tvTitle, tvDescription;
    private long mLastClickTime = System.currentTimeMillis();
    private static final long CLICK_TIME_INTERVAL = 300;

    public ViewHolder(View itemView) {
        super(itemView);
        itemView.setClickable(true);
        itemView.setOnClickListener(this);

        tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
        tvDescription = (TextView) itemView
                .findViewById(R.id.tv_description);
    }

    @Override
    public void onClick(View v) {
        long now = System.currentTimeMillis();
        if (now - mLastClickTime < CLICK_TIME_INTERVAL) {
            return;
        }
        mLastClickTime = now;
        mListener.onClick(FRAGMENT_VIEW, getAdapterPosition()); // open
                                                                // FRAGMENT_VIEW
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 答案很好,但它只解决了涉及同一项目的案例的问题.我的意思是,如果用户触摸item1并立即触摸item2,则会打开两个片段.至少,这发生在我身上. (8认同)

joa*_*t4u 12

这里最直接的方法是使用setMotionEventSplittingEnabled(false)你的RecyclerView.

默认情况下,此设置为true RecyclerView,允许处理多个触摸.

设置为false时,此ViewGroup方法会阻止RecyclerView子项接收多次单击,仅处理第一次.

在这里查看更多相关信息.

  • 这不是真的,内部文档证实了这一点: * @param split &lt;code&gt;true&lt;/code&gt; 允许 MotionEvents 被拆分并分派到多个 * 子视图。&lt;code&gt;false&lt;/code&gt; 只允许一个子视图成为*此 ViewGroup 接收的任何 MotionEvent 的目标。简单来说,设置这个只会阻止多个触摸事件被不同的孩子处理,但是一个孩子仍然可以收到很多触摸事件。(或者更简单地说,单击 a -&gt; b 是不可能的,但是 a -&gt; 双击仍然是可能的) (8认同)

son*_*wen 6

这是一种非常讨厌的行为.我必须使用额外的标志来阻止我的工作.

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView tvTitle, tvDescription;
private boolean clicked;

public ViewHolder(View itemView) {
    super(itemView);
    itemView.setClickable(true);
    itemView.setOnClickListener(this);

    tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
    tvDescription = (TextView) itemView.findViewById(R.id.tv_description);
}

@Override
public void onClick(View v) {
    if(clicked){
        return;
    }
    clicked = true;
    v.postDelay(new Runnable(){
          @Override
          public void run(View v){
              clicked = false;
          }
    },500);
    mListener.onClick(FRAGMENT_VIEW, getAdapterPosition()); // open FRAGMENT_VIEW
}
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 5

如果您使用的是 Kotlin,则可以根据 Money 的回答进行操作

class CodeThrottle {
    companion object {
        const val MIN_INTERVAL = 300
    }
    private var lastEventTime = System.currentTimeMillis()

    fun throttle(code: () -> Unit) {
        val eventTime = System.currentTimeMillis()
        if (eventTime - lastEventTime > MIN_INTERVAL) {
            lastEventTime = eventTime
            code()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的视图持有者中创建此对象

    private val codeThrottle = CodeThrottle()
Run Code Online (Sandbox Code Playgroud)

然后在你的绑定中执行以下操作

name.setOnClickListener { codeThrottle.throttle { listener.onCustomerClicked(customer, false) } }
Run Code Online (Sandbox Code Playgroud)

放置您需要调用的任何代码来代替

listener.onCustomerClicked(customer, false) 
Run Code Online (Sandbox Code Playgroud)