Mastering Android Layout Reuse: From <include> to ViewBinding and Kotlin Extensions
A junior Android developer learns to extract a card UI into a reusable layout, replace repetitive findViewById code with a custom view, then streamline everything further using Jetpack ViewBinding and Kotlin extension functions, dramatically cutting boilerplate and simplifying maintenance.
Layout Reuse with <include>
Define the reusable card UI in a separate layout file card_item.xml. The layout uses androidx.cardview.widget.CardView containing an ImageView and two TextView s.
<?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"
android:layout_width="match_parent"
android:layout_height="100dp"
app:cardCornerRadius="5dp"
android:layout_margin="10dp"
app:cardElevation="2dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/avatar"
android:layout_width="80dp"
android:layout_height="90dp"
android:src="@mipmap/logo"
android:scaleType="centerCrop"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#333"
android:textSize="18sp"
android:layout_toRightOf="@+id/avatar"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp" />
<TextView
android:id="@+id/des"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#999"
android:textSize="12sp"
android:layout_below="@+id/name"
android:layout_toRightOf="@+id/avatar"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp" />
</RelativeLayout>
</androidx.cardview.widget.CardView>Include this layout in any fragment layout using the <include> tag:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/card_item" />
</LinearLayout>In the fragment, bind the views with findViewById and set data.
class MyFragment : Fragment() {
private lateinit var avatar: ImageView
private lateinit var name: TextView
private lateinit var desc: TextView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.my_fragment, container, false)
avatar = view.findViewById(R.id.avatar)
name = view.findViewById(R.id.name)
desc = view.findViewById(R.id.des)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
avatar.setImageResource(R.mipmap.logo)
name.text = "技术最TOP"
desc.text = "扒最前沿科技动态,聊最TOP编程技术~"
}
}Encapsulating the Card in a Custom View
To avoid repeating view‑lookup code, create a custom view CardItem that inflates card_item.xml internally and provides a setData method.
class CardItem @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
private var ivAvatar: ImageView
private var tvName: TextView
private var tvDesc: TextView
init {
val view = LayoutInflater.from(context).inflate(R.layout.card_item, null, false)
ivAvatar = view.findViewById(R.id.avatar)
tvName = view.findViewById(R.id.name)
tvDesc = view.findViewById(R.id.des)
addView(view)
}
fun setData(imageRes: Int, name: String, desc: String) {
ivAvatar.setImageResource(imageRes)
tvName.text = name
tvDesc.text = desc
}
}Use the custom view directly in XML and call setData from the fragment.
<com.jay.jetpack.viewbinding.CardItem
android:id="@+id/card_item"
android:layout_width="match_parent"
android:layout_height="wrap_content" /> override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
cardItem.setData(R.mipmap.logo, "技术最TOP", "扒最前沿科技动态,聊最TOP编程技术~")
}Jetpack ViewBinding for Boilerplate Elimination
Enable ViewBinding in the module’s build.gradle:
viewBinding {
enabled = true
}Gradle generates a binding class for each layout (e.g., CardItemBinding for card_item.xml and MyFragment2Binding for my_fragment2.xml). The class name is derived from the layout file name by removing underscores and appending Binding.
Replace the custom view usage with an <include> that has an ID, then access its views through the generated binding:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include android:id="@+id/topCard" layout="@layout/card_item" />
</LinearLayout>Fragment code using ViewBinding:
class MyFragment2 : Fragment(R.layout.my_fragment2) {
private lateinit var binding: MyFragment2Binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = MyFragment2Binding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.topCard.apply {
avatar.setImageResource(R.mipmap.logo)
name.text = "技术最TOP"
des.text = "扒最前沿科技动态,聊最TOP编程技术。"
}
}
}Kotlin Extension Function Combined with ViewBinding
Define a concise extension on the generated binding to set all fields in one call.
fun CardItemBinding.bind(imageResId: Int, nameStr: String, descStr: String) {
avatar.setImageResource(imageResId)
name.text = nameStr
des.text = descStr
}Now the fragment can populate the card with a single line:
binding.topCard.bind(R.mipmap.logo, "技术最TOP Super", "扒最前沿科技动态,聊最TOP编程技术。Super")This approach reduces the custom view class from dozens of lines to a few lines of extension code, centralises layout changes, and eliminates repetitive findViewById calls across multiple fragments.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
