Afz*_*ivE 39 android kotlin android-recyclerview
我在使用Android 3年后,正在Kotlin编写我的第一个应用程序.只是混淆了如何在Kotlin中使用itemClickListener和RecyclerView.
我尝试过特征(编辑:现在界面)方法,非常类似于Java
public class MainActivity : ActionBarActivity() {
protected override fun onCreate(savedInstanceState: Bundle?) {
// set content view etc go above this line
class itemClickListener : ItemClickListener {
override fun onItemClick(view: View, position: Int) {
Toast.makeText(this@MainActivity, "TEST: " + position, Toast.LENGTH_SHORT).show()
}
}
val adapter = DrawerAdapter(itemClickListener())
mRecyclerView.setAdapter(adapter)
}
trait ItemClickListener {
fun onItemClick(view: View, position: Int)
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎非常多余,所以我尝试了内部类方法:
inner class ItemClickListener {
fun onItemClick(view: View, position: Int) {
startActivityFromFragmentForResult<SelectExerciseActivity>(SELECT_EXERCISES)
}
}
Run Code Online (Sandbox Code Playgroud)
然后只需设置适配器的点击监听器,如下所示:
val adapter = WorkoutsAdapter(ItemClickListener())
Run Code Online (Sandbox Code Playgroud)
但我仍然对此不满意,因为我认为可能会有更好,更清洁的方式.我试图基本上实现这样的事情: RecyclerView onClick
有什么建议?
结束了批准的答案的变化
定义了活动中的功能:
val itemOnClick: (View, Int, Int) -> Unit = { view, position, type ->
Log.d(TAG, "test")
}
Run Code Online (Sandbox Code Playgroud)
将函数本身传递给适配器,如下所示:
class ExercisesAdapter(val itemClickListener: (View, Int, Int) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
// other stuff up here
val vhExercise = ExerciseVH(view) // view holder
// on to the view holder through the extension function
vhExercise.onClick(itemClickListener)
}
}
Run Code Online (Sandbox Code Playgroud)
循环中的扩展功能在下面的批准答案中.
fun <T : RecyclerView.ViewHolder> T.onClick(event: (view: View, position: Int, type: Int) -> Unit): T {
itemView.setOnClickListener {
event.invoke(it, getAdapterPosition(), getItemViewType())
}
return this
}
Run Code Online (Sandbox Code Playgroud)
den*_*rle 40
我的解决方案就像以前的解决方案一样,来自活动的超级干净通话.
ContactAdapter:
class ContactAdapter @Inject constructor() : RecyclerView.Adapter<ContactAdapter.ViewHolder>() {
var onItemClick: ((Contact) -> Unit)? = null
var contacts: List<Contact> = emptyList()
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val contact = contacts[position]
holder.email.text = contact.email
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val email: TextView = itemView.email
init {
itemView.setOnClickListener {
onItemClick?.invoke(contacts[adapterPosition])
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
ContactActivity:
override fun setupRecyclerAdapter() {
recyclerView.adapter = contactAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
contactAdapter.onItemClick = { contact ->
// do something with your item
Log.d("TAG", contact.email)
}
}
Run Code Online (Sandbox Code Playgroud)
Dam*_*tla 25
我有一点不同的方法.您可以为ViewHolder创建扩展程序
fun <T : RecyclerView.ViewHolder> T.listen(event: (position: Int, type: Int) -> Unit): T {
itemView.setOnClickListener {
event.invoke(getAdapterPosition(), getItemViewType())
}
return this
}
Run Code Online (Sandbox Code Playgroud)
然后在这样的适配器中使用它
class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
val items: MutableList<String> = arrayListOf()
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MyViewHolder? {
val inflater = LayoutInflater.from(parent!!.getContext())
val view = inflater.inflate(R.layout.item_view, parent, false)
return MyViewHolder(view).listen { pos, type ->
val item = items.get(pos)
//TODO do other stuff here
}
}
override fun onBindViewHolder(holder: MyViewHolder?, position: Int) {
}
override fun getItemCount(): Int {
return items.size()
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
}
}
Run Code Online (Sandbox Code Playgroud)
我和我的同事一起在图书馆提供这样的扩展.
Ang*_*oko 15
您可以通过使用接口轻松实现这一点
class ExercisesAdapter(private val itemClickListener: ItemClickListener) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
interface ItemClickListener {
fun onItemClick(position: Int)
fun onLongClick(position: Int)
}
inner class MyViewHolder(view:View): RecyclerView.ViewHolder(view){
init {
view.setOnClickListener {
if (bindingAdapterPosition >= 0) {
itemClickListener.onItemClick(bindingAdapterPosition)
}
}
view.setOnLongClickListener{
if (bindingAdapterPosition >= 0) {
itemClickListener.onLongClick(bindingAdapterPosition)
}
return@setOnLongClickListener true
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
来自您的MainActivity
public class MainActivity : AppCompatActivity(), ExercisesAdapter.ItemClickListener {
protected override fun onCreate(savedInstanceState: Bundle?) {
// set content view etc go above this line
mAdapter = ExercisesAdapter(this)
}
override fun onItemClick(position: Int) {
Toast.makeText(this@MainActivity, "TEST: " + position, Toast.LENGTH_SHORT).show()
}
override fun onLongClick(position: Int) {
//do long click here
}
}
Run Code Online (Sandbox Code Playgroud)
Raj*_*ddy 11
对不起,很抱歉,此链接提供了一个很棒的答案,它是Java的。做了一些功课,并将其转换为Kotlin。
现在它可以正常工作了。这是代码,
创建一个名为RecyclerItemClickListenr的类,
class RecyclerItemClickListenr(context: Context, recyclerView: RecyclerView, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {
private val mGestureDetector: GestureDetector
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
fun onItemLongClick(view: View?, position: Int)
}
init {
mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean {
return true
}
override fun onLongPress(e: MotionEvent) {
val childView = recyclerView.findChildViewUnder(e.x, e.y)
if (childView != null && mListener != null) {
mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView))
}
}
})
}
override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
val childView = view.findChildViewUnder(e.x, e.y)
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView))
}
return false
}
override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}}
Run Code Online (Sandbox Code Playgroud)
并以“活动/片段”身份访问
recyclerView.addOnItemTouchListener(RecyclerItemClickListenr(this, recyclerView, object : RecyclerItemClickListenr.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
//do your work here..
}
override fun onItemLongClick(view: View?, position: Int) {
TODO("do nothing")
}
}))
Run Code Online (Sandbox Code Playgroud)
not*_*ato 10
如果有人正在寻找更简单的答案,我尝试了以下 - 这与AfzalivE的解决方案非常相似:
在我的Adapter类中,我传递了clickListener
一个参数.在onBindViewHolder
,我曾经setOnClickListener
打电话clickListener
和处理点击事件.
MyAdapter.kt:
class MyAdapter constructor(objects: ArrayList<MyObject>, val clickListener: (MyObject) -> Unit) : RecyclerView.Adapter<MyAdapter.Holder>() {
private var mObjects : ArrayList<MyObject> = ArrayList<MyObject>()
init {
mObjects = objects
}
override fun onBindViewHolder(holder: Holder?, position: Int) {
var item : MyObject = objects[position]
// Calling the clickListener sent by the constructor
holder?.containerView?.setOnClickListener { clickListener(item) }
}
// More code (ViewHolder definitions and stuff)...
}
Run Code Online (Sandbox Code Playgroud)
注意:我需要从列表项的容器(根视图)中引用,在本例中是containerView
然后我将我的对象作为参数传递,而不需要再次在列表中搜索它并直接在我的Activity
类上处理它,在我设置适配器的那一刻:
MyActivity.kt:
myRecyclerView?.adapter = MyAdapter(mObjects) {
Log.e("Activity", "Clicked on item ${it.itemName}")
}
Run Code Online (Sandbox Code Playgroud)
更新
如果您需要获取所单击项目的位置,只需将其定义为回调中的参数,然后稍后将其发回.请注意val clickListener: (MyObject, Int) -> Unit
以下内容:
MyAdapter.kt
class MyAdapter constructor(objects: ArrayList<MyObject>, val clickListener: (MyObject, Int) -> Unit) : RecyclerView.Adapter<MyAdapter.Holder>() {
// Rest of the code...
Run Code Online (Sandbox Code Playgroud)
然后在onBindViewHolder()
调用回调方法时传递位置:
override fun onBindViewHolder(holder: Holder?, position: Int) {
var item : MyObject = objects[position]
// Calling the clickListener sent by the constructor
holder?.containerView?.setOnClickListener { clickListener(item, position) }
}
Run Code Online (Sandbox Code Playgroud)
在MyActivity.kt上,您必须更改设置适配器的方式,以便获得该位置.像这样:
myRecyclerView?.adapter = MyAdapter(mObjects) { itemDto: MyObject, position: Int ->
Log.e("MyActivity", "Clicked on item ${itemDto.someItemPropertyLikeName} at position $position")
}
Run Code Online (Sandbox Code Playgroud)
在 onBindViewHolder 上添加 ClickListener 代码乐趣
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.vieww.textView.setText(arr.get(position))
holder.vieww.setOnClickListener {(holder.vieww.textView.setTextColor(Color.GREEN))} // click event
}
Run Code Online (Sandbox Code Playgroud)
小智 7
您不需要向 ViewHolder 或类似的东西编写扩展函数。
最佳实践; 使用高阶函数
class MainRecyclerAdapter(val news: JSONArray, private val itemClickListener: (Int) -> Unit) : RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder>() {}
Run Code Online (Sandbox Code Playgroud)
只需添加一个高阶函数即可。像itemClickListener然后转到ViewHolder类。将此函数作为参数写入您的绑定函数,并将其设置为 itemView 像这样:
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bind(newsItem: JSONObject,itemClickListener:(Int)->Unit) {
//Some Stuff here..
itemView.setOnClickListener { itemClickListener(adapterPosition) }
}
}
Run Code Online (Sandbox Code Playgroud)
在BindViewHolder上使用这个方法
override fun onBindViewHolder(holder: MainRecyclerAdapter.ViewHolder, position: Int) {
holder.bind(news.getJSONObject(position),itemClickListener)
}
Run Code Online (Sandbox Code Playgroud)
现在您可以在任何活动或片段中编写 onClick 函数。只需提供参数即可。
val itemOnClick: (Int) -> Unit = { position ->
newsRecyclerView.adapter!!.notifyDataSetChanged()
Toast.makeText(this.context,"$position. item clicked.",Toast.LENGTH_SHORT).show()
}
newsRecyclerView.adapter = MainRecyclerAdapter(news,itemClickListener = itemOnClick)
Run Code Online (Sandbox Code Playgroud)
小智 7
基于denwehrle略有不同
要在片段上使用,请在OnCreateView内
adapter.onItemClick = {it ->
//do something
}
Run Code Online (Sandbox Code Playgroud)
添加适配器类:
var onItemClick: ((Contact)->Unit) ?= null
...
inner class contactViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val myItemView: TextView = itemView.findViewById(R.id.textView)
init{
itemView.setOnClickListener {
onItemClick?.invoke(contact[adapterPosition])
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为最优雅的解决方案是将责任赋予recyclerView,而不是查看甚至改编它。
为此,我们需要:
class RecyclerItemClickListener(
private val mRecycler: RecyclerView,
private val clickListener: ((position: Int, view: View) -> Unit)? = null,
private val longClickListener: ((position: Int, view: View) -> Unit)? = null
) : RecyclerView.OnChildAttachStateChangeListener {
override fun onChildViewDetachedFromWindow(view: View) {
view.setOnClickListener(null)
view.setOnLongClickListener(null)
}
override fun onChildViewAttachedToWindow(view: View) {
view.setOnClickListener { v -> setOnChildAttachedToWindow(v) }
}
private fun setOnChildAttachedToWindow(v: View?) {
if (v != null) {
val position = mRecycler.getChildLayoutPosition(v)
if (position >= 0) {
clickListener?.invoke(position, v)
longClickListener?.invoke(position, v)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
import android.support.v7.widget.RecyclerView
import com.app.manager.internal.common.RecyclerItemClickListener
@JvmOverloads
fun RecyclerView.affectOnItemClicks(onClick: ((position: Int, view: View) -> Unit)? = null, onLongClick: ((position: Int, view: View) -> Unit)? = null) {
this.addOnChildAttachStateChangeListener(RecyclerItemClickListener(this, onClick, onLongClick))
}
Run Code Online (Sandbox Code Playgroud)
import kotlinx.android.synthetic.main.{your_layout_name}.*
class FragmentName : Fragment() {
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
recycler.affectOnItemClick { position, view -> /*todo*/ }
}
}
Run Code Online (Sandbox Code Playgroud)
3个简单的步骤:
1. 传入你的适配器参数如下:
class ListAdapter(private val mListener: (ListItemDataClass) -> Unit)
Run Code Online (Sandbox Code Playgroud)
2.在onBindViewHolder
功能上,像这样使用
override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
val item = getItem(position)
holder.itemView.setOnClickListener {
item?.let { it1 -> mListener.invoke(it1) }
}
}
Run Code Online (Sandbox Code Playgroud)
3.在你的活动中,像这样使用
val adapter = ListAdapter {
Toast.makeText(this, it.title, Toast.LENGTH_SHORT).show()
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这是一种不使用接口的简单方法,只需在适配器中在 viewholder 类中创建一个 init 块即可。像下面这样
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
init {
itemView.setOnClickListener{
//your code here---
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
49775 次 |
最近记录: |