Android Compose Horizontal pager with Indicator .
Automated scroll!
Hello guys , First of all my name is Eang Tithsophorn. I been working as Mobile Development for more than 3 year which are include Android , iOS and Flutter.
Here the list of my usage:
- Kotlin
- build.gradle (kts)
- NetworkImage
- Material3
- Box (Stack)
First of all , we need this dependency from google itself!
implementation("androidx.compose.foundation:foundation:1.4.0")
implementation("io.coil-kt:coil-compose:2.2.2")// NetworkImage
Note : accompanist.pager already deprecated.
Just Follow the trend!
Incase you want to explore more for pager, Here is the doc.
Now let’s start , Shall we?
What’s if I tell you that all you need to run as a page?
HorizontalPager(
pageCount = yourList.size,
state = pagerState,
modifier = Modifier.height(300.dp)
) { index ->
AsyncImage(
model = yourList[index],
contentDescription = "this is image from server",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
}
Note: AsyncImage is an compose function for request image from url which is doesn’t need the internet permission
You can play around with height and even with out you will notice something or some text!
Now it’s time for indicator!
val pagerState = rememberPagerState()
That’s where the controller of the page and indicator will be!
For Indicator
Row(
Modifier
.height(10.dp)
.fillMaxWidth()
.align(Alignment.BottomCenter),
horizontalArrangement = Arrangement.Center
) {
repeat(itemsList.size) { iteration ->
val color =
if (pagerState.currentPage == iteration) Color.Yellow else Color.LightGray
Box(
modifier = Modifier
.padding(start = 2.dp, end = 2.dp, bottom = 5.dp)
.clip(CircleShape)
.background(color)
.size(8.dp)
)
}
}
We style it a little bit and then we combine it all together!
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun BannerView(
modifier: Modifier = Modifier,
itemsList: List<String> = listOf(),
pagerState: PagerState = rememberPagerState()
) {
Card(
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
shape = RoundedCornerShape(8.dp),
modifier = modifier
) {
Box {
HorizontalPager(
pageCount = itemsList.size,
state = pagerState,
modifier = Modifier.height(300.dp)
) { index ->
AsyncImage(
model = itemsList[index],
contentDescription = "this is image from server",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
}
Row(
Modifier
.height(10.dp)
.fillMaxWidth()
.align(Alignment.BottomCenter),
horizontalArrangement = Arrangement.Center
) {
repeat(itemsList.size) { iteration ->
val color =
if (pagerState.currentPage == iteration) appColor else Color.LightGray
Box(
modifier = Modifier
.padding(start = 2.dp, end = 2.dp, bottom = 5.dp)
.clip(CircleShape)
.background(color)
.size(8.dp)
)
}
}
}
}
}
Here the Result
I knew you want it auto scroll right?
I got you!
Here the code for auto scroll.
LaunchedEffect(key1 = pagerState.currentPage) {
launch {
delay(2000)
with(pagerState) {
val target = if (currentPage < itemsList.count() - 1) currentPage + 1 else 0
animateScrollToPage(
page = target, animationSpec = tween(
durationMillis = 0, easing = FastOutLinearInEasing
)
)
}
}
}
Full Code!!!!
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun BannerView(
modifier: Modifier = Modifier,
itemsList: List<String> = listOf(),
pagerState: PagerState = rememberPagerState()
) {
Card(
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
shape = RoundedCornerShape(8.dp),
modifier = modifier
) {
Box {
HorizontalPager(
pageCount = itemsList.size,
state = pagerState,
modifier = Modifier.height(300.dp)
) { index ->
AsyncImage(
model = itemsList[index],
contentDescription = "this is image from server",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
}
Row(
Modifier
.height(10.dp)
.fillMaxWidth()
.align(Alignment.BottomCenter),
horizontalArrangement = Arrangement.Center
) {
repeat(itemsList.size) { iteration ->
val color =
if (pagerState.currentPage == iteration) Color.Yellow else Color.LightGray
Box(
modifier = Modifier
.padding(start = 2.dp, end = 2.dp, bottom = 5.dp)
.clip(CircleShape)
.background(color)
.size(8.dp)
)
}
}
}
}
LaunchedEffect(key1 = pagerState.currentPage) {
launch {
delay(2000)
with(pagerState) {
val target = if (currentPage < itemsList.count() - 1) currentPage + 1 else 0
animateScrollToPage(
page = target, animationSpec = tween(
durationMillis = 0, easing = FastOutLinearInEasing
)
)
}
}
}
}
How I call:
BannerView(
itemsList = listOf(
"https://images.pexels.com/photos/5110955/pexels-photo-5110955.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
"https://images.pexels.com/photos/3876443/pexels-photo-3876443.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
"https://images.pexels.com/photos/4284831/pexels-photo-4284831.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
"https://images.pexels.com/photos/4514301/pexels-photo-4514301.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
),
pagerState = pagerState,
modifier = Modifier.padding(start = 4.dp, end = 4.dp, bottom = 8.dp, top = 8.dp)
)
Thank you for your time!
I hope that’s it helpful in your case!
Leave a comment for check out more , git and my site.
See you in the next one!! :)