Ich schreibe meine erste App in Kotlin nach 3 Jahren Erfahrung mit Android . Ich bin nur verwirrt, wie man itemClickListener mit einem RecyclerView in Kotlin verwendet.
Ich habe versucht, das Merkmal (Edit: Now Interface) zu verwenden, sehr Java-ähnlich
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([email protected], "TEST: " + position, Toast.LENGTH_SHORT).show()
}
}
val adapter = DrawerAdapter(itemClickListener())
mRecyclerView.setAdapter(adapter)
}
trait ItemClickListener {
fun onItemClick(view: View, position: Int)
}
}
Das schien sehr überflüssig zu sein, also versuchte ich den inneren Klassenansatz:
inner class ItemClickListener {
fun onItemClick(view: View, position: Int) {
startActivityFromFragmentForResult<SelectExerciseActivity>(SELECT_EXERCISES)
}
}
Und dann einfach den Klick-Listener des Adapters so einstellen:
val adapter = WorkoutsAdapter(ItemClickListener())
Aber ich bin damit nicht zufrieden, weil ich denke, dass es einen besseren und saubereren Weg gibt. Ich versuche im Wesentlichen so etwas zu erreichen: RecyclerView onClick
Irgendwelche Vorschläge?
Endete mit einer Variation der genehmigten Antwort
Definiert die Funktion in der Aktivität:
val itemOnClick: (View, Int, Int) -> Unit = { view, position, type ->
Log.d(TAG, "test")
}
Die Funktion selbst wurde wie folgt an den Adapter übergeben:
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)
}
}
Erweiterungsfunktion durch Schleife in der unten angegebenen genehmigten Antwort.
fun <T : RecyclerView.ViewHolder> T.onClick(event: (view: View, position: Int, type: Int) -> Unit): T {
itemView.setOnClickListener {
event.invoke(it, getAdapterPosition(), getItemViewType())
}
return this
}
Ich habe einen etwas anderen Ansatz. Sie können eine Erweiterung für Ihren ViewHolder erstellen
fun <T : RecyclerView.ViewHolder> T.listen(event: (position: Int, type: Int) -> Unit): T {
itemView.setOnClickListener {
event.invoke(getAdapterPosition(), getItemViewType())
}
return this
}
Dann verwenden Sie es in diesem Adapter
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) {
}
}
Ich arbeite mit meinen Kollegen in library und biete solche Erweiterungen an.
Meine Lösung ist wie eine Kombination der vorherigen mit einem super sauberen Aufruf aus der Aktivität.
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])
}
}
}
}
ContactActivity:
override fun setupRecyclerAdapter() {
recyclerView.adapter = contactAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
contactAdapter.onItemClick = { contact ->
// do something with your item
Log.d("TAG", contact.email)
}
}
Falls jemand nach einer no-frills - Antwort sucht, habe ich Folgendes versucht - was der Lösung von AfzalivE sehr ähnlich ist:
In meiner Adapter-Klasse habe ich die clickListener
als Parameter übergeben. Bei onBindViewHolder
habe ich setOnClickListener
verwendet, um clickListener
aufzurufen und das Click-Ereignis zu behandeln.
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)...
}
Hinweis : Ich benötigte einen Verweis aus dem Container meines Listenelements (der Stammansicht), in diesem Fall containerView
.
Dann habe ich mein Objekt als Parameter übergeben, ohne es erneut in einer Liste suchen zu müssen, und behandele es direkt in meiner Activity
-Klasse, sobald ich den Adapter setze:
MyActivity.kt :
myRecyclerView?.adapter = MyAdapter(mObjects) {
Log.e("Activity", "Clicked on item ${it.itemName}")
}
Update
Wenn Sie die Position des angeklickten Elements ermitteln möchten, definieren Sie es einfach als Parameter für den Rückruf und senden Sie es später zurück. Beachten Sie die val clickListener: (MyObject, Int) -> Unit
unten:
MyAdapter.kt
class MyAdapter constructor(objects: ArrayList<MyObject>, val clickListener: (MyObject, Int) -> Unit) : RecyclerView.Adapter<MyAdapter.Holder>() {
// Rest of the code...
Bei onBindViewHolder()
übergeben Sie die Position beim Aufruf der Callback-Methode:
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) }
}
Und auf MyActivity.kt müssen Sie die Einstellung des Adapters ändern, um die Position zu erhalten. So was:
myRecyclerView?.adapter = MyAdapter(mObjects) { itemDto: MyObject, position: Int ->
Log.e("MyActivity", "Clicked on item ${itemDto.someItemPropertyLikeName} at position $position")
}
Ich denke, die eleganteste Lösung besteht darin, diese Verantwortung RecyclerView zu übertragen und sie nicht anzusehen oder gar anzupassen.
dazu brauchen wir:
class RecyclerItemClickListener(private val mRecycler: RecyclerView, private val clickListener: OnClickListener? = null, private val longClickListener: OnLongClickListener? = 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?.onItemClick(position, v)
longClickListener?.onLongItemClick(position, v)
}
}
}
interface OnClickListener {
fun onItemClick(position: Int, view: View)
}
interface OnLongClickListener {
fun onLongItemClick(position: Int, view: View)
}
}
import Android.support.v7.widget.RecyclerView
import com.decathlon.manager.internal.common.RecyclerItemClickListener
fun RecyclerView.affectOnItemClick(listener: RecyclerItemClickListener.OnClickListener) {
this.addOnChildAttachStateChangeListener(RecyclerItemClickListener(this, listener, null))
}
fun RecyclerView.affectOnLongItemClick(listener: RecyclerItemClickListener.OnLongClickListener) {
this.addOnChildAttachStateChangeListener(RecyclerItemClickListener(this, null, listener))
}
fun RecyclerView.affectOnItemClicks(onClick: RecyclerItemClickListener.OnClickListener, onLongClick: RecyclerItemClickListener.OnLongClickListener) {
this.addOnChildAttachStateChangeListener(RecyclerItemClickListener(this, onClick, onLongClick))
}
import kotlinx.Android.synthetic.main.{your_layout_name}.*
class FragmentName : Fragment() {
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
recycler.affectOnItemClick(object : RecyclerItemClickListener.OnClickListener {
override fun onItemClick(position: Int, view: View) {
//todo
}
})
}
}
Sie können dies leicht erreichen, indem Sie eine Schnittstelle verwenden
class ExercisesAdapter constructor(val mItemClickListener: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{
mItemClickListener.onItemClick(adapterPosition)
}
view.setOnLongClickListener{
mItemClickListener.onLongClick(adapterPosition)
[email protected] true
}
}
}
}
Von Ihrer MainActivity
public class MainActivity : ActionBarActivity(), 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([email protected], "TEST: " + position, Toast.LENGTH_SHORT).show()
}
override fun onLongClick(position: Int) {
//do long click here
}
}
Sie könnten so etwas versuchen:
public class MainActivity : ActionBarActivity() {
protected override fun onCreate(savedInstanceState: Bundle?) {
[...]
val adapter = DrawAdapter(::onItemClick)
[...]
}
}
fun onItemClick(view: View, position: Int) {
//Do work
}
und SAM-Konvertierung funktioniert genauso wie in Java 8, verwenden Sie also einfach ein Lambda:
public class MainActivity : ActionBarActivity() {
protected override fun onCreate(savedInstanceState: Bundle?) {
[...]
val adapter = DrawAdapter({view, position -> /*Do work*/ })
[...]
}
}
RecyclerItemClickListener
package com.mypackage.custom
import Android.content.Context
import Android.support.v7.widget.RecyclerView
import Android.view.GestureDetector
import Android.view.MotionEvent
import Android.view.View
@Suppress("DEPRECATION")
class RecyclerItemClickListener(context: Context, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {
private var mGestureDetector: GestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapUp(e: MotionEvent): Boolean {
return true
}
})
interface OnItemClickListener {
fun onItemClick(view: View, position: Int)
}
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.getChildPosition(childView))
return true
}
return false
}
override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
Für Aktivität:
recyclerView!!.addOnItemTouchListener(
RecyclerItemClickListener(this!!, object : RecyclerItemClickListener.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
//Write your code here
}
})
Für Fragment:
recyclerView!!.addOnItemTouchListener(
RecyclerItemClickListener(this!!.activity!!, object : RecyclerItemClickListener.OnItemClickListener {
override fun onItemClick(view: View, position: Int) {
//Write your code here
}
})
Entschuldigung für die Verzögerung, Ich habe eine großartige Antwort von this link bekommen und es war in Java ..
Jetzt funktioniert es richtig .. Hier ist der Code,
Erstellen Sie eine Klasse mit dem Namen 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) {}}
und greifen Sie von Aktivität/Fragment aus auf
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")
}
}))
In RecyclerView können Sie die aufgeblasene Ansicht in der Klasse ViewHolder
anklicken und von der Methode onBindViewHolder
callback aufrufen. Beispiel:
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val view = view
val tv_message = view.tv_message
val tv_address = view.tv_address
fun bind(listViewItem: ListViewItem) {
view.setOnClickListener(View.OnClickListener {
Toast.makeText(
view.context,
"Name: " + listViewItem.name + "/n Address: " + listViewItem.address,
Toast.LENGTH_LONG).show()
})
}
}
}
Sie können die Adapter-Methode onBindViewHolder()
aufrufen:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val listViewItem: ListViewItem = mListViewItems[position]
holder.tv_message.text = listViewItem.name
holder.tv_address.text = listViewItem.address
holder.bind(mListViewItems[position]);
}
Adapterkonstruktor-Deklaration
class YourAdapter(private val mListener: (ItemObject) -> Unit) : RecyclerView.Adapter<ViewHolder>()
Adapter :: onBindViewHolder
holder.itemView.setOnClickListener {
mListener.invoke(item) // <- item instance of ItemObject
}
Wie benutzt man
mTypesWasteAdapter = YourAdapter({ it.something()})
Grundsätzlich erhalten Sie das ItemObject als it
im Lambda-Argument.
Zum Schluss noch eine schöne Lösung:
MyRecyclerAdapter.kt
class MyRecyclerAdapter(val context: Context, val items : ArrayList<Item>, val clickListener: (Int) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): RecyclerView.ViewHolder {
return MyViewHolder(LayoutInflater.from(context).inflate(R.layout.my_item, parent, false))
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as MyViewHolder).clickableView.setOnClickListener {
clickListener(position)
}
}
}
class MyViewHolder (view: View) : RecyclerView.ViewHolder(view) {
val clickableView = view.clickable_view
}
MainActivity.kt
fun appClickListener(position: Int) {
// You got the position of ArrayList
}
my_recyclerview.adapter = MyRecyclerAdapter(this, myList, clickListener = {
appClickListener(it)
})
Meine einfache Lösung, die die Funktion höherer Ordnung und die Bereichsfunktion let
verwendet, um den Listener nur festzulegen, wenn itemAction
festgelegt wurde
// Adapter
private var itemAction: ((Item) -> Unit)? = null
fun setItemAction(action: (Item) -> Unit) {
this.itemAction = action
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun setItem(item: Item) {
// ...
itemAction?.let {
itemView.setOnClickListener { it(item) }
}
}
}
und in Aktivität/Fragment
adapter.setItemAction { // <- it is Item
// do something with it
}
Sie müssen keine Erweiterungsfunktion für ViewHolder oder ähnliches schreiben.
Beste Übung; Verwenden Sie Funktion höherer Ordnung
class MainRecyclerAdapter(val news: JSONArray, private val itemClickListener: (Int) -> Unit) : RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder>() {}
Fügen Sie einfach eine Funktion höherer Ordnung hinzu. wie itemClickListener und gehen Sie dann zur ViewHolder-Klasse. Schreiben Sie diese Funktion als Parameter in Ihre Bindefunktion und setzen Sie diese auf itemView.
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bind(newsItem: JSONObject,itemClickListener:(Int)->Unit) {
//Some Stuff here..
itemView.setOnClickListener { itemClickListener(adapterPosition) }
}
}
Verwenden Sie diese Methode fürBindViewHolder
override fun onBindViewHolder(holder: MainRecyclerAdapter.ViewHolder, position: Int) {
holder.bind(news.getJSONObject(position),itemClickListener)
}
Und jetzt können Sie Ihre onClick-Funktion in jede Aktivität oder Fragmente schreiben. Geben Sie einfach einen Parameter an.
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)
OH, was zum Teufel könnte jemandem gefallen Wir stellen alle Bearbeitungs- und Mülleimer-Bilder in unser Recycling-Verzeichnis und möchten, dass etwas passiert, wenn sie angeklickt werden. Hier ist unser Kotlin-Beispiel
Dies ist eine Kartenansicht, die im Adapter aufgeblasen ist
<RelativeLayout
Android:id="@+id/editCLICK"
Android:layout_width="60dp"
Android:layout_height="60dp"
Android:layout_marginStart="370dp"
Android:paddingLeft="6dp"
Android:paddingRight="6dp"
Android:paddingTop="12dp">
<ImageView
Android:id="@+id/ivEdit"
Android:layout_width="30dp"
Android:layout_height="30dp"
Android:background="@color/color_Transparent"
Android:src="@drawable/ic_edit"
Android:tint="@color/color_lightBlue" />
</RelativeLayout>
dann machen wir im Adapter einige Bindungen
override fun onBindViewHolder(holder: ParentViewHolder, position: Int) {
val items = parentList[position]
holder.item.text = items.dept
holder.editCLICK.setOnClickListener {
val i = Intent(context, EnterParentActivity::class.Java)
i.putExtra("FROM", "U")
i.putExtra("MainActId",items.idD)
i.putExtra("PFK",items.fkD)
i.putExtra("ET",items.dept)
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(i)
}
}
inner class ParentViewHolder(view: View):RecyclerView.ViewHolder(view){
var item: TextView = view.findViewById(R.id.tvDept) as TextView
var editCLICK: RelativeLayout = view.findViewById(R.id.editCLICK) as RelativeLayout
}
Einfach schnell und zuverlässig genießen
Etwas anders, basierend auf denwehrle
Zur Verwendung in einem Fragment in OnCreateView
adapter.onItemClick = {it ->
//do something
}
Fügen Sie in der Adapterklasse hinzu:
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])
}
}
}
// Schritt 1 mache ein Interface wie
interface RecyclerViewClickListener {
fun onItemClick(position: String)
fun onLongClick(position: Int)
}
Schritt 2 Übergeben Sie in der Klasse Adapter ein weiteres Argument als Schnittstelle
class ModelAdapter(var item_list: ArrayList<UploadDocument>,var mItemClickListener:RecyclerViewClickListener) : RecyclerView.Adapter<ModelAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ModelAdapter.ViewHolder {
// create a new view
val view = LayoutInflater.from(parent.context).inflate(R.layout.upload_document_row_item, null)
// create ViewHolder
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ModelAdapter.ViewHolder, position: Int) {
holder.txtRegistrationDoc?.setText(item_list[position].getdocName())
holder.txtCertificate?.setText(item_list[position].getcertificateName())
holder.txtFileSize?.setText(item_list[position].getfileSize())
holder.txtCreatedOn?.setText(item_list[position].getcreatedOn())
holder.txtModifiedOn?.setText(item_list[position].getModifiedDate())
//holder.chkSelected.isChecked = item_list[position].isSelected()
holder.chkSelected.tag = item_list[position].getdocName()
holder. chkSelected!!.setOnCheckedChangeListener { buttonView, isChecked ->
if(isChecked)
{
System.out.println("position>>>"+buttonView.tag.toString())
mItemClickListener.onItemClick(buttonView.tag.toString())
}
}
//(context as UploadDocumentActivity::class.Java).onClickCalled("your argument here")
/* holder.btn_delete.setOnClickListener(object : View.OnClickListener() {
override fun onClick(v: View) {
deleteItemFromList(v, position)
}
})*/
}
override fun getItemCount(): Int {
return item_list.size
}
/*// confirmation dialog box to delete an unit
private fun deleteItemFromList(v: View, position: Int) {
val builder = AlertDialog.Builder(v.getContext())
//builder.setTitle("Dlete ");
builder.setMessage("Delete Item ?")
.setCancelable(false)
.setPositiveButton("CONFIRM",
DialogInterface.OnClickListener { dialog, id ->
item_list.remove(position)
notifyDataSetChanged()
})
.setNegativeButton("CANCEL", DialogInterface.OnClickListener { dialog, id -> })
builder.show()
}*/
class ViewHolder(
itemLayoutView: View) : RecyclerView.ViewHolder(itemLayoutView) {
var item_name: TextView
var txtRegistrationDoc: TextViewNormal?=null
var txtCertificate: TextViewNormal?=null
var txtFileSize: TextViewNormal?=null
var txtCreatedOn: TextViewNormal?=null
var txtModifiedOn: TextViewNormal?=null
var chkSelected: CheckBox
init {
item_name = itemLayoutView.findViewById(R.id.txt_Name)
txtRegistrationDoc = itemLayoutView.findViewById(R.id.txtRegistrationDoc)
txtCertificate = itemLayoutView.findViewById(R.id.txtCertificate)
txtFileSize = itemLayoutView.findViewById(R.id.txtFileSize)
txtCreatedOn = itemLayoutView.findViewById(R.id.txtCreatedOn)
txtModifiedOn = itemLayoutView.findViewById(R.id.txtModifiedOn)
//btn_delete = itemLayoutView.findViewById(R.id.btn_delete_unit)
chkSelected = itemLayoutView.findViewById(R.id.chk_selected)
}
}
}
// Schritt 3 In deiner Aktivität/Frgament
recyclerView?.adapter = ModelAdapter(documentList,object : `in`.mobilepedia.com.gicgwaliarincubationcentre.RecyclerViewClickListener
{
override fun onItemClick(position: String) {
System.out.println("Position>>>>>"+position)
}
override fun onLongClick(position: Int) {
}
})
Sie können OnClickListener direkt im Adapter deklarieren und eine Umleitung vornehmen, und zweitens können Sie Ihren Onclick auf Fragment/Aktivität umleiten, an der Sie den Recycleradapter festgelegt haben
1.
class CartAdapter(context: Context) : RecyclerView.Adapter<CartAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_cart, parent, false));
}
override fun getItemCount(): Int {
return 10;
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.rtbProductRating.setOnClickListener{
var iNavigation= Intent(context,MainActivity::class.Java)
iNavigation.flags= Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
context.startActivity(iNavigation)
// directly redirect your activity from adapter
}
}
class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView)
}
Die zweite Möglichkeit besteht darin, Ihren Adapter umzuleiten, indem Sie auf Fragmentieren/Aktivität klicken und dann Ihre Aktivität von dort aus umleiten, anstatt vom Adapter umzuleiten
class CartAdapter(context: Context, onClickListener: View.OnClickListener) : RecyclerView.Adapter<CartAdapter.ViewHolder>() {
var context = context
var onClickListener = onClickListener
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_cart, parent, false));
}
override fun getItemCount(): Int {
return 10;
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//set your position to the view
holder.itemView.rtbProductRating.tag = position
//redirect click to the fragment
holder.itemView.rtbProductRating.setOnClickListener {
onClickListener.onClick(holder.itemView.rtbProductRating)
}
// holder.itemView.tv_waybill_count.text = holder.itemView.context.getString(R.string.waybills,5)
}
class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView)
}
Your fragment will look like:
class CartFragment: BaseFragment(),View.OnClickListener {
override val layout= R.layout.frg_cart
override fun onClick(v: View?) {
var position=v?.tag as Int
if(position==0){
var iNavigation= Intent(this,MainActivity::class.Java)
iNavigation.flag=Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
startActivity(iNavigation)
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
listener()
}
private fun listener() {
cart_rv.adapter=CartAdapter(activity,this)
}
}
Füge ClickListener-Code bei onBindViewHolder hinzu
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
}
Hier ist meine MainActivity.kt-Klasse, die Recyclerview zum Auffüllen von Standortdaten verwendet. Es verfügt über eine einfache Element-Listener-Schnittstelle, die Sie implementieren können.
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: RecyclerView.Adapter<*>
private lateinit var viewManager: RecyclerView.LayoutManager
private var locationArrayList = arrayListOf<Location>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//create locations
var ny = Location("New York")
var la = Location("Los Angeles")
locationArrayList.addAll(listOf(ny, la))
viewManager = LinearLayoutManager(this)
viewAdapter = LocationsAdapter(locationArrayList)
recyclerView = findViewById<RecyclerView>(R.id.recyclerView).apply {
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
setHasFixedSize(true)
// use a linear layout manager
layoutManager = viewManager
// specify an viewAdapter
adapter = viewAdapter
}
//recycler view click listener implement
recyclerView.addOnItemClickListener(object: OnItemClickListener {
override fun onItemClicked(position: Int, view: View) {
// Your logic
Toast.makeText([email protected], locationArrayList[position].locationName, Toast.LENGTH_SHORT).show()
}
})
}
//on item click interface
interface OnItemClickListener {
fun onItemClicked(position: Int, view: View)
}
fun RecyclerView.addOnItemClickListener(onClickListener: OnItemClickListener) {
this.addOnChildAttachStateChangeListener(object: RecyclerView.OnChildAttachStateChangeListener {
override fun onChildViewDetachedFromWindow(view: View?) {
view?.setOnClickListener(null)
}
override fun onChildViewAttachedToWindow(view: View?) {
view?.setOnClickListener({
val holder = getChildViewHolder(view)
onClickListener.onItemClicked(holder.adapterPosition, view)
})
}
})
}
//end of interface
}
Ich habe mir diese Lösung ausgedacht, um eine Aktivität zu öffnen, wenn auf eine Zeile geklickt wird, und zwar mithilfe eines Begleitobjekts und einer zugehörigen Benutzeroberfläche. Die Aktivität wird über die Hauptaktivität geöffnet, da ich vor dem Verlassen den Listenstatus speichern musste.
Adapter
class MyAdapter(
val dataList: List<objects.ListObject>, val listener: ItemClickListener
) : RecyclerView.Adapter<MyAdapter.ListViewHolder>()
{
companion object {
var mClickListener: ItemClickListener? = null
}
interface ItemClickListener
{
fun clickRow(position: Int)
}
override fun onBindViewHolder(holder: MyAdapter.ListViewHolder, position: Int)
{
holder.bindData(
...
)
mClickListener = listener
holder.itemView.setOnClickListener { view ->
mClickListener?.clickRow(position)
}
}
...
}
Haupttätigkeit
val context = this
private lateinit var mMyAdapter: MyAdapter
fun initList()
{
mMyAdapter =
MyAdapter(dataList, object : MyAdapter.ItemClickListener
{
override fun clickRow(position: Int)
{
openActivityListItems(position)
}
}
)
}
fun openActivityListItems(position : Int)
{
recyclerViewState = mListView.getLayoutManager()?.onSaveInstanceState()
val intent = Intent(context, ListItems::class.Java)
intent.putExtra("Parameter1", dataList[position].Parameter1)
intent.putExtra("Parameter2", dataList[position].Parameter2)
context.startActivity(intent)
}
Wenn sich jemand für die alte Art der Umsetzung interessiert ..
Ich habe ein vollständiges Beispiel veröffentlicht, das auch Ihren Adaptercode reduziert. Es verwendet das alte Muster des Callbacks.
Grad der Projektebene
buildscript {
ext.kotlin_version = '1.3.10'
repositories {
google()
mavenCentral()
jcenter()
}
dependencies {
classpath 'com.Android.tools.build:gradle:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-Android-extensions:$kotlin_version"//newly added
classpath 'com.google.gms:google-services:4.1.0' // google-services plugin
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Applevel Gradle
apply plugin: 'com.Android.application'
apply plugin: 'kotlin-Android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-Android-extensions'
apply plugin: 'org.jetbrains.kotlin.Android.extensions'//it is used for @Percelize
Android {
compileSdkVersion 28
dataBinding {
enabled = true
}
androidExtensions {
experimental = true
}
defaultConfig {
applicationId 'broadpeak.firebase.learning'
minSdkVersion 19
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "Android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}
}
/*kapt {
generateStubs = true
}*/
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.Android.support:appcompat-v7:28.0.0'
implementation 'com.Android.support:design:28.0.0'
implementation 'com.Android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.firebase:firebase-core:16.0.5'
implementation 'com.google.firebase:firebase-firestore:17.1.3'
implementation 'com.google.firebase:firebase-auth:16.0.5'
implementation 'com.google.firebase:firebase-messaging:17.3.4'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.firebaseui:firebase-ui-auth:4.1.0'
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
////kapt "com.Android.databinding:compiler:$Android_plugin_version"\ // not required above 3.2.0
///kapt "com.Android.databinding:compiler:3.1.4"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.Android.support.test:runner:1.0.2'
androidTestImplementation 'com.Android.support.test.espresso:espresso-core:3.0.2'
}
// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'
SubjectListActivity.class
class SubjectListActivity : BaseActivity() {
var subjects = mutableListOf<SubjectBO>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.question_list_activity)
recycler_view.itemAnimator = DefaultItemAnimator()
recycler_view.setHasFixedSize(true)
recycler_view.layoutManager = LinearLayoutManager([email protected])
db.collection("tagCollection").get().addOnSuccessListener { querySnapshot ->
if (querySnapshot.isEmpty()) {
Log.d(TAG, "onSuccess: LIST EMPTY")
} else {
// Convert the whole Query Snapshot to a list
// of objects directly! No need to fetch each document.
subjects = querySnapshot.toObjects(SubjectBO::class.Java)
if(subjects.size > 0){
recycler_view.adapter = SubjectAdapter(subjects, object : OnRecyclerItemClickListener {
override fun onItemClicked(view: View?, position: Int) {
var intent = Intent([email protected],McqActivity::class.Java)
intent.putExtra("keyTagBO",subjects.get(position))
startActivity(intent)
}
});
}
}
}.addOnFailureListener { exception ->
exception.printStackTrace()
}
}
SubjectAdapter.class
class SubjectAdapter(items: List<SubjectBO>, onRecyclerItemClickListener: OnRecyclerItemClickListener)
: BaseAdapter<SubjectBO, SubjectViewHolder>(items, onRecyclerItemClickListener) {
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): SubjectViewHolder {
return SubjectViewHolder(parent, R.layout.item_subject, onRecyclerItemClickListener)
}
}
SubjectViewHolder.class
class SubjectViewHolder(parent: ViewGroup, itemLayoutId: Int, onRecyclerItemClickListener:
OnRecyclerItemClickListener) : BaseViewHolder<SubjectBO>(parent, itemLayoutId, onRecyclerItemClickListener) {
override fun bindData(data: SubjectBO) {
itemView.tvTitle.setText(data.tagName)
}
}
BaseAdapter.class
abstract class BaseAdapter<T, U : BaseViewHolder<T>>
(var items: List<T>, var onRecyclerItemClickListener: OnRecyclerItemClickListener)
: RecyclerView.Adapter<U>() {
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: U, pos: Int) {
holder.bindData(items.get(pos))
}
}
BaseViewHolder.class
abstract class BaseViewHolder<T : BaseModel>(parent: ViewGroup, @LayoutRes itemLayoutId: Int,
var onRecyclerItemClickListener: OnRecyclerItemClickListener) :
RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(itemLayoutId, parent,
false)), View.OnClickListener {
override fun onClick(v: View?) {
onRecyclerItemClickListener.onItemClicked(v, adapterPosition)
}
abstract fun bindData(data: T)
init {
itemView.setOnClickListener(this)
}
}
OnRecyclerItemClickListener.class
interface OnRecyclerItemClickListener{
fun onItemClicked(view: View?, position: Int)
}