Adding a RecyclerView
Before we move into the shared element transitions there are a few changes we need to change to our app as we want to reproduce the most common use of the shared element transitions, a RecyclerView with a details screen.
By the end of this step this will be our final app:

First of all we need to change the CardView
in both of our XML layout files to a RecyclerView
.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout ....>
<!-- Circle ImageView -->
<!-- Main ImageView -->
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_contacts"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="16dp"
android:elevation="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/guideline_horizontal30"
tools:listitem="@layout/li_main" />
<!-- ImageView Paw 1-->
<!-- ImageView Paw 2-->
<!-- ImageView Paw 3-->
<!-- ImageView Paw 4-->
<!-- Second Background View-->
<!-- ImageView Leaf 1 -->
<!-- ImageView Leaf 2 -->
<!-- Guidelines -->
</android.support.constraint.motion.MotionLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout ....>
<!-- Circle ImageView -->
<!-- ImageView Leaf 1 -->
<!-- ImageView Leaf 2 -->
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_contacts"
android:layout_width="match_parent"
android:layout_height="0dp"
tools:listitem="@layout/li_main"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/guideline_horizontal20"
app:layout_constraintVertical_bias="0.0"
android:elevation="2dp"/>
<!-- Main ImageView -->
<!-- ImageView Paw 1-->
<!-- ImageView Paw 2-->
<!-- ImageView Paw 3-->
<!-- ImageView Paw 4-->
<!-- Second Background View-->
<!-- Guidelines -->
</android.support.constraint.motion.MotionLayout>
Then we need to create the XML layout for our list items.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout android:layout_height="wrap_content"
android:layout_width="match_parent"
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">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/iv_avatar"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:elevation="3dp"
app:layout_constraintBottom_toBottomOf="@+id/cardView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/cardView"
tools:src="@tools:sample/avatars" />
<android.support.v7.widget.CardView
android:id="@+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:background="@color/cardview_light_background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="29dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" />
<TextView
android:id="@+id/tv_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/tv_name"
app:layout_constraintTop_toBottomOf="@+id/tv_name"
tools:text="@tools:sample/us_phones" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
</android.support.constraint.ConstraintLayout>
We then create a data class for our mock data:
data class Contact (val avatarId: Int?, val name: String, val phone:String)
On our MainActivity.kt
we add the following methods
private val contacts = arrayListOf<Contact>()
private val NUMBER_OF_ITEMS = 8
....
// Create dummy data to populate to our RecyclerView
private fun getData(){
var count =0
while (count < NUMBER_OF_ITEMS) {
contacts.add(Contact(getDrawableForPosition(count+1), "XYZ", "645654654"))
count ++
}
}
/**
We want to have an automatic way to get the images for the avatars.
This will return the resource id for a specific name
The position refers to the item position on the list
*/
private fun getDrawableForPosition(position:Int): Int? {
val name = "avatar_$position"
return resources.getIdentifier(name, "drawable",packageName)
}
We also need to create a RecyclerView
Adapter.
class ContactsAdapter(val context: Context, val items:List<Contact>) :
RecyclerView.Adapter<ContactsAdapter.ViewHolder>() {
class ViewHolder (view: View) : RecyclerView.ViewHolder(view) {
// Holds the TextView that will add each animal to
val avatar = view.iv_avatar!!
val tvName = view.tv_name!!
val tvPhone = view.tv_phone!!
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContactsAdapter.ViewHolder {
return ViewHolder(LayoutInflater.from(context).inflate(R.layout.li_main, parent, false))
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: ContactsAdapter.ViewHolder, position: Int) {
Glide.with(context).load(items[position].avatarId).into(holder.avatar)
holder.tvName.text = items[position].name
holder.tvPhone.text = items[position].phone
}
}
Finally we populate our RecyclerView
with our dummy data
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_start)
getData()
rv_contacts.apply {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(context)
adapter = ContactsAdapter(context, contacts)
}
}
And of course we run our app to test that everything is working
Last updated