0

Ich baue einen ViewHolder und Adapter für ein Fragment und wenn ich versuche, ein OnClick für den ViewHolder zu machen, funktioniert keiner der Kontexte, die ich übergebe. Es gibt keine activity von getActivity(), die ich verwenden kann, und p0!!.context noch itemView.context arbeiten entweder. Woher soll ich meinen Kontext bekommen und wie referenziere ich ihn? Vielen Dank!getActivity()/Kontext in einem ViewHolder in Kotlin Andorid

package com._________.criminalintent 

import android.os.Bundle 
import android.support.v4.app.Fragment 
import android.support.v7.widget.LinearLayoutManager 
import android.support.v7.widget.RecyclerView 
import android.view.LayoutInflater 
import android.view.View 
import android.view.ViewGroup 
import android.widget.TextView 
import android.widget.Toast 

class CrimeListFragment: Fragment() { 
    private var mCrimeRecyclerView: RecyclerView? = null 
    private var mAdapter: CrimeAdapter? = null 

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { 
    // fragment_crime_list.xml has a RecyclerView element = crime_recycler_view 
    // inflate the fragment into the activity 
     val view = inflater!!.inflate(R.layout.fragment_crime_list, container, false) 

     // grab the recyclerView and give it a required layoutManager 
     mCrimeRecyclerView = view.findViewById(R.id.crime_recycler_view) 
     mCrimeRecyclerView!!.layoutManager = LinearLayoutManager(activity) 
     updateUI() 
     return view 
    } 

    private fun updateUI() { 
     val crimeLab = CrimeLab.get(activity) 
     val crimes = crimeLab.getCrimes() 
     mAdapter = CrimeAdapter(crimes) 
     // Connect the adapter to the recyclerView 
     mCrimeRecyclerView!!.adapter = mAdapter 
    } 

    /** 
    * in Kotlin, we must give the view passed into the constructor directly 
    * as a substitute for a super() call 
    * 
    * create a ViewHolder that holders the crime list item's view 
    * 
    * super(itemView) = super(inflater!!.inflate(R.layout.list_item_crime, parent, false)) 
    * MUST give it the direct value in Kotlin 
    */ 
    private class CrimeHolder(inflater: LayoutInflater?, parent: ViewGroup): 
     RecyclerView.ViewHolder(inflater!!.inflate(R.layout.list_item_crime, parent, false)), 
     View.OnClickListener { 

     private var mCrime: Crime? = null 

     /** 
     * When given a crime, this CrimeHolder will update the title and date for this Crime 
     */ 
     fun bind(crime: Crime) { 
      mCrime = crime 
      val titleTextView = itemView.findViewById<TextView>(R.id.crime_title) 
      val dateTextView = itemView.findViewById<TextView>(R.id.crime_date) 
      titleTextView.text = mCrime!!.mTitle 
      dateTextView.text = mCrime!!.mDate.toString() 
     } 

     override fun onClick(p0: View?) { 

      Toast.makeText(WHAT_TO_PUT_HERE, "${mCrime!!.mTitle} clicked!", Toast.LENGTH_SHORT/2) 
       .show() 
    } 
} 


    private class CrimeAdapter(private var mCrimes: MutableList<Crime>): 
     RecyclerView.Adapter<CrimeHolder>() { 

     /** 
     * - Calls our CrimeHolder to make our custom ViewHolders 
     * - Called by RecyclerView when it needs a new view to display 
     * - Gets the layoutInflater from the ViewGroup and returns a CrimeHolder of it 
     */ 
     override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): CrimeHolder 
     = CrimeHolder(LayoutInflater.from(parent!!.context), parent) 


     /** 
     * Bind the crime (data) to the CrimeHolder 
     */ 
     override fun onBindViewHolder(holder: CrimeHolder?, position: Int) { 
      holder!!.bind(mCrimes[position]) 
     } 

     /** 
     * Sees how many items are in the RecyclerView that need to be shown 
     */ 
     override fun getItemCount(): Int = mCrimes.size 
    } 
} 
+2

Ich weiß, das ist kein Code-Review, aber hier ist meine 2 Cent. Wenn Sie Ihre Ansichten als 'Late-In-Var 'einstellen, brauchen Sie nicht die' '' '' überall. –

+0

Heiliger Mist. Wie habe ich das nie gewusst ... Danke! – user3338275

+0

Sprechen Sie über 2 Cent, verwenden Sie immer den engsten Kontext. Sie benötigen Kontext für einen Layout-Manager? Verwenden Sie 'recyclerView.context'. /// 'in' onCreateView ist nie null. 'container' darf null sein. /// Setze keinen Kontext in 'CrimeHolder'! View-Halter können auf ihr "itemView" und damit auf "itemView.context" zugreifen. –

Antwort

1

in Ihrer Implementierung können Sie sicher verwenden Context von View zu Ihrer Verfügung gestellt OnClickListener

override fun onClick(p0: View) { 
      Toast.makeText(p0.context, "${mCrime!!.mTitle} clicked!", Toast.LENGTH_SHORT/2) 
       .show() 
    } 

Denken Sie daran Onclick zu setzen:

fun bind(crime: Crime) { 
      mCrime = crime 
      val titleTextView = itemView.findViewById<TextView>(R.id.crime_title) 
      val dateTextView = itemView.findViewById<TextView>(R.id.crime_date) 
      titleTextView.text = mCrime!!.mTitle 
      dateTextView.text = mCrime!!.mDate.toString() 
      itemView.setOnClickListener(this) 
} 

Außerdem alle Kotlin Klassen verschachtelt sind (static) standardmäßig aktiviert. Ihre private class CrimeHolder entspricht also private static class CrimeHolder in Java. Deshalb haben Sie keinen Zugriff auf getActivity() von innerhalb CrimeHolder

+0

Der 'setOnClickListener' hat funktioniert! Also, unabhängig davon, ob ich ein onClick habe, muss ich onClick für die Ansicht einstellen. Warum wird "das" weitergegeben? Und ich dachte, statisch ist das Kotlin-Äquivalent des Begleiterobjekts. – user3338275

+0

'val titleTextView = itemView.findViewById (R.id.crime_title)' und solche sollten direkt auf dem Ansichtshalter * nicht lokal definiert werden, wenn der Ansichtshalter gebunden ist *. Das vereitelt den ganzen Zweck des View Holders - Caching gefundener Ansichten. –

+0

@EugenPechanec danke, das macht sehr viel Sinn. – user3338275

1

Verwenden Sie itemView.context Eigenschaft in Ihrem Halter.

Edit: Der Grund, warum Ihre onClick nicht „Arbeit“ (nicht genannt wird) ist, weil Sie nicht die onClickListener registriert haben, zum Beispiel:

itemView.setOnClickListener(this) 

in Ihrem Halter init oder bind.

+0

Entschuldigung, ich habe mich vertippt, das war eine, die ich vorher probiert habe. – user3338275

+0

@ user3338275 siehe bearbeitete Antwort. Sie haben Ihren OnClickListener nirgendwo festgelegt. – maciekjanusz

Verwandte Themen