web-dev-qa-db-ja.com

getActivity()/ KotlinのViewHolderのコンテキストAndroid

フラグメントのViewHolderとアダプタを作成しています。ViewHolderのOnClickを作成しようとすると、渡したコンテキストが機能しません。使用できるgetActivity()からのactivityはなく、p0!!.contextitemView.contextどちらでも機能します。どこからコンテキストを取得し、どのように参照するのですか?

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
    }
}
5
user3338275

実装では、Contextに提供されているViewからOnClickListenerを安全に使用できます

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

Onclickを設定することを忘れないでください。

_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)
}
_

さらに、すべてのKotlinクラスはデフォルトでネストされています(static)。したがって、あなたの_private class CrimeHolder_はJavaの_private static class CrimeHolder_と同等です。 CrimeHolder内からgetActivity()にアクセスできないのはそのためです

6
rafal

使用する itemView.contextホルダー内のプロパティ。

編集:onClickが「機能しない」(呼び出されない)理由は、onClickListenerを登録していないためです。次に例を示します。

itemView.setOnClickListener(this)

ホルダーの内側initまたはbind

1
maciekjanusz
 itemView.setOnClickListener {
                Toast.makeText(itemView.context, "Item is clicked $position", Toast.LENGTH_SHORT).show() }
        }
0
HandyPawan