片段内的 RecyclerView 的 Kotlin OnItemClickListener
Posted
技术标签:
【中文标题】片段内的 RecyclerView 的 Kotlin OnItemClickListener【英文标题】:Kotlin OnItemClickListener for a RecyclerView inside a Fragment 【发布时间】:2021-06-29 03:59:45 【问题描述】:问题与我无法通过在适配器中实现 OnClickListener 来为位于“mainFragment”中的 RecyclerView 实现 OnItemClick 侦听器有关。
我希望我的应用程序 (kotlin) 每次单击 RecyclerView 中的 itemView(一个 ImageView)时启动另一个片段(以下代码中的“deletePage”),这个片段将显示同一张照片。
我的适配器代码如下:
class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>()
private var photo = emptyList<Photo>()
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder
return MyViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.row_layout, parent, false)
)
override fun getItemCount(): Int
return photo.size
override fun onBindViewHolder(holder: MyViewHolder, position: Int)
holder.itemView.longitude.text = photo[position].latitude
holder.itemView.latitude.text = photo[position].longitude
holder.itemView.imageView.load(photo[position].photo)
fun setData(photo: List<Photo>)
this.photo = photo
notifyDataSetChanged()
而我的 mainFragment 代码如下:
class MainFragment : Fragment()
private lateinit var myView: MyViewModel
private val adapter by lazy MyAdapter()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View?
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_main, container, false)
//Recyclerview
val adapter = MyAdapter()
val recyclerView = view.recycler_view
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(requireContext())
myView = ViewModelProvider(this).get(MyViewModel::class.java)
myView.readPhoto.observe(viewLifecycleOwner, Observer photo ->
adapter.setData(photo)
)
setHasOptionsMenu(true)
return view
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater)
inflater.inflate(R.menu.menu_database, menu)
override fun onOptionsItemSelected(item: MenuItem): Boolean
when
item.itemId == R.id.deleteAll -> findNavController().navigate(R.id.deletePage)
item.itemId == R.id.refresh ->
Toast.makeText(activity, "yep", Toast.LENGTH_SHORT).show()
instertDataToDatabase()
if (item.itemId == R.id.deleteAll)
return super.onOptionsItemSelected(item)
目标是,当您单击 RecyclerView 的项目时,会显示“findNavController().navigate(R.id.deletePage)”片段,但每次我尝试实施解决方案时,应用程序在单击项目时崩溃回收站视图。现在导航可以通过单击工具栏菜单中的按钮来工作,但这不是理想的解决方案。
非常感谢任何形式的帮助或建议!
【问题讨论】:
【参考方案1】:首先,您需要在onBindViewHolder
中为您的 itemView 提供点击监听器
override fun onBindViewHolder(holder: MyViewHolder, position: Int)
holder.itemView.longitude.text = photo[position].latitude
holder.itemView.latitude.text = photo[position].longitude
holder.itemView.imageView.load(photo[position].photo)
holder.itemView.setOnClickListener navigateToFragment()
对于导航,您应该有一个上下文实例。 以下是我想到的可能的解决方案:
将导航器实例提供给适配器
class Navigator(fragment: Fragment)
private val fragmentRef = WeakReference(fragment)
fun navigate()
// make your navigations here with using fragmentRef.get()
在您的片段中:
private val navigator = Navigator(this)
...
val adapter = MyAdapter(navigator)
在您的适配器中:
class MyAdapter(private val navigator: Navigator) : RecyclerView.Adapter<MyAdapter.MyViewHolder>()
fun navigateToFragment()
navigator.navigate()
制作回调接口
2.1。在片段中实现该接口并为适配器提供接口实例
interface Navigable
fun navigate()
在您的片段中:
class MainFragment : Fragment(), Navigable
...
override fun navigate()
// make your navigation
val adapter = MyAdapter(navigator)
在您的适配器中:
class MyAdapter(private val navigable: Navigable) : RecyclerView.Adapter<MyAdapter.MyViewHolder>()
fun navigateToFragment()
navigable.navigate()
2.2。制作接口,但不传引用,在adapter中使用findFragment
在您的适配器中:覆盖 onAttachedToRecyclerView
以查找片段
private lateinit var navigable: Navigable
override fun onAttachedToRecyclerView(recyclerView: RecyclerView)
super.onAttachedToRecyclerView(recyclerView)
navigable = recyclerView.findFragment<Fragment>() as Navigable
fun navigateToFragment()
navigable.navigate()
【讨论】:
我不认为适配器应该实现点击逻辑或保留对主机片段的引用。相反,我认为公开一个回调并使用它来实现片段的操作会是一个更好的解决方案。 我更喜欢使用数据绑定并从 xml 提供单击侦听器,但是在此示例中,视图只能在适配器内部访问。要么我们将视图从适配器传递到片段,要么适配器将通过回调通知片段。您如何在没有参考的情况下从适配器进行回调?以上是关于片段内的 RecyclerView 的 Kotlin OnItemClickListener的主要内容,如果未能解决你的问题,请参考以下文章
E/RecyclerView:没有附加适配器;在片段内的recyclerview上跳过布局
android studio中片段内的RecyclerView使我的应用程序崩溃
android RecyclerView pinch zoom,ScaleGestureDetector&GridLayoutManager,with BigImageViewer,kotli