我已经看到了许多示例,这些示例为行项目提供单击功能(用于在回收器视图中选择行项目),但是所有这些示例都使用自定义单击侦听器类来实现。有什么方法可以实现这种点击功能?
答案 0 :(得分:1)
检测RecyclerView项的单击非常简单。您需要做的就是定义一个接口(如果您不使用Kotlin,在这种情况下,您只需传入一个lambda):
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private final Clicks clicks;
public MyAdapter(Clicks clicks) {
this.clicks = clicks;
}
private List<MyObject> items = Collections.emptyList();
public void updateData(List<MyObject> items) {
this.items = items;
notifyDataSetChanged(); // TODO: use ListAdapter for diffing instead if you need animations
}
public interface Clicks {
void onItemSelected(MyObject myObject, int position);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private MyObject myObject;
public MyViewHolder(View view) {
super(view);
// bind views
view.setOnClickListener((v) -> {
int adapterPosition = getAdapterPosition();
if(adapterPosition >= 0) {
clicks.onItemSelected(myObject, adapterPosition);
}
});
}
public void bind(MyObject myObject) {
this.myObject = myObject;
// bind data to views
}
}
}
Kotlin中的相同代码:
class MyAdapter(val itemClicks: (MyObject, Int) -> Unit): RecyclerView.Adapter<MyViewHolder>() {
private var items: List<MyObject> = Collections.emptyList()
fun updateData(items: List<MyObject>) {
this.items = items
notifyDataSetChanged() // TODO: use ListAdapter for diffing instead if you need animations
}
inner class MyViewHolder(val myView: View): RecyclerView.ViewHolder(myView) {
private lateinit var myObject: MyObject
init {
// binds views
myView.onClick {
val adapterPosition = getAdapterPosition()
if(adapterPosition >= 0) {
itemClicks.invoke(myObject, adapterPosition)
}
}
}
fun bind(myObject: MyObject) {
this.myObject = myObject
// bind data to views
}
}
}
答案 1 :(得分:1)
如果使用Kotlin,则可以将方法作为构造函数参数或通过setter方法发送。对于Kotlin中的这种情况,您无需创建任何接口侦听器。
class ImageCategoryAdapter(val listener: (YourType) -> Unit) : RecyclerView.Adapter<ImageCategoryAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_poll_category, parent, false))
}
override fun getItemCount() = yourList.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// ...
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
// ...
init {
// this is the magic
itemView.setOnClickListener { listener.invoke(yourList[adapterPosition]) }
}
}
}
在适配器中,我们将函数用作名为listener的构造函数参数。然后单击项目视图,我们将使用所需类型调用该功能。
val adapter = ImageCategoryAdapter {
// Your callback
// here it will be type of parameter which we are sending from adapter by invoking the function.
processClickedItem(it)
}
这就是为什么我沉迷于Kotlin的原因。在这种情况下,不需要接口回调。
已更新 如果您也想发送职位。
class ImageCategoryAdapter(val listener: (YourType, Int) -> Unit) : RecyclerView.Adapter<ImageCategoryAdapter.ViewHolder>() {
...
}
您必须使用两个参数来调用此函数。
itemView.setOnClickListener { listener.invoke(yourList[adapterPosition], adapterPosition) }
现在我们可以看到有多个参数,因此it
对于参数不起作用,我们必须为此lambda函数提供变量名称。
val adapter = ImageCategoryAdapter { clickItem, position -> processClickedItem(clickItem, position)}