如何在回收视图中为自定义ViewHolder实现OnClickListener?

我正在创建一个应用程序,应该显示在recyclerview中的蓝牙设备,我希望用户能够单击项目执行操作。 现在我只是试图让吐司出现在点击后,但我想可能会显示一个对话框给对选择等,但我明显缺少的东西在我onclicklistener的用法。 我试图让我的ViewHolder类: DeviceHolder实现View.OnClickListener ,并将调用Toast.makeText()内我的onClick覆盖。 然而,没有任何事情发生。 我相信我只是错过了一些小事,并会感谢帮助find问题。 另外,我正在做的这kotlin,我是新来的,如果有可能更有效,kotlintypes的方式做到这一点,也将有所帮助。 我在下面张贴我的代码。 提前致谢。

 class DeviceAdapter(val mContext : Context) : RecyclerView.Adapter(){ val mDevices = ArrayList() interface OnClickListener{ fun onClick(v: View) } fun updateItems(list: ArrayList){ mDevices.clear() mDevices.addAll(list) Log.d(TAG, "updating items : $mDevices") notifyDataSetChanged() } fun ViewGroup.inflate(@LayoutRes res: Int, attachToRoot: Boolean = false): View{ return LayoutInflater.from(mContext).inflate(res, this, attachToRoot) } override fun onBindViewHolder(holder: DeviceHolder, position: Int) { Log.d(TAG, "onBindViewHolder called!") holder.bindItems(mDevices.get(position)) } override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): DeviceAdapter.DeviceHolder{ Log.d(TAG, "onCreateViewHolder called!") val v = parent!!.inflate(R.layout.device_item, false) return DeviceHolder(v) } override fun getItemCount(): Int { return mDevices.size } inner class DeviceHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener { override fun onClick(v: View?) { Toast.makeText(mContext, "test", Toast.LENGTH_LONG).show() } val nameView = itemView.findViewById(R.id.nameView) as TextView val addrView = itemView.findViewById(R.id.addressView) as TextView fun bindItems(btDevice: BluetoothDevice) { Log.d(TAG, "holder created!") nameView.text = btDevice.name addrView.text = btDevice.address itemView.setOnClickListener { this } } } companion object { val TAG = "Device Adapter" } } 

这里是日志消息:

 10-09 00:35:50.233 7581-7581/com.example.zemcd.toofxchange D/DiscoveryTask: device found! 10-09 00:35:51.795 7581-7581/com.example.zemcd.toofxchange D/DiscoveryTask: device found! 10-09 00:35:56.752 7581-7581/com.example.zemcd.toofxchange D/DiscoveryTask: device list : [**:B8:9A:39:1D:**, **:DF:BF:2A:F3:**] 10-09 00:35:56.752 7581-7581/com.example.zemcd.toofxchange D/Device Adapter: updating items : [**:B8:9A:39:1D:**, **:DF:BF:2A:F3:**] 10-09 00:35:56.752 7581-7581/com.example.zemcd.toofxchange D/DiscoveryTask: discovery finished 10-09 00:35:56.762 7581-7581/com.example.zemcd.toofxchange D/Device Adapter: onCreateViewHolder called! 10-09 00:35:56.774 7581-7581/com.example.zemcd.toofxchange D/Device Adapter: onBindViewHolder called! 10-09 00:35:56.774 7581-7581/com.example.zemcd.toofxchange D/Device Adapter: holder created! 10-09 00:35:56.783 7581-7581/com.example.zemcd.toofxchange D/Device Adapter: onCreateViewHolder called! 10-09 00:35:56.786 7581-7581/com.example.zemcd.toofxchange D/Device Adapter: onBindViewHolder called! 10-09 00:35:56.786 7581-7581/com.example.zemcd.toofxchange D/Device Adapter: holder created! 

我设法通过消除OnClickListener的实现来解决这个问题,而只是使用这个语句来代替itemView.setOnClickListener { /* lamda here */ } 。 我不相信这个确切的语法在Java中可用,但在作品中的KOTLIN。 这里是我修改的代码:

 inner class DeviceHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val nameView = itemView.findViewById(R.id.nameView) as TextView val addrView = itemView.findViewById(R.id.addressView) as TextView fun bindItems(btDevice: BluetoothDevice) { Log.d(TAG, "holder created!") nameView.text = btDevice.name addrView.text = btDevice.address itemView.setOnClickListener { Toast.makeText(it.context, "testing", Toast.LENGTH_SHORT).show() } } } 

通过在lambda内部使用it关键字,我访问了itemView对象的上下文,而不是使用上面描述的我原来的mContext。 我仍然不确定为什么我的旧方法不起作用,但是这样做对我很有用。

根据你的代码你正在实现clicklistner,但没有添加任何注册点击listener.add clickListener为nameViewAddrView

 nameView.setOnClickListener(this); addrView.setOnClickListener(this); 

这工作:

1将您自己的点击侦听器设置为适配器,并保留对其的引用:

 private OnItemClickListener onItemClickListener; // ... public interface OnItemClickListener { // note: here you would need some params, for instance the view void onItemClick(View v); } public void setOnItemClickListener(OnItemClickListener l) { this.onItemClickListener = l; } 

2当创建每个视图的时候,设置一个监听器,并且一旦回调,就把这个回调传递给1中设置的监听器:

 @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ViewHolder vh = getViewHolder( /*...*/ ); vh.setOnItemClickListener(new OnItemClickListener() { if (onItemClickListener != null) { // each view holder calls the one listener set to the Adapter onItemClickListener.onItemClick(v); } } } 

3让你的观众在onClick上听(完整的)观点,让它转发呼叫:

 public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { // each view holder has a listener set to it private OnItemClickListener mListener; public ViewHolder(View v) { super(v); // ... // set the viewholder as a listener to the view's clicks v.setOnClickListener(this); } @Override public void onClick(View v) { // when view is clicked, simply forward the call if (mListener != null) { mListener.onItemClick(v); } } public void setOnItemClickListener(OnItemClickListener listener) { mListener = listener; } 

}

4在这一点上,适配器用户将有:

 mAdapter = new MyAdapter(ctx); mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() { @Override public void onItemClick(View v) { // the given view was clicked, do something with it } });