![]() |
| TextView on ImageView |
For now, I had used four different existing layouts to make this happen. Those Parent Layouts are:-
- Use Frame Layout
- Use Relative Layout
- Use Linear Layout
- Use CardView Layout
FrameLayout:
RelativeLayout:
Linear Layout:
CardView:
Code:
So displaying TextView over an ImageView in multiple ways is accomplished.
Update (September 2026): overlapping text on an image with ConstraintLayout and Jetpack Compose
The four approaches above (FrameLayout, RelativeLayout, LinearLayout and CardView) all still work. Today the most common ways to put text on top of an image are a FrameLayout or ConstraintLayout in XML and a Box in Jetpack Compose. Both keep the layout flat, which is better for performance than nesting several layouts.
1. XML: ConstraintLayout
Because views in a ConstraintLayout are drawn in the order they appear in the file, the TextView declared after the ImageView is drawn on top of it. Pin the text to the bottom of the image:
<androidx.constraintlayout.widget.ConstraintLayout
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="220dp">
<ImageView
android:id="@+id/cover"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/sample"
android:contentDescription="Cover image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/caption"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#99000000"
android:padding="12dp"
android:text="Text on top of the image"
android:textColor="@android:color/white"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="@id/cover"
app:layout_constraintStart_toStartOf="@id/cover"
app:layout_constraintEnd_toEndOf="@id/cover" />
</androidx.constraintlayout.widget.ConstraintLayout>
The semi-transparent background (#99000000) keeps the text readable on any picture. If you only need a simple overlay and no other constraints, a plain FrameLayout with android:layout_gravity="bottom" on the TextView gives the same result.
2. Jetpack Compose: Box
In Compose, children of a Box are stacked in the order you write them. Use Modifier.align to place each child inside the box:
@Composable
fun ImageWithCaption() {
Box(
modifier = Modifier
.fillMaxWidth()
.height(220.dp)
) {
Image(
painter = painterResource(id = R.drawable.sample),
contentDescription = "Cover image",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
Text(
text = "Text on top of the image",
color = Color.White,
fontSize = 18.sp,
modifier = Modifier
.align(Alignment.BottomStart)
.fillMaxWidth()
.background(Color(0x99000000))
.padding(12.dp)
)
}
}
To load an image from the network use Coil (AsyncImage) instead of Image; the Box and align part stays exactly the same.
Tips
- Readability: put a dark scrim (semi-transparent background or a vertical gradient) behind the text so it stays readable on bright images.
- Accessibility: always set a
contentDescriptionon meaningful images. - Which one: XML app: FrameLayout for simple overlays, ConstraintLayout when other views depend on the image. Compose app:
Box.



Comments
Post a Comment