Reputation: 535
I'm trying to achieve a horizontal scroll view using jetpack compose like below:
But I couldn't find any solution to set the width of cell to take width of screen with 16dp margin, and that's what I'm getting:
This the my code:
private val imageList : Array<Effect<Image>> =arrayOf(
imageResource(R.drawable.maldive),
imageResource(R.drawable.maldiveone),
imageResource(R.drawable.maldivetwo))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
createList()
}
}
@Composable
fun createList(){
MaterialTheme() {
HorizontalScroller(){
Row(crossAxisSize = LayoutSize.Expand) {
(0..3).forEachIndexed { _, i ->
populateListItem(i)
}
}
}
}
}
@Composable
fun populateListItem(index: Int){
Column(crossAxisSize = LayoutSize.Wrap, modifier = Spacing(16.dp)) {
Card(elevation = 0.dp, shape = RoundedCornerShape(8.dp, 8.dp, 8.dp, 8.dp)) {
val im: Image = +imageList[index.rem(3)]
Container(expanded = true,height = 180.dp)
{
DrawImage(image = im)
}
}
HeightSpacer(height = 16.dp)
Text("Maldive $index",
style = +themeTextStyle { h6 })
Text("Enjoy Our $index Resort!",
style = +themeTextStyle { body2 })
}
}
Upvotes: 7
Views: 14758
Reputation: 23844
Just adding my solution here...
@Composable
fun HorizontalScrollScreen() {
// replace with your items...
val items = (1..10).map { "Item $it" }
// a wrapper to fill the entire screen
Box(modifier = Modifier.fillMaxSize()) {
// BowWithConstraints will provide the maxWidth used below
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
// LazyRow to display your items horizontally
LazyRow(
modifier = Modifier.fillMaxWidth(),
state = rememberLazyListState()
) {
itemsIndexed(items) { index, item ->
Card(
modifier = Modifier
.height(100.dp)
.width(maxWidth) // here is the trick
.padding(16.dp)
) {
Text(item) // card's content
}
}
}
}
}
}
This implementation works, but you will not have the snap behavior. This behavior is not supported out-of-the-box by LazyRow
(there's a feature request for that https://issuetracker.google.com/issues/166590434), but you can try to implement this using the flingBehavior
parameter.
Or for now, you can use the Accompanist Pager library. https://github.com/google/accompanist/tree/main/pager
Upvotes: 1
Reputation: 75
You want your child item's width is match_parent right?. You should use com.google.accompanist:accompanist-pager:0.8.1
from google. It will look like horizontal viewpager
Link: https://google.github.io/accompanist/pager/
Upvotes: 0
Reputation: 433
From JetPack Compose 1.0.0-beta01 use BoxWithConstraints
to get the screen's maximum width and height and pass that along to @Composable
annotated functions and Modifiers as needed.
@Composable
fun WithConstraintsComposable() {
BoxWithConstraints {
Text("My minHeight is $minHeight while my maxWidth is $maxWidth)
}
}
docs: https://developer.android.com/jetpack/compose/layout#constraints
Upvotes: 0
Reputation: 643
The key is resources.displayMetrics.widthPixels, this will do the magic. replace your populateListItem function with below, it will work
@Composable
fun populateListItem(index: Int) {
val padding = 16
val dm = resources.displayMetrics
val cardWidth = dm.widthPixels/dm.density - 16 * 2 // 2 is multiplied for left and right padding
Column(crossAxisSize = LayoutSize.Wrap, modifier = Spacing(padding.dp)) {
Card(elevation = 0.dp, shape = RoundedCornerShape(8.dp, 8.dp, 8.dp, 8.dp)) {
val im: Image = +imageList[index.rem(3)]
Container(width = cardWidth.dp, height = 180.dp)
{
DrawImage(image = im)
}
}
HeightSpacer(height = 16.dp)
Text("Maldive $index",
style = +themeTextStyle { h6 })
Text("Enjoy Our $index Resort!",
style = +themeTextStyle { body2 })
}
}
Upvotes: 1