Llegamos a algo imprescindible en el desarrollo de aplicaciones móviles, las listas. Antaño se usaban ListView en android, pero con el tiempo Google sacó las RecyclerView, listas más customizables, potentes y eficientes.
Configurando nuestro proyecto
Lo primero que haremos será crear un nuevo proyecto o podemos usar el del capítulo anterior, pues reutilizaremos código de ahí.
Una vez creado iremos al build.gradle del módulo app e implementaremos una dependencia. Una dependencia es básicamente código externo del proyecto el cual podemos implementar para aprovecharlo, en este caso implementaremos el Recyclerview que por defecto no lo trae.
Así que vamos a la parte de las dependencies{} y añadimos
implementation 'com.android.support:recyclerview-v7:25.0.0'
Y también añadiremos una librería llamada Picasso que la usaremos para la gestión de imágenes.
implementation 'com.squareup.picasso:picasso:2.5.2'
Nos aparecerá en la parte superior una barra que nos dirá que es necesario sincronizar el gradle, así que le damos. Si todo sale bien ya tendremos esta parte configurada, si te da error de sdk posiblemente es que tengas varias versiones diferentes (CompileSDKVersion, buildToolsVersion…) todas a 25. Debería quedar así.
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 25 buildToolsVersion "25.0.0" defaultConfig { applicationId "com.cursokotlin.dataclasskotlin" //Nombre de nuestra app minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) androidTestImplementation ('com.android.support.test.espresso:espresso-core:3.0.0', { exclude group: 'com.android.support', module: 'support-annotations' }) implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation 'com.android.support:appcompat-v7:25.4.0' testImplementation 'junit:junit:4.12' implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support:recyclerview-v7:25.0.0' implementation 'com.squareup.picasso:picasso:2.5.2' }
Editando nuestra layout y creando una celda
El layout principal será el contenedor del RecyclerView, pero luego para inflarlo tendremos que crear un adapter (hablaremos de él un poco más abajo) y una celda que será la que muestre cada una de las filas de la lista.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rvSuperheroList" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout>
En este ejemplo seguiremos con los objetos superhéroe del capítulo anterior así que la celda que hagamos llevará un ImageView para el logo del superhéroe y tres textos, uno para el nombre real, el nombre de superhéroe y el de la compañía (DC o Marvel). Vamos a res/layout y creamos un archivo llamado item_superhero_list.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp"> <ImageView android:id="@+id/ivAvatar" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginEnd="10dp" android:layout_marginRight="10dp" android:scaleType="centerCrop" /> <TextView android:id="@+id/tvSuperhero" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" android:textSize="20sp" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/ivAvatar" android:layout_toEndOf="@+id/ivAvatar" tools:text= "dadawdawdwd" /> <TextView android:id="@+id/tvRealName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="15sp" android:layout_below="@+id/tvSuperhero" android:layout_toRightOf="@+id/ivAvatar" android:layout_toEndOf="@+id/ivAvatar" tools:text = "wdawd"/> <TextView android:id="@+id/tvPublisher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="italic" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" tools:text = "DC"/> </RelativeLayout>
Si no me equivoco todos los atributos de arriba ya los hemos visto excepto los «tools:text» la función tools lo que hace es ayudarnos a ver algo de un modo más sencillo. Aquí por ejemplo está poniendo un texto para poder ir maquetando mejor la vista, pero cuando compile la aplicación, ese texto no estará, así que podríamos decir que es un molde. Si tenéis alguna otra duda podéis dejar un comentario.
Ahora vamos a crear un modelo superhéroe del cual haremos varias listas para cargar en el recyclerview, como esto ya está hecho en el capítulo anterior solo os voy a dejar la clase aquí para que la copien.
data class Superhero( var superhero:String, var publisher:String, var realName:String, var photo:String )
Creando nuestros objetos superhéroes
Volvemos a MainActivity.kt y vamos a crear dos funciones, una que configurará nuestro recyclerview con el adapter y otra que generará la lista de objetos superhéroes.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setUpRecyclerView() } fun setUpRecyclerView(){ ... } fun getSuperheros(): MutableList<Superhero>{ var superheros:MutableList<Superhero> = ArrayList() superheros.add(Superhero("Spiderman", "Marvel", "Peter Parker", "https://cursokotlin.com/wp-content/uploads/2017/07/spiderman.jpg")) superheros.add(Superhero("Daredevil", "Marvel", "Matthew Michael Murdock", "https://cursokotlin.com/wp-content/uploads/2017/07/daredevil.jpg")) superheros.add(Superhero("Wolverine", "Marvel", "James Howlett", "https://cursokotlin.com/wp-content/uploads/2017/07/logan.jpeg")) superheros.add(Superhero("Batman", "DC", "Bruce Wayne", "https://cursokotlin.com/wp-content/uploads/2017/07/batman.jpg")) superheros.add(Superhero("Thor", "Marvel", "Thor Odinson", "https://cursokotlin.com/wp-content/uploads/2017/07/thor.jpg")) superheros.add(Superhero("Flash", "DC", "Jay Garrick", "https://cursokotlin.com/wp-content/uploads/2017/07/flash.png")) superheros.add(Superhero("Green Lantern", "DC", "Alan Scott", "https://cursokotlin.com/wp-content/uploads/2017/07/green-lantern.jpg")) superheros.add(Superhero("Wonder Woman", "DC", "Princess Diana", "https://cursokotlin.com/wp-content/uploads/2017/07/wonder_woman.jpg")) return superheros } }
Aunque la clase no está terminada, quería que vieran el modelo de superhéroe creado, para que ahora entiendan mejor que vamos a hacer en el adapter.
Creando el adapter
Ahora vamos a crear el adapter del Recyclerview. Un adapter es la clase que hace de puente entre la vista (el recyclerview) y los datos. Así que creamos una nueva clase llamada RecyclerAdapter.kt
La clase RecyclerAdapter se encargará de recorrer la lista de superhéroes que le pasaremos más tarde, y llamando a otra clase interna que tendrá, este rellenará los campos.
Vamos a ir viendo método por método, así que hasta el final de la explicación la clase tendrá fallos.
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() { var superheros: MutableList<Superhero> = ArrayList() lateinit var context:Context ... }
Lo primero que hacemos es decirle a la clase que tendrá un RecyclerAdapter y un ViewHolder. Después creamos las dos variables que necesitamos para el adapter, una lista de superhéroes (que rellenaremos en la clase principal y se la mandaremos aquí y el contexto de la mainAcitivity para poder trabajar con la librería Picasso.
fun RecyclerAdapter(superheros : MutableList<Superhero>, context: Context){ this.superheros = superheros this.context = context } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = superheros.get(position) holder.bind(item, context) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val layoutInflater = LayoutInflater.from(parent.context) return ViewHolder(layoutInflater.inflate(R.layout.item_superhero_list, parent, false)) } override fun getItemCount(): Int { return superheros.size }
Lo primero es un simple constructor (tiene el mismo nombre que la clase y lo único que hará será recibir la lista y el contexto que le pasamos desde la clase principal).
Los siguientes tres métodos tienen delante la palabra reservada override, esto es porque son métodos obligatorios que se implementan de la clase RecyclerView. onBindViewHolder() se encarga de coger cada una de las posiciones de la lista de superhéroes y pasarlas a la clase ViewHolder(todavía no está hecha) para que esta pinte todos los valores.
Después tenemos onCreateViewHolder() que como su nombre indica lo que hará será devolvernos un objeto ViewHolder al cual le pasamos la celda que hemos creado.
Y para finalizar el método getItemCount() nos devuelve el tamaño de la lista, que lo necesita el RecyclerView.
Para finalizar el adapter queda hacer la clase ViewHolder de la que tanto hemos hablado. No es necesaria hacerla dentro del adapter, pero como van tan ligadas la una a la otra creo que es lo mejor.
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val superheroName = view.findViewById(R.id.tvSuperhero) as TextView val realName = view.findViewById(R.id.tvRealName) as TextView val publisher = view.findViewById(R.id.tvPublisher) as TextView val avatar = view.findViewById(R.id.ivAvatar) as ImageView fun bind(superhero:Superhero, context: Context){ superheroName.text = superhero.superhero realName.text = superhero.realName publisher.text = superhero.publisher itemView.setOnClickListener(View.OnClickListener { Toast.makeText(context, superhero.superhero, Toast.LENGTH_SHORT).show() }) avatar.loadUrl(superhero.photo) } fun ImageView.loadUrl(url: String) { Picasso.with(context).load(url).into(this) } }
Lo primero que hace esta clase es hacer referencia a los items de la celda, el view.findViewByID() busca los items a través de la id que le ponemos, y luego añadimos el as X donde X es el tipo del componente (ImageView, TextView…).
Dentro tiene el método bind(superhero:Superhero, context: Context) que dicho método lo llamamos desde el onBindViewHolder() para que rellene los datos. Después de añadir todos los textos que queremos, hacemos 2 cositas más. La primera es que llamamos a itemView que es la vista (celda) que estamos rellenando y le ponemos un setOnClickListener que pintará en pantalla el nombre del superhéroe en el que hemos hecho click. Y para finalizar seleccionamos el ImageView y con el método que hemos creado le pasamos la URL de la imagen. Esta url la usará Picasso para descargarla de internet y pintarla en nuestra lista. Pero para que Picasso pueda hacer eso, debemos ponerle permiso de internet a nuestra app.
Vamos a AndroidManifest.xml y añadimos el permiso después de abrir la etiqueta manifest.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cursokotlin.dataclasskotlin"> <uses-permission android:name="android.permission.INTERNET" /> //Pedimos permiso de internet <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Y nuestro adapter completo sería así.
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() { var superheros: MutableList<Superhero> = ArrayList() lateinit var context:Context fun RecyclerAdapter(superheros : MutableList<Superhero>, context: Context){ this.superheros = superheros this.context = context } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = superheros.get(position) holder.bind(item, context) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val layoutInflater = LayoutInflater.from(parent.context) return ViewHolder(layoutInflater.inflate(R.layout.item_superhero_list, parent, false)) } override fun getItemCount(): Int { return superheros.size } class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val superheroName = view.findViewById(R.id.tvSuperhero) as TextView val realName = view.findViewById(R.id.tvRealName) as TextView val publisher = view.findViewById(R.id.tvPublisher) as TextView val avatar = view.findViewById(R.id.ivAvatar) as ImageView fun bind(superhero:Superhero, context: Context){ superheroName.text = superhero.superhero realName.text = superhero.realName publisher.text = superhero.publisher avatar.loadUrl(superhero.photo) itemView.setOnClickListener(View.OnClickListener { Toast.makeText(context, superhero.superhero, Toast.LENGTH_SHORT).show() }) } fun ImageView.loadUrl(url: String) { Picasso.with(context).load(url).into(this) } } }
Ahora volvemos al MainActivity.kt para finalizar el método que nos queda. Primero crearemos dos variables, la del RecyclerView y la del adapter que acabamos de terminar.
lateinit var mRecyclerView : RecyclerView val mAdapter : RecyclerAdapter = RecyclerAdapter()
El recyclerview lo tenemos que instanciar en el método setUpRecyclerView() por lo que tenemos que ponerle la propiedad lateinit a la variable, indicándole a Kotlin que la instanciaremos más tarde.
fun setUpRecyclerView(){ mRecyclerView = findViewById(R.id.rvSuperheroList) as RecyclerView mRecyclerView.setHasFixedSize(true) mRecyclerView.layoutManager = LinearLayoutManager(this) mAdapter.RecyclerAdapter(getSuperheros(), this) mRecyclerView.adapter = mAdapter }
Para finalizar creamos el método, lo primero que hará será buscar en el layout el Recycler y asignarselo a la variable que creamos. El siguiente método se usa para evitar problemas cuando el padre que contiene la lista cambia y puede estropear el recycler.
Luego llamamos a nuestro adapter y le pasamos los campos que necesite, en este caso getSuperheros (que devuelve una lista de superhéroes) y this (el contexto). Y para finalizar se lo asignamos a el recyclerview.
Ahora solo necesitamos compilar para ver el resultado de nuestra aplicación.
Continúa con el curso: Capítulo 16 – Persistencia de datos con Shared Preferences
Me ha gustado este artículo, muchas gracias por compartirlo y sigue así.
Genial, muchas gracias!
Espero por más…
Thank you. I enjoy it
Muyyyyy Buenoo, a estudiar se dijo jajaja esto es una clase larguita, en mi caso hubo mas copy/paste que logic paste (hablo de mi) jajaja muy buena MAKIA.
Amigo, gracias por todo.
Pero a patir del capitulo anterior y mas aun en este ya tu explicación no era tan precisa como al inicio, supongo que puedes estar agotado se que no es fácil, pero hay muchos datos que no explicas como instanciar, viewHolder entre otras, tranqui, traqnui no te estoy pidiendo que lo expliques en una respuesta si bien es cierto podemos googlear pero creo que la finalidad del curso se perdió aquí, aprendí todo hasta el capitulo 13 pero aquí ya no hay explicación sino trabajo hecho, no se si tenias prisa por sacar un producto pero en mi perspectiva personal creo que se te paso una explicación mas detallada.
Igual no dejo de agradecerte, pero para futuro espero tomes en cuenta mi comentario.
Buenas, agradezco todo tipo de críticas constructivas. Creo que el curso sigue el mismo plano, pero que la carga de trabajo aumenta. Si es posible que deje cosas sin explicar, más por despistes míos que otra cosa, es por ello que siempre digo que pregunten en los comentarios porque cada vez tengo menos tiempo para escribir, además que yo también estoy aprendiendo.
Un saludo y espero que el próximo capítulo te guste más.
[…] Picasso: Lo usaremos para cargar las imágenes de internet, ya lo hemos usado anteriormente en el capítulo 15. […]
Podrias poner el codigo para descargarlo?
Gracias
Buenas, este al ser bastante sencillo no lo tengo subido. Si tienes alguna duda puedes preguntar y trataré de echarte un cable ^^.
Para los cursos más complejos está todo el proyecto subido (y de aquí en adelante será así con todos).
Un saludo
Rellenar el Recyclerview con Arrays es importante, pero mejor seria hacerlo desde una base de datos externa, de tal manera que podamos observar como se realiza la conexión, como se extrae la información, como quedaría el codigo del archivo php que retorne el json, como se rellena el recyclerview y como se cambia a otra activity o a otro fragment dando click en una fila del recyclerview, no solo mostrar un mensaje.
Me gustaría que incluyas un buscador en la action bar para poder filtrar el recyclereview, a lo mejor es mucho pedir, pero creo que ayudaría a aumentar el interés por el curso de usuarios que ya tengan un poco mas de conocimientos en programación.
Exito
No creo que una cosa quite la otra, es decir, si sabes pintar un recyclerview te da igual de donde vienen los datos porque están abstraídos. Ya hay un capítulo donde te enseña a hacer llamadas a back, por lo que con esa respuesta solo tendrías que añadir el contenido de este turorial.
Respecto a la petición me la apunto. Últimamente no puedo dedicarle mucho tiempo al curso pero en breve habrá una novedad enorme.
Me encontré con tu curso gracias a Google y la verdad es que está excelente. Super claro. Gracias
[…] o si queremos hacer una alarma, necesitaremos el permiso para hacer vibrar nuestro dispositivo. En capítulos anteriores hemos trabajado con ellos de una forma muy superflua, en este capítulo los entenderemos a […]
Te falto añadir que en el main layout debiamos poner el recyclerview manualmente con el design (sino no funciona, da el error de unsolved reference en el MainActivity.kt), para un novato como yo en kotlin puede ser confuso pero para ti es el abc supongo, pero te lo hago tomar en cuenta
Buenas, puedes especificar un poco más? No entiendo exactamente que es lo que no entendiste, así lo actualizo 🙂
Creo que Gonzalo se refiere al tools:context del activity que si copiar no coincide con el local de cada uno
Vale, es que eso lo suelo quitar siempre (no es necesario) pero se me habrá colado. Ahora lo quito. Thx!
Hola! soy nueva en Kotlin, y estoy siguiendo tu curso, es posible que las depencies ya no se use «implementation» y en cambio se use «classpath»? yo lo hice con «implementation» aun cuando a mi no me aparecia el codigo como el tuyo, para probar, obviamente me dio error ya que dice que no sabia leer «implementation» asi que use el «classpath» y todo perfecto
De nuevo te molesto, y disculpa… Continuando con el programa, a la hora de agregar el ImageView y los TextView, arrastarandolos desde a paleta no se anclan, desaparecen, cuaquier cosa que arrastre, no me funciona, me podrias ayudar? gracias
Buenas, puedes poner el XML de la vista a ver que pasa?
hola, disculpa que te moleste de nuevo, he seguito todo tu tutoria y es excelente, queria hacerte un pregunta sobre android studio, hasta ahora corro las app en un telefono conectado a la computadora, ya que no me funciona bien el emulador del android studio, y ha funcionado muy bien. Termine este capitulo del tutorial, corre sin error, pero sale en el celular que la aplicacion se tiene que cerrar, no puedo visualizarla. Ademas en el android studio me aparece una cantidad de errores que empiezan con: «E/AndroidRuntime: FATAL EXCEPTION: main» he busado por internet y nada que lo solucione, esperaba que tu me pudieras dar una mano, gracias
Puedes poner todo el error? Ahí solo te avisa que hay un error pero la información importante va justo después
Hola, ya no me aparece mas el error, pero sigue apaperienco el mensaje que la aplicacion se detuvo y hay que cerrar
Era este: E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.marveldc, PID: 12979
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.marveldc/com.example.marveldc.MainActivity}: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class android.support.v7.widget.RecyclerView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2988)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1631)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Caused by: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class android.support.v7.widget.RecyclerView
Caused by: android.view.InflateException: Binary XML file line #10: Error inflating class android.support.v7.widget.RecyclerView
Caused by: java.lang.ClassNotFoundException: Didn’t find class «android.support.v7.widget.RecyclerView» on path: DexPathList[[zip file «/data/app/com.example.marveldc-1/base.apk»],nativeLibraryDirectories=[/data/app/com.example.marveldc-1/lib/arm64, /system/lib64, /vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.view.LayoutInflater.createView(LayoutInflater.java:616)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:794)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:734)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:865)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:828)
at android.view.LayoutInflater.inflate(LayoutInflater.java:525)
at android.view.LayoutInflater.inflate(LayoutInflater.java:427)
at android.view.LayoutInflater.inflate(LayoutInflater.java:378)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
at com.example.marveldc.MainActivity.onCreate(MainActivity.kt:15)
at android.app.Activity.performCreate(Activity.java:6942)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2880)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2988)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1631)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Hola, me encanta tu curso, pero tengo un problema, uso como emulador BlueStacks y meha funcionado bien hasta los capitulos anteriores. En este me aparece el emulador en blanco, no me aparece la lista y no me sale ningun error, me podrias por favor ayudar
Te recomiendo usar el propio emulador de Android Studio.
Hola! gracias, lo he intentado pero no me funciona, al probar a crear algun profil en el AVD, me sale unknown error y no puedo utilizarlo
En este post https://stackoverflow.com/questions/41072643/android-studio-build-avd-unknown-error/46332056 alguien tiene el mismo error que tú, prueba a ver.
Un saludo
Gracias de verdad por tu tiempo! feliz año! Listo con el AVD pero al correr la aplicacion me dice que la app se para y se tiene que cerrar
Me sirvio demasiado deberias seguir subiendo mas tutoriales, mmuchas gracias
Hola Aris,
está muy bien el artículo. Creo que podría simplificarse más si utilizaras las kotlin android extensiones y en vez de constructores «a lo java» usaras el estilo kotlin.
Por otro lado, no termino de entender esto:
mRecyclerView.setHasFixedSize(true)
mRecyclerView.layoutManager = LinearLayoutManager(this)
¿Podrías explicarme un poco mejor para qué sirve?
Especialmente eso de layoutManager. Nosotros no hemos creado ningún LinearLayout, ¿por qué necesita el recycler un layoutManager?
Salu2.
Hola, estoy utilizando la versión 3.6.3 de Android Studio y no utilizo ningún emulador; para las diferentes ejercicios conecto un dispositivo físico (Motorola 4E PLUS) que ha tenido resultado positivos. Pero con este ejercicio en particular no me arroja ningún error pero la pantalla sale en blanco.
Alguna idea que puede estar fallando ?
Hola Jhon, no estoy seguro, pero tal vez nos llamas a la funcion: setUpRecyclerView().
Según donde la tengas declarada, llámala y te lo ejecutará.
Suerte, tal vez sea eso.
[…] ido desarrollando a lo largo del curso. Todas ellas son un conjunto de componentes (por ejemplo el RecyclerView o la base de datos Room). Para añadirlas siempre hemos tenido que ir al fichero Gradle y añadir […]
Lo he implementado con el SDK 28 y sin problema, sólo cambia que hay que la librería cambia pero el mismo Android Studio ya te lo dice y te la implementa si se lo dices, yo uso ya la versión 4.0 de android studio. Si a alguien le interesa subo el codigo completo a github pero vamos es prácticamente con 3 cambios a lo que dice el excelente manual.
Gracias amigo por la dedicación que tienes y buena explicación, todo bien pero tengo una duda, en el «itemView.setOnClickListener» como abres otra activity? lo intento pero me marca error en el Intent y no se como solucionarlo
saludos!
Gracias por el tutorial, muy completo. solo que fue realmente confuso ya que te enfocas mucho en el capitulo anterior de tu curso, y yo solo venía por esta parte.
Te recomiendo mirar el capitulo en video que esta mas actualizado 🙂
Sigue funcionando todo igual al día de hoy o tendría que tener en cuenta algún cambio en particular al momento de practicar con este capitulo y el video de Youtube
Este es mi vídeo más actualizado
https://www.youtube.com/watch?v=k3zoVAMuW5w&ab_channel=Programaci%C3%B3nAndroidbyAristiDevs
Muy bueno el curso kotlin, gracias por tu tiempo; estoy intentando llenar un spinner con key value por medio de un adapter todo esto con view binding, pero no lo consigo podrías darme luz en el camino jejeje.
De antemano muchas gracias
Aun sigue siendo relevante tu contenido,, muchas gracias por estos tutoriales en el blog.. tremendo crack!!!