how - "No hay suficiente información para inferir el parámetro T" con Kotlin y Android
toolbar android text (5)
Andoid O change findViewById api de
vista pública findViewById (int id);
a
public final T findViewById (int id)
entonces, si está dirigido a la API 26, puede cambiar
val listView = findViewById (R.id.list) como ListView
a
val listView = findViewById (R.id.list)
o
val listView: ListView = findViewById (R.id.list)
Estoy tratando de replicar el siguiente ListView en mi aplicación de Android usando Kotlin: https://github.com/bidrohi/KotlinListView .
Lamentablemente recibo un error que no puedo resolver por mí mismo. Aquí está mi código:
MainActivity.kt:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listView = findViewById(R.id.list) as ListView
listView.adapter = ListExampleAdapter(this)
}
private class ListExampleAdapter(context: Context) : BaseAdapter() {
internal var sList = arrayOf("Eins", "Zwei", "Drei")
private val mInflator: LayoutInflater
init {
this.mInflator = LayoutInflater.from(context)
}
override fun getCount(): Int {
return sList.size
}
override fun getItem(position: Int): Any {
return sList[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
val view: View?
val vh: ListRowHolder
if(convertView == null) {
view = this.mInflator.inflate(R.layout.list_row, parent, false)
vh = ListRowHolder(view)
view.tag = vh
} else {
view = convertView
vh = view.tag as ListRowHolder
}
vh.label.text = sList[position]
return view
}
}
private class ListRowHolder(row: View?) {
public val label: TextView
init {
this.label = row?.findViewById(R.id.label) as TextView
}
}
}
Los diseños son exactamente como aquí: https://github.com/bidrohi/KotlinListView/tree/master/app/src/main/res/layout
El mensaje de error completo que recibo es este: Error: (92, 31) Error en la inferencia de tipos: No hay suficiente información para inferir el parámetro T en diversión findViewById (p0: Int): T! Por favor especifíquelo explícitamente.
Agradecería cualquier ayuda que pueda obtener.
Cambia tu código a esto. Donde ocurrieron los principales cambios están marcados con asteriscos.
package com.phenakit.tg.phenakit
import android.content.Context
import android.os.Bundle
import android.support.design.widget.BottomNavigationView
import android.support.v7.app.AppCompatActivity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ListView
import android.widget.TextView
public class MainActivity : AppCompatActivity() {
private var mTextMessage: TextView? = null
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
mTextMessage!!.setText(R.string.title_home)
return@OnNavigationItemSelectedListener true
}
R.id.navigation_dashboard -> {
mTextMessage!!.setText(R.string.title_dashboard)
return@OnNavigationItemSelectedListener true
}
R.id.navigation_notifications -> {
setContentView(R.layout.activity_list_view)
return@OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mTextMessage = findViewById(R.id.message) as TextView?
val navigation = findViewById(R.id.navigation) as BottomNavigationView
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
**val listView = findViewById<ListView>(R.id.list)**
**listView?.adapter = ListExampleAdapter(this)**
}
private class ListExampleAdapter(context: Context) : BaseAdapter() {
internal var sList = arrayOf("Eins", "Zwei", "Drei")
private val mInflator: LayoutInflater
init {
this.mInflator = LayoutInflater.from(context)
}
override fun getCount(): Int {
return sList.size
}
override fun getItem(position: Int): Any {
return sList[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
val view: View?
val vh: ListRowHolder
if(convertView == null) {
view = this.mInflator.inflate(R.layout.list_row, parent, false)
vh = ListRowHolder(view)
view.tag = vh
} else {
view = convertView
vh = view.tag as ListRowHolder
}
vh.label.text = sList[position]
return view
}
}
private class ListRowHolder(row: View?) {
public var label: TextView
**init { this.label = row?.findViewById<TextView?>(R.id.label) as TextView }**
}
}
Debe estar utilizando el nivel de API 26 (o superior).
Esta versión ha cambiado la firma de
View.findViewById()
- vea aquí
https://developer.android.com/preview/api-overview.html#fvbi-signature
Entonces, en su caso, donde el resultado de
findViewById
es ambiguo, debe proporcionar el tipo:
1 / Cambiar
val listView = findViewById(R.id.list) as ListView
para
val listView = findViewById<ListView>(R.id.list)
2 / Cambiar
this.label = row?.findViewById(R.id.label) as TextView
para
this.label = row?.findViewById<TextView>(R.id.label) as TextView
Tenga en cuenta que en 2 / la conversión solo es necesaria porque la
row
es anulable.
Si la
label
fuera anulable, o si hiciera que la
row
no fuera anulable, no sería necesario.
Te sugiero que uses la extensión de Android Kotlin de Synthetics:
https://kotlinlang.org/docs/tutorials/android-plugin.html
https://antonioleiva.com/kotlin-android-extensions/
En su caso, el código será algo como esto:
init {
this.label = row.label
}
Tan sencillo como eso ;)
Esta funcionando
El nivel de API 25 o inferior usa esto
var et_user_name = findViewById(R.id.et_user_name) as EditText
Nivel API 26 o superior use esto
val et_user_name: EditText = findViewById(R.id.et_user_name)
¡Feliz codificación!