A modern, Kotlin-based implementation of the shimmer effect for Android, inspired by Facebook's Shimmer library.
- Easy Integration: Simple XML attributes, programmatic API, or Jetpack Compose modifier
- Jetpack Compose Support: First-class Compose support with
Modifier.shimmer() - Highly Customizable: Control direction, shape, colors, duration, and more
- Modern Architecture: Built with Kotlin and modern Android best practices
- Lightweight: Minimal dependencies
- Alpha and Color Modes: Support for both alpha-based and color-based shimmer effects
- Multiple Shapes: Linear and radial shimmer patterns
- Min SDK: 21 (Android 5.0)
- Target SDK: 35 (Android 15)
- Kotlin: 2.0.21+
Add the dependency to your app's build.gradle.kts:
dependencies {
implementation("io.github.anglesvar:shimmer:1.0.0")
}Or in build.gradle:
dependencies {
implementation 'io.github.anglesvar:shimmer:1.0.0'
}If you're using it as a local module:
dependencies {
implementation(project(":shimmer"))
}Apply shimmer effect using the Modifier.shimmer() extension:
import com.anglesvar.shimmer.shimmer
import com.anglesvar.shimmer.Shimmer
@Composable
fun LoadingPlaceholder() {
Box(
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.background(Color.LightGray)
.shimmer()
)
}@Composable
fun CustomShimmer() {
Box(
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.background(Color.Gray)
.shimmer(
direction = Shimmer.Direction.LEFT_TO_RIGHT,
shape = Shimmer.Shape.LINEAR,
baseColor = Color.Gray.copy(alpha = 0.3f),
highlightColor = Color.White,
durationMillis = 1500,
intensity = 0.5f,
dropoff = 0.5f,
tilt = 20f
)
)
}For better performance when multiple composables use the same shimmer configuration:
@Composable
fun ShimmerList() {
val shimmerState = rememberShimmerState(
config = ShimmerConfig(
direction = Shimmer.Direction.TOP_TO_BOTTOM,
baseColor = Color.Gray.copy(alpha = 0.3f),
highlightColor = Color.White
),
durationMillis = 1500
)
Column {
repeat(5) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(80.dp)
.background(Color.LightGray)
.shimmer(shimmerState)
)
Spacer(modifier = Modifier.height(8.dp))
}
}
}@Composable
fun QuickPlaceholder() {
ShimmerBox(
modifier = Modifier
.fillMaxWidth()
.height(100.dp),
backgroundColor = Color.LightGray
) {
// Optional content inside
Text("Loading...", modifier = Modifier.padding(16.dp))
}
}@Composable
fun RadialShimmerExample() {
Box(
modifier = Modifier
.size(200.dp)
.clip(CircleShape)
.background(Color.Gray)
.shimmer(
shape = Shimmer.Shape.RADIAL,
highlightColor = Color.White,
baseColor = Color.Gray.copy(alpha = 0.3f)
)
)
}Add ShimmerFrameLayout to your layout:
<com.anglesvar.shimmer.ShimmerFrameLayout
android:id="@+id/shimmer_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:shimmer_auto_start="true"
app:shimmer_base_alpha="0.3"
app:shimmer_highlight_alpha="1.0"
app:shimmer_duration="1000"
app:shimmer_direction="left_to_right"
app:shimmer_shape="linear">
<!-- Your content here -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Loading..." />
</com.anglesvar.shimmer.ShimmerFrameLayout>Control shimmer programmatically:
val shimmerLayout = findViewById<ShimmerFrameLayout>(R.id.shimmer_layout)
// Start shimmer
shimmerLayout.startShimmer()
// Stop shimmer
shimmerLayout.stopShimmer()
// Custom configuration
val shimmer = Shimmer.AlphaHighlightBuilder()
.setDirection(Shimmer.Direction.LEFT_TO_RIGHT)
.setDuration(1500)
.setIntensity(0.5f)
.setDropoff(0.5f)
.setTilt(20f)
.build()
shimmerLayout.setShimmer(shimmer)For a colored shimmer effect:
<com.anglesvar.shimmer.ShimmerFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:shimmer_colored="true"
app:shimmer_base_color="#E0E0E0"
app:shimmer_highlight_color="#FFFFFF"
app:shimmer_duration="1500">
<!-- Your content -->
</com.anglesvar.shimmer.ShimmerFrameLayout>Or programmatically:
val shimmer = Shimmer.ColorHighlightBuilder()
.setBaseColor(Color.GRAY)
.setHighlightColor(Color.WHITE)
.setDuration(1500)
.build()| Attribute | Type | Default | Description |
|---|---|---|---|
shimmer_clip_to_children |
boolean | true | Clip shimmer to children bounds |
shimmer_colored |
boolean | false | Use color shimmer instead of alpha |
shimmer_auto_start |
boolean | true | Auto-start animation |
shimmer_base_color |
color | #4CFFFFFF | Base color for shimmer |
shimmer_highlight_color |
color | #FFFFFFFF | Highlight color |
shimmer_base_alpha |
float | 0.3 | Base alpha (0.0 - 1.0) |
shimmer_highlight_alpha |
float | 1.0 | Highlight alpha (0.0 - 1.0) |
shimmer_intensity |
float | 0.0 | Shimmer intensity |
shimmer_dropoff |
float | 0.5 | Gradient dropoff |
shimmer_tilt |
float | 20 | Tilt angle in degrees |
shimmer_duration |
integer | 1000 | Animation duration (ms) |
shimmer_repeat_count |
integer | -1 | Repeat count (-1 = infinite) |
shimmer_repeat_delay |
integer | 0 | Delay between repeats (ms) |
shimmer_repeat_mode |
enum | restart | restart or reverse |
shimmer_direction |
enum | left_to_right | Direction of shimmer effect |
shimmer_shape |
enum | linear | linear or radial |
shimmer_width_ratio |
float | 1.0 | Width ratio |
shimmer_height_ratio |
float | 1.0 | Height ratio |
shimmer_fixed_width |
dimension | 0 | Fixed width in pixels |
shimmer_fixed_height |
dimension | 0 | Fixed height in pixels |
left_to_righttop_to_bottomright_to_leftbottom_to_top
linear: Ray effect (default)radial: Spotlight effect
Run the sample module to see various shimmer configurations in action, including both XML and Jetpack Compose implementations.
BSD License - See LICENSE file for details.
Created by anglesvar
Inspired by Facebook's Shimmer Android library