Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用RecyclerView的SelectionTracker选择第一项而无需长按_Java_Android_Android Recyclerview - Fatal编程技术网

Java 如何使用RecyclerView的SelectionTracker选择第一项而无需长按

Java 如何使用RecyclerView的SelectionTracker选择第一项而无需长按,java,android,android-recyclerview,Java,Android,Android Recyclerview,我正在构建一个应用程序,允许用户从RecyclerView列表中选择,突出显示他们的选择。问题在于,为了第一次突出显示某个项目,需要长时间按下。然后,短按一下就足以进行选择 我在文档中没有找到任何东西来说明为什么会发生这种情况 我正在使用 具体如下: 代码如下: 期望: 我希望每次有人短按RecyclerView上的项目时,它都会被选中 现实: 为了第一次选择一个项目,用户需要长按它 有什么想法吗?尽管我想不出一个解决方案不包括重新实现MotionInputHandler和SelectionT

我正在构建一个应用程序,允许用户从RecyclerView列表中选择,突出显示他们的选择。问题在于,为了第一次突出显示某个项目,需要长时间按下。然后,短按一下就足以进行选择

我在文档中没有找到任何东西来说明为什么会发生这种情况

我正在使用

具体如下:

代码如下:

期望: 我希望每次有人短按RecyclerView上的项目时,它都会被选中

现实: 为了第一次选择一个项目,用户需要长按它


有什么想法吗?

尽管我想不出一个解决方案不包括重新实现MotionInputHandler和SelectionTracker.Builder,正如指南中提到的,有一个巧妙的技巧可以实现您想要的行为

我们知道,只要SelectionTracker不是空的,TouchInputHandler就可以通过单击来选择项目。这意味着,如果我们在SelectoinTracker中保存了一些与实际列表项无关的特殊键,那么我们实际上可以通过这种方式“激活”单击选择模式。但是,我们还必须确保我们的密钥提供者不提供相同的特殊密钥来保持数据的一致性

因此,假设您选择了一个特殊的键(例如ghostKey),那么激活和禁用选择模式现在只需调用mSelectionTracker.selectghostkey或mSelectionTracker.clearSelection即可。然后,您可以随意执行这些调用,可以使用一个按钮激活和禁用选择模式,也可以在宿主视图创建过程中简单地调用该模式,即onCreate、onCreateView等

如果您使用的是Kotlin,您还可以定义一些扩展来包装这些调用,这样您就可以执行诸如mSelectionTracker.enable或mSelectionTracker.disable之类的操作。这就是我所做的:

binding.root.setOnClickListener {
   tracker?.let {
     if(!it.hasSelection()) it.select(binding.currItem?.uuid!!)
        binding.setVariable(BR.selected, it.isSelected(binding.currItem?.uuid))
     }

     binding.executePendingBindings()
}
我在视图上实现了一个点击监听器,检查选择跟踪器是否有任何选中的实体。如果它没有任何选择,那么我显式地添加了选择,选择跟踪器将自动启用


我想这一定是您正在寻找的解决方案。

只需覆盖SelectionHotspot即可返回true。这就是你所需要的

fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
            object : ItemDetailsLookup.ItemDetails<Long>() {
                override fun getPosition(): Int = adapterPosition
                override fun getSelectionKey(): Long? = itemId
                override fun inSelectionHotspot(e: MotionEvent): Boolean { return true }
            }
用这条线

selectionTracker.selectitem.getSelectionKey

在这个覆盖方法上

 .withOnItemActivatedListener(new OnItemActivatedListener() {
                @Override
                public boolean onItemActivated(@NonNull ItemDetailsLookup.ItemDetails item, @NonNull MotionEvent e) {
                    selectionTracker.select(item.getSelectionKey());
                    return true;
                }
            })
我是这样解决的。继续编码..

RecyclerView选择框架的设计不适合处理以下任一情况

A.一个“启用多重选择”按钮,用于打开和关闭多重选择

B.使用多个不能选择的行ViewType的RecyclerView适配器

*如果您的范围需要上述A.或B.项,请不要使用RecyclerView选择框架

相反,请将其卸下并执行以下操作:

一,。将Post Api数据字段添加到列表项模型:

var isMultiSelected: Boolean = false // User has highlighted this inbox's row for multi-selection
二,。创建一个侦听器,以便从适配器与片段/活动进行通信:

class MyFragment : MyFragmentListener {
interface MyFragmentListener {
    fun myDataModelOnClick(myDataModel: MyDataModel)
    fun engageMultiSelect(selectedDataModelCount: Int)
    fun disengageMultiSelect()
}
override fun engageMultiSelect(selectedMyModelCount: Int) {
    // Update the fragment view for multi-select engaged conditions
    selectedCount_textView.text = selectedMyModelCount.toString()
}

override fun disengageMultiSelect() {
// Update the fragment view for multi-select engaged conditions
}
三,。更新Adapter.onBindViewHolder以使用新字段

holder.enableMultiSelectionButton.setOnClickListener {
    myModel.isMultiSelected = true
    myModel.engageMultiSelect(getMultiSelectionCount()) // Enable multi-selection
    notifyItemChanged(position)
}
holder.rowConstraintLayout.setOnClickListener {
    if (getMultiSelectionCount() > 0) { // Is multi-selection engaged?
        myModel.isMultiSelected = !myModel.isMultiSelected
        if (getMultiSelectionCount() > 0) { // New Item Count may still be larger than 0
            myModelListener.engageMultiSelect(getMultiSelectionCount())
        } else {
            myModelListener.disengageMultiSelect()
        }
        notifyItemChanged(position)
    } else {
        // Normal 'tap' when multi-selection is not engaged
    }
}
holder.rowConstraintLayout.setOnLongClickListener {
    myModel.isMultiSelected = !myModel.isMultiSelected
    if (getMultiSelectionCount() > 0) { // Is multi-selection engaged?
        myModelListener.engageMultiSelect(getMultiSelectionCount())
    } else {
        myModelListener.disengageMultiSelect()
    }
    notifyItemChanged(position)
    true
}
if (myModel.isMultiSelected) {
    holder.rowConstraintLayout.setBackgroundColor(R.id.coolcolor)
} else {
    holder.rowConstraintLayout.setBackgroundColor(R.id.white)
}
在您的ViewHolder中,设置onClickListener,并在其中使用SelectionTracker.hasSelection检查是否有任何选定的项目,如果返回false,只需使用SelectionTracker.selectgetItemDetails.getSelectionKey选择该项目即可 像这样:

itemView.setOnClickListener(v -> {
    if (!tracker.hasSelection())
        tracker.select(getItemDetails().getSelectionKey());
    });

所以这个场景应该像谷歌照片应用程序一样。一旦长按,照片就会被选中,然后你只需点击照片进行选择。这听起来很相似,是的。但是,我不想这样,好吧。因此,每次您想长按单击进行选择时?每次我想短按单击进行选择时。短按意味着只需单击即可。另外,请注意,只要启用了“选择模式”,即使未选择任何可见项目,mSelectionTracker.hasSelection现在也将返回true。因此,您可能需要进行额外检查,以确保项目确实被选中。谢谢您的回答!如果我理解正确,您建议我在第一次选择之前和取消选择之后选择一个不存在的项目,以便跳过长时间单击?是,基本上是在后台选择一个虚构的项目,只要在单击时选择真实的项目,我检查mSelectionTracker.hasSelection ononselection是否已更改,因此它似乎可以工作。非常感谢。非常感谢兄弟们这么做了,但没用。它在使用android studio emulator的API 21和API 26上的行为不同。在inSelectionHotspot中返回false允许长按API 21中的选择,但仍然可以单按API 26。我想在API 26上强制长按。@DeKekem如果要长按,请不要重写inSelectionHotspot方法。其默认行为是长按选择第一项。您可以在MyModelAdapter构造函数clas中将MyModelFragmentListener添加到MyModelAdapter s MyModelAdapterprivate val myModelFragmentListener:myModelFragmentListener