Overview
Text shadow enhances text legibility and visual depth by adding a soft outline or offset layer behind a TextView. Shadow effects are commonly used to make text stand out over images, gradients, or complex backgrounds. Android provides built-in support for shadow rendering via APIs and XML attributes.
This document explains how to apply shadow effects on text in Android using both XML and programmatic approaches, along with design considerations and advanced usage patterns.
Shadow in Typography — Why It Matters
Shadow in typography can:
- Improve online readability in low-contrast areas
- Add visual hierarchy to UI elements
- Provide subtle design accents without heavy graphics
- Simulate depth in flat layouts
- Support multi-layered text styling
In mobile UI design, a carefully tuned shadow can reduce eye strain and increase clarity when text overlays busy backgrounds.
Basic Shadow Using XML Attributes
Android’s TextView supports the android:shadowLayer attribute, which defines the radius, offset, and color of the shadow.
Shadow Attributes
| Attribute | Purpose |
|---|---|
android:shadowRadius | Blur radius for the shadow |
android:shadowDx | Horizontal offset (positive = right, negative = left) |
android:shadowDy | Vertical offset (positive = down, negative = up) |
android:shadowColor | Color of the shadow |
Example: XML Shadow
<TextView
android:id="@+id/textShadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Elevated Text"
android:textSize="28sp"
android:textColor="#FFFFFF"
android:shadowColor="#80000000"
android:shadowDx="2"
android:shadowDy="2"
android:shadowRadius="4" />
Here:
- A semi-transparent black shadow (
#80000000) adds depth - Offsets position the shadow below and to the right
- A moderate blur radius smooths the edge
Shadow values can be scaled based on screen density to ensure consistent rendering across devices.
Programmatic Shadow in Java/Kotlin
Applying shadow at runtime enables dynamic effects based on app state, theme, or user preferences.
Java
TextView textView = findViewById(R.id.textShadow);
textView.setShadowLayer(
6f, // radius
4f, // dx
4f, // dy
Color.parseColor("#66000000") // shadow color
);
Kotlin
val textView: TextView = findViewById(R.id.textShadow)
textView.setShadowLayer(
6f,
4f,
4f,
Color.parseColor("#66000000")
)
Programmatic shadow application is useful when themes or user control determine the visual style.
Advanced Shadow Techniques
Multi-Layered Text Shadow
To simulate richer depth or “neon glow” effects, you can stack shadows by drawing multiple TextView’s or customizing drawing in a Canvas.
textView.setShadowLayer(8f, 0f, 0f, Color.parseColor("#FF5722"));
textView.setShadowLayer(12f, 2f, 2f, Color.parseColor("#E91E63"));
Because setting multiple shadow layers on the same text replaces the previous one, a custom view with multiple drawn text passes can achieve layered visuals.
Custom Drawing with Canvas
When shadows require precise control (e.g., layered colored glows or animating shadow properties), override onDraw() in a custom TextView:
public class ShadowTextView extends androidx.appcompat.widget.AppCompatTextView {
public ShadowTextView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
// Draw shadow pass
getPaint().setShadowLayer(10f, 5f, 5f, Color.BLACK);
super.onDraw(canvas);
// Draw primary text on top
getPaint().setShadowLayer(0f, 0f, 0f, Color.TRANSPARENT);
super.onDraw(canvas);
}
}
Custom drawing offers complete control over the sequence and rendering, allowing you to combine shadow with animations or state changes.
Design Considerations
Color and Contrast
- Select a shadow color with appropriate opacity; pure black isn’t always best
- Mid-tone backgrounds may benefit from lighter, blurred shadows
Performance Impacts
- Excessive shadow radius and high blur values can increase rendering cost
- On large text blocks or lists, consider limiting shadows to headers or key elements
Accessibility
- Ensure that text remains legible without shadow for users with contrast requirements
- Shadows should not replace contrast — they should augment readability
Cross-Device Consistency
Device pixel densities vary across Android screens. To ensure consistent shadow appearance:
- Use
dporspfor shadow properties when calculating offsets - Scale shadow attributes based on
DisplayMetrics.density
Example:
float scale = getResources().getDisplayMetrics().density;
textView.setShadowLayer(4 * scale, 2 * scale, 2 * scale, Color.DKGRAY);
This ensures similar visual weight across phones and tablets.


