Ejercicio: RecyclerView usando ViewBinding en Kotlin
Uso de ViewBinding en un RecyclerView en Kotlin
Tutorial sobre RecyclerView en Kotlin:
SuperHero.kt
data class SuperHero ( var superhero:String, var publisher:String, var realName:String, var photo:String )
SuperHeroProvider original
class SuperHeroProvider { companion object { val superHeroList = listOf<SuperHero>( SuperHero( "KotlinMan", "Jetbrains", "AristiDevs", "https://cursokotlin.com/wp-content/uploads/2020/09/Webp.net-compress-image.jpg" ), SuperHero( "Spiderman", "Marvel", "Peter Parker", "https://cursokotlin.com/wp-content/uploads/2017/07/spiderman.jpg" ), SuperHero( "Daredevil", "Marvel", "Matthew Michael Murdock", "https://cursokotlin.com/wp-content/uploads/2017/07/daredevil.jpg" ), SuperHero( "Wolverine", "Marvel", "James Howlett", "https://cursokotlin.com/wp-content/uploads/2017/07/logan.jpeg" ), SuperHero( "Batman", "DC", "Bruce Wayne", "https://cursokotlin.com/wp-content/uploads/2017/07/batman.jpg" ), SuperHero( "Thor", "Marvel", "Thor Odinson", "https://cursokotlin.com/wp-content/uploads/2017/07/thor.jpg" ), SuperHero( "Flash", "DC", "Jay Garrick", "https://cursokotlin.com/wp-content/uploads/2017/07/flash.png" ), SuperHero( "Green Lantern", "DC", "Alan Scott", "https://cursokotlin.com/wp-content/uploads/2017/07/green-lantern.jpg" ), SuperHero( "Wonder Woman", "DC", "Princess Diana", "https://cursokotlin.com/wp-content/uploads/2017/07/wonder_woman.jpg" ) ) } }
SuperHeroProvider
class SuperHeroProvider { companion object { val URL = "https://dam.org.es/ficheros/" val superHeroList = listOf<SuperHero>( SuperHero( "KotlinMan", "Jetbrains", "AristiDevs", // "https://cursokotlin.com/wp-content/uploads/2020/09/Webp.net-compress-image.jpg" URL + "Webp.net-compress-image.jpg" ), SuperHero( "Spiderman", "Marvel", "Peter Parker", // "https://cursokotlin.com/wp-content/uploads/2017/07/spiderman.jpg" URL + "spiderman.jpg" ), SuperHero( "Daredevil", "Marvel", "Matthew Michael Murdock", // "https://cursokotlin.com/wp-content/uploads/2017/07/daredevil.jpg" URL + "daredevil.jpg" ), SuperHero( "Wolverine", "Marvel", "James Howlett", // "https://cursokotlin.com/wp-content/uploads/2017/07/logan.jpeg" URL + "logan.jpeg" ), SuperHero( "Batman", "DC", "Bruce Wayne", // "https://cursokotlin.com/wp-content/uploads/2017/07/batman.jpg" URL + "batman.jpg" ), SuperHero( "Thor", "Marvel", "Thor Odinson", // "https://cursokotlin.com/wp-content/uploads/2017/07/thor.jpg" URL + "thor.jpg" ), SuperHero( "Flash", "DC", "Jay Garrick", // "https://cursokotlin.com/wp-content/uploads/2017/07/flash.png" URL + "flash.png" ), SuperHero( "Green Lantern", "DC", "Alan Scott", // "https://cursokotlin.com/wp-content/uploads/2017/07/green-lantern.jpg" URL + "green-lantern.jpg" ), SuperHero( "Wonder Woman", "DC", "Princess Diana", // "https://cursokotlin.com/wp-content/uploads/2017/07/wonder_woman.jpg" URL + "wonder_woman.jpg" ) ) } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerSuperHero" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.03" /> </androidx.constraintlayout.widget.ConstraintLayout>
item_superhero.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/ivSuperHero" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/ic_launcher_background" /> <TextView android:id="@+id/tvSuperHeroName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="37dp" android:layout_marginTop="16dp" android:text="TextView" app:layout_constraintStart_toEndOf="@+id/ivSuperHero" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tvRealName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="9dp" android:text="TextView" app:layout_constraintStart_toStartOf="@+id/tvSuperHeroName" app:layout_constraintTop_toBottomOf="@+id/tvSuperHeroName" /> <TextView android:id="@+id/tvPublisher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:text="TextView" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="@+id/tvRealName" /> </androidx.constraintlayout.widget.ConstraintLayout>
SuperHeroViewHolder.kt
class SuperHeroViewHolder(view:View):RecyclerView.ViewHolder(view) { val superHero = view.findViewById<TextView>(R.id.tvSuperHeroName) val realName = view.findViewById<TextView>(R.id.tvRealName) val publisher = view.findViewById<TextView>(R.id.tvPublisher) val photo = view.findViewById<ImageView>(R.id.ivSuperHero) fun render (superHeroModel: SuperHero) { superHero.text = superHeroModel.superhero realName.text = superHeroModel.realName publisher.text = superHeroModel.publisher } }
SuperHeroAdapter.kt
class SuperHeroAdapter (val superheroList:List<SuperHero>) : RecyclerView.Adapter<SuperHeroViewHolder> () { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SuperHeroViewHolder { val layoutInflater = LayoutInflater.from(parent.context) return SuperHeroViewHolder(layoutInflater.inflate(R.layout.item_superhero, parent, false)) } override fun onBindViewHolder(holder: SuperHeroViewHolder, position: Int) { val item = superheroList[position] holder.render(item) } override fun getItemCount(): Int { return superheroList.size } }
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initRecyclerView() } private fun initRecyclerView() { val recyclerView = findViewById<RecyclerView>(R.id.recyclerSuperHero) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = SuperHeroAdapter(SuperHeroProvider.superHeroList) } }
Descarga de imágenes con Glide
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
Dependencia en build.gradle
implementation("com.github.bumptech.glide:glide:4.16.0")
SuperHeroViewHolder.kt
class SuperHeroViewHolder(view:View):RecyclerView.ViewHolder(view) { val superHero = view.findViewById<TextView>(R.id.tvSuperHeroName) val realName = view.findViewById<TextView>(R.id.tvRealName) val publisher = view.findViewById<TextView>(R.id.tvPublisher) val photo = view.findViewById<ImageView>(R.id.ivSuperHero) fun render (superHeroModel: SuperHero) { superHero.text = superHeroModel.superhero realName.text = superHeroModel.realName publisher.text = superHeroModel.publisher Glide.with(photo.context).load(superHeroModel.photo).into(photo)
implementation ("com.squareup.picasso:picasso:2.8")
SuperHeroViewHolder.kt
class SuperHeroViewHolder(view:View):RecyclerView.ViewHolder(view) { val superHero = view.findViewById<TextView>(R.id.tvSuperHeroName) val realName = view.findViewById<TextView>(R.id.tvRealName) val publisher = view.findViewById<TextView>(R.id.tvPublisher) val photo = view.findViewById<ImageView>(R.id.ivSuperHero) fun render (superHeroModel: SuperHero) { superHero.text = superHeroModel.superhero realName.text = superHeroModel.realName publisher.text = superHeroModel.publisher // Glide.with(photo.context).load(superHeroModel.photo).into(photo) Picasso.get().load(superHeroModel.photo).into(photo); } }
Uso de View Binding
build.gradle
buildFeatures { viewBinding = true }
SuperHeroViewHolder.kt
class SuperHeroViewHolder(view: View) : RecyclerView.ViewHolder(view) { val binding = ItemSuperheroBinding.bind(view) fun render(superHeroModel: SuperHero, onClickListener: (SuperHero) -> Unit) { binding.tvSuperHeroName.text = superHeroModel.superhero binding.tvRealName.text = superHeroModel.realName binding.tvPublisher.text = superHeroModel.publisher // Glide.with(binding.ivSuperHero.context).load(superHeroModel.photo).into(binding.ivSuperHero) Picasso.get().load(superHeroModel.photo).into(binding.ivSuperHero); itemView.setOnClickListener { onClickListener(superHeroModel) } } }
SuperHeroAdapter.kt
class SuperHeroAdapter( private val superheroList: List<SuperHero>, private val onClickListener: (SuperHero) -> Unit ) : RecyclerView.Adapter<SuperHeroViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SuperHeroViewHolder { val layoutInflater = LayoutInflater.from(parent.context) return SuperHeroViewHolder(layoutInflater.inflate(R.layout.item_superhero, parent, false)) } override fun onBindViewHolder(holder: SuperHeroViewHolder, position: Int) { val item = superheroList[position] holder.render(item, onClickListener) } override fun getItemCount(): Int { return superheroList.size } }
MainActivity.kt
class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) initRecyclerView() } private fun initRecyclerView() { val manager = LinearLayoutManager(this) val decoration = DividerItemDecoration(this, manager.orientation) binding.recyclerSuperHero.layoutManager = manager binding.recyclerSuperHero.adapter = SuperHeroAdapter(SuperHeroProvider.superHeroList) { superHero -> onItemSelected( superHero ) } binding.recyclerSuperHero.addItemDecoration(decoration) } fun onItemSelected(superHero: SuperHero) { Toast.makeText(this, superHero.superhero, Toast.LENGTH_SHORT).show() } }
item_superhero.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_marginHorizontal="16dp" android:layout_marginVertical="8dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/ivSuperHero" android:layout_width="150dp" android:layout_height="150dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:src="@drawable/ic_launcher_background" /> <TextView android:id="@+id/tvSuperHeroName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="21sp" android:textStyle="bold" android:textColor="@color/black" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/ivSuperHero" app:layout_constraintTop_toTopOf="parent" tools:text="KotlinMan" /> <TextView android:id="@+id/tvRealName" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/ivSuperHero" app:layout_constraintTop_toBottomOf="@+id/tvSuperHeroName" tools:text="Julio" /> <TextView android:id="@+id/tvPublisher" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" tools:text="Hola" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView>
Mejora: poner un botón que permita añadir un nuevo elemento a la lista
Más información:
How To: RecyclerView with a Kotlin-Style Click Listener in Android
Ejercicio 2 de la tarea online
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.