Jetpack Compose Vertical Scrolling is interrupted by Horizontal Scrolling - android

I have create a Column having 5 Rows, Column has vertical scrolling enabled and Rows has horizontal scrolling enabled.
Sometimes when I try to fling or scroll vertically, Rows consume the gesture and stops vertical scroll to happen.
is there a way to enable horizontal scroll only when certain x-delta is dragged/swipped/scrolled?
code to reproduce :
val colors = remember {
listOf(
Color.Blue,
Color.Green,
Color.Cyan,
Color.Magenta
)
}
Box(
modifier = Modifier
) {
Column(
modifier = Modifier
.padding(top = 200.dp)
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
repeat(5) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.horizontalScroll(rememberScrollState())
) {
repeat(5) {
Box(
modifier = Modifier
.size(200.dp)
.background(
color = remember {
colors.random()
}
)
)
}
}
}
}
}
Edit 1: this is a bug in compose issue added to tracker

Related

Why when animating using animateContentSize(), the content bounces off the edge of the container

Below is a simplified version of the bar from the diagram that I am implementing. While scrolling the chart, I change its scale and would like to animate it, but during the animation, the edge of the column moves away from the edge of the chart. How can I avoid this?
demo
#Composable
fun AnimationTest() {
var toggle by remember { mutableStateOf(true) }
Row(
modifier = Modifier
.padding(8.dp)
.animateContentSize()
.clickable { toggle = !toggle },
) {
Spacer(modifier = Modifier.weight(if (toggle) 0.4f else 0.6f))
Card(
modifier = Modifier
.animateContentSize()
.weight(if (toggle) 0.6f else 0.4f)
) {
Row {
Box(
modifier = Modifier
.weight(if (toggle) 0.2f else 0.1f)
.background(Color.Magenta)
.height(56.dp)
)
Box(
modifier = Modifier
.weight(if (toggle) 0.4f else 0.3f)
.background(Color.Blue)
.height(56.dp)
)
}
}
}
}
I tried to use Animated Content, but I don't quite understand what to specify as transitionSpec.
I guess the problem is that the Card to which I apply the animateContentSize() also changes its size, but not by changing the size of children, but by changing its own weight.

Android Jetpack Compose LazyVerticalGrid horizontal span also adds unnecessary vertical span

So, my code looks like this (I simplified it a lot for readability)
LazyVerticalGrid(
modifier = modifier
.background(Color.Black)
.padding(16.dp),
cells = GridCells.Fixed(5),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(26) {
Spacer(
modifier = Modifier
.size(64.dp)
.background(Color.Cyan)
)
}
item {
Spacer(
modifier = Modifier
.height(64.dp)
.fillMaxWidth()
.background(Color.Magenta)
)
}
}
And it looks like this (screenshot from preview):
However, when I add a span to the last item (the magenta one):
item(span = { GridItemSpan(2) }) {
//The last item goes here
}
An unwanted space in the bottom is added:
If the item with a span is the first one (before the cyan ones), the space remains in the bottom.

how to add space between grid items in jetpack compose

I am currently trying to implement a gridview, it consists of 2 columns. I know i can implement my own grid view using columns and rows, but i just want to use existing approach although it is experimental.
#Composable
fun MyGridScreen() {
LazyVerticalGrid(cells = GridCells.Fixed(2), modifier = Modifier.fillMaxSize(),contentPadding = PaddingValues(12.dp)) {
items(15) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.padding(10.dp)
.height(80.dp)
.background(Color.Red)
.aspectRatio(1f)
) {
Text("Grid item $it", color = Color.White)
}
}
}
}
Below is the result i achieved. I can't put space below the item :(
You need to set verticalArrangement and horizontalArrangement properties on the LazyVerticalGrid composable.
This will space the items by 10.dp in both the vertical and horizontal axis.
#Composable
fun MyGridScreen() {
LazyVerticalGrid(
cells = GridCells.Fixed(2),
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(12.dp),
verticalArrangement = Arrangement.spacedBy(10.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp
) {
items(15) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.padding(10.dp)
.height(80.dp)
.background(Color.Red)
.aspectRatio(1f)
) {
Text("Grid item $it", color = Color.White)
}
}
}
}
Padding is exactly what you need in this case. But you need to understand that in compose modifiers order means a lot. By moving background modifier in between padding and sizes modifiers, you'll get what you need. And clickable ripple will work the same.
Check out more how modifiers order works: https://stackoverflow.com/a/65698101/3585796
.padding(10.dp)
.background(Color.Red)
.height(80.dp)
.aspectRatio(1f)
p.s. if you need your items to be a square, just put your box in one more box. Looks like width of items in LazyVerticalGrid gets overridden by the grid to fill max width, not sure if that's a bug or a feature.

How to use Jetpack Compose ConstraintLayout together with Column

I'd like to test a simple layout in compose:
A ConstraintLayout (yellow) wrapping
StickyTopText (green)
a Scrolling View (gray)
StickyBottomText (yellow)
I implemented it like this:
#Composable
#Preview
fun MapOverlay() {
ConstraintLayout(
modifier = Modifier
.background(Color.Yellow)
.fillMaxHeight()
) {
val (stickyTop, scroller, stickyBottom) = createRefs()
Text(text = "Sticky Top Text",
modifier = Modifier
.constrainAs(stickyTop) {
top.linkTo(parent.top)
}
.background(Color.Green)
)
Column(
modifier = Modifier
.constrainAs(scroller) {
top.linkTo(stickyTop.bottom)
bottom.linkTo(stickyBottom.top)
height = Dimension.fillToConstraints
}
.verticalScroll(rememberScrollState())
) {
repeat(80) {
Text(
text = "This is Test $it of 80",
modifier = Modifier
.fillMaxWidth()
.background(Color.LightGray)
)
}
}
Text(text = "Sticky Bottom Text",
modifier = Modifier
.background(Color.Red)
.constrainAs(stickyBottom) {
bottom.linkTo(parent.bottom)
})
}
}
Most of it works pretty fine, except the list getting cut off at the end at item 77 instead of 80: (79; zero-Indexed)
What am i doing wrong? Or is this a bug?
(I know i might do this via a scaffold, but that seemed over engineered. Also i would like to understand the issue, not circumvent it
Compose version 1.0.0-beta09
I checked your code and it's really not working on 1.0.0-alpha07, but it's working on 1.0.0-alpha08 (and compose 1.0.0-beta09) 😉
Also, is there any particular reason you're using ConstraintLayout? You can achieve the same result using this code:
Column(
Modifier
.background(Color.Yellow)
.fillMaxHeight()
) {
Text("Sticky Top Text", Modifier.background(Color.Green))
Column(
Modifier
.weight(1f)
.verticalScroll(rememberScrollState())
) {
repeat(80) {
Text(
"This is Test ${it + 1} of 80",
Modifier
.fillMaxWidth()
.background(Color.LightGray)
)
}
}
Text("Sticky Bottom Text", Modifier.background(Color.Red))
}

fillViewPort behavior in Jetpack Compose Column

Is there something like ScrollView fillViewPort in Jetpack Compose Column?
See this example:
#Composable
fun FillViewPortIssue() {
Column(
Modifier
.fillMaxSize()
.padding(16.dp)
) {
for (i in 0..5) {
Box(
modifier = Modifier
.padding(vertical = 8.dp)
.background(Color.Red)
.fillMaxWidth()
.height(72.dp)
)
}
Spacer(modifier = Modifier.weight(1f))
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { /*TODO*/ }
) {
Text("Ok")
}
}
}
This is the result:
When the device is in landscape, the content is cropped, because there's no scroll.
If I add the verticalScroll modifier do the Column...
...
Column(
Modifier
.verticalScroll(rememberScrollState()) // <<-- this
.fillMaxSize()
.padding(16.dp)
) {
...
... the scroll problem is fixed, but the button goes up, like this.
In the traditional toolkit, we can fix this using ScrollView + fillViewPort property. Is there something equivalent to Compose?
Just change the order of the modifiers worked...
Thanks to Abhishek Dewan (from Kotlin Slack channel)!
Column(
Modifier
.fillMaxSize() // first, set the max size
.verticalScroll(rememberScrollState()) // then set the scroll
) {
I had a similar issue recently and substituted verticalScroll for scrollable(rememberScrollState(), Orientation.Vertical) which seemed to work for my case and allow the screen to fill its viewport while allowing scrolling

Categories

Resources