diff --git a/README.md b/README.md index ae98482..6cdcc1b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This library can be simpler solution for small grid UI. There are benefits of this library: - **Similar API to LazyGrid**: The GridLayout's APIs are designed to provide similar development experience to LazyGrid. -- **Easy to implement adaptive grid**: There are _"Fixed"_ and _"Adaptive"_ for grid layout management like LazyGrid. +- **Easy to implement various grid**: There are _"Fixed"_, _"Adaptive"_ and _"FixedSize"_ for grid layout management like LazyGrid. Like LazyGrid, it eliminates dealing with different screen sizes. - **Simple to use as a part of LazyList**: The GridLayout is not lazy layout. It can be simply placed in lazy layouts. If only a portion of the full layout is grid, No need to use LazyGrid with span size for full layout. diff --git a/docs/cell-strategy.md b/docs/cell-strategy.md index ad669ee..b2d7af5 100644 --- a/docs/cell-strategy.md +++ b/docs/cell-strategy.md @@ -3,8 +3,8 @@ All grid layout composables take a cell strategy parameter called `SimpleGridCells`. `SimpleGridCells` defines the number of cells and the size of each cell. -There are 2 types of cell strategy, `Fixed` and `Adaptive`. -They are similar to LazyGrid's `Fixed` and `Adaptive`. +There are several types of cell strategy, `Fixed`, `Adaptive` and `FixedSize`. +They are similar to LazyGrid's `GridCells.Fixed`, `GridCells.Adaptive` and `GridCells.FixedSize`. ## Fixed @@ -94,9 +94,51 @@ And each cells will have 1/3 of 400dp (about 133.333dp) width or height. If the grid size is expanded to 600dp, the number of cells on each line will be changed to 5 and each cell's size will be 120dp. +## FixedSize + +`SimpleGridCells.FixedSize` is a cell strategy for as many cells as possible with exact size. + +The API of `FixedSize` looks like this: + +```kotlin +class FixedSize( + private val size: Dp, + private val fill: Boolean = true +) : SimpleGridCells +``` + +There is a parameter called `size`. This is the size of each cell should have. +The `size` must be a positive size. If the size is 0 or below, it occurs an exception. +If the `size` is bigger than container's size, the cell will have the same size to the container. + +!!! note + For information about `fill` parameter, read [Fill Option](#fill-option) section. + +For example, a grid has 400dp width or height and `FixedSize(120.dp)` is applied. + +```kotlin +HorizontalGrid( + rows = SimpleGridCells.FixedSize(120.dp), + modifier = Modifier.height(400.dp) +) { /* content */ } + +VerticalGrid( + columns = SimpleGridCells.FixedSize(120.dp), + modifier = Modifier.width(400.dp) +) { /* content */ } +``` + +![fixed-size-example](./images/fixedsize-example.png) + +The grid will have 3 cells on each line and the remaining space will not be used. +If the grid size is expanded to 600dp, the number of cells on each line will be changed to 5. + +In other case, `FixedSize(300.dp)` for `VerticalGrid(Modifier.width(200.dp))` means that there +will be only one column and the cell will have 200dp width. + ## Fill Option -Both `Fixed` and `Adaptive` have a optional parameter named `fill`. +All cell strategy classes have a optional parameter named `fill`. The `fill` parameter determines that grid's item composable should fill grid cell's size. When `fill` is true, grid layout forces item composable to have width or height to fit cell's maximum width or height. diff --git a/docs/images/fixedsize-example.png b/docs/images/fixedsize-example.png new file mode 100644 index 0000000..fab1b7b Binary files /dev/null and b/docs/images/fixedsize-example.png differ diff --git a/docs/index.md b/docs/index.md index 9796938..28da988 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ This library can be simpler solution for small grid UI. There are benefits of this library: - **Similar API to LazyGrid**: The GridLayout's APIs are designed to provide similar development experience to LazyGrid. -- **Easy to implement adaptive grid**: There are _"Fixed"_ and _"Adaptive"_ for grid layout management like LazyGrid. +- **Easy to implement various grid**: There are _"Fixed"_, _"Adaptive"_ and _"FixedSize"_ for grid layout management like LazyGrid. Like LazyGrid, it eliminates dealing with different screen sizes. - **Simple to use as a part of LazyList**: The GridLayout is not lazy layout. It can be simply placed in lazy layouts. If only a portion of the full layout is grid, No need to use LazyGrid with span size for full layout. diff --git a/grid/api/android/grid.api b/grid/api/android/grid.api index 1143dcc..b6c4c92 100644 --- a/grid/api/android/grid.api +++ b/grid/api/android/grid.api @@ -91,3 +91,13 @@ public final class com/cheonjaeung/compose/grid/SimpleGridCells$Fixed : com/cheo public fun hashCode ()I } +public final class com/cheonjaeung/compose/grid/SimpleGridCells$FixedSize : com/cheonjaeung/compose/grid/SimpleGridCells { + public static final field $stable I + public synthetic fun (FZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (FZLkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun calculateCrossAxisCellSizes (Landroidx/compose/ui/unit/Density;II)Ljava/util/List; + public fun equals (Ljava/lang/Object;)Z + public fun fillCellSize ()Z + public fun hashCode ()I +} + diff --git a/grid/api/jvm/grid.api b/grid/api/jvm/grid.api index 1143dcc..b6c4c92 100644 --- a/grid/api/jvm/grid.api +++ b/grid/api/jvm/grid.api @@ -91,3 +91,13 @@ public final class com/cheonjaeung/compose/grid/SimpleGridCells$Fixed : com/cheo public fun hashCode ()I } +public final class com/cheonjaeung/compose/grid/SimpleGridCells$FixedSize : com/cheonjaeung/compose/grid/SimpleGridCells { + public static final field $stable I + public synthetic fun (FZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (FZLkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun calculateCrossAxisCellSizes (Landroidx/compose/ui/unit/Density;II)Ljava/util/List; + public fun equals (Ljava/lang/Object;)Z + public fun fillCellSize ()Z + public fun hashCode ()I +} + diff --git a/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/BoxGridMeasurePolicy.kt b/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/BoxGridMeasurePolicy.kt index fc100cf..b2d59a7 100644 --- a/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/BoxGridMeasurePolicy.kt +++ b/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/BoxGridMeasurePolicy.kt @@ -189,14 +189,22 @@ private class BoxGridMeasureHelper( val horizontalSpacingPx = horizontalSpacing.roundToPx() val verticalSpacingPx = verticalSpacing.roundToPx() - var currentX = 0 - var currentY = 0 + var currentX = if (layoutDirection == LayoutDirection.Rtl) { + val horizontalSpacingCount = (columnCount - 1).coerceAtLeast(0) + val horizontalSpacingSumPx = horizontalSpacingPx * horizontalSpacingCount + val contentWidth = cellWidthConstraintList.sum() + horizontalSpacingSumPx + measureResult.layoutSize.width.roundToInt() - contentWidth + } else { + 0 + } val xPositions = IntArray(columnCount) - val yPositions = IntArray(rowCount) for (i in 0 until columnCount) { xPositions[i] = currentX currentX += cellWidthConstraintList[i] + horizontalSpacingPx } + + var currentY = 0 + val yPositions = IntArray(rowCount) for (i in 0 until rowCount) { yPositions[i] = currentY currentY += cellHeightConstraintList[i] + verticalSpacingPx diff --git a/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/SimpleGridCells.kt b/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/SimpleGridCells.kt index 48dbbb7..7a9b532 100644 --- a/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/SimpleGridCells.kt +++ b/grid/src/commonMain/kotlin/com/cheonjaeung/compose/grid/SimpleGridCells.kt @@ -134,4 +134,67 @@ interface SimpleGridCells { return hash } } + + /** + * Make grid to have as many rows or columns as possible and each cell has exactly [size]. + * If [size] is bigger than container's size, the cell will have the same size to the container. + * + * For example, `FixedSize(20.dp)` for `VerticalGrid(Modifier.width(66.dp)` means that there + * will be 3 columns and each cell will have 20dp width and 6dp is remained. + * + * In other case, `FixedSize(150.dp)` for `VerticalGrid(Modifier.width(100.dp)` means that there + * will be only one column and the cell will have 100dp width. + * + * @param size The size which each cell should have. + * @param fill When `true`, item composable fill cell's width or height. + */ + @ExperimentalGridApi + class FixedSize( + private val size: Dp, + private val fill: Boolean = true, + ) : SimpleGridCells { + init { + if (size <= 0.dp) { + throw IllegalArgumentException("FixedSize size must be a positive, but $size") + } + } + + override fun Density.calculateCrossAxisCellSizes( + availableSize: Int, + spacing: Int + ): List { + val cellSize = size.roundToPx() + val availableSizeWithSpacing = availableSize + spacing + val cellSizeWithSpacing = cellSize + spacing + + return if (cellSizeWithSpacing < availableSizeWithSpacing) { + val count = if (cellSizeWithSpacing != 0) { + availableSizeWithSpacing / cellSizeWithSpacing + } else { + 1 + } + return List(count) { cellSize } + } else { + List(1) { availableSize } + } + } + + override fun fillCellSize(): Boolean { + return fill + } + + override fun equals(other: Any?): Boolean { + if (other !is FixedSize) return false + if (this.size != other.size) return false + if (this.fill != other.fill) return false + return true + } + + override fun hashCode(): Int { + var hash = 1 + hash = hash * 31 + size.hashCode() + hash = hash * 31 + fill.hashCode() + return hash + } + } } diff --git a/grid/src/test/java/com/cheonjaeung/compose/grid/BoxGridTest.kt b/grid/src/test/java/com/cheonjaeung/compose/grid/BoxGridTest.kt index d16b83d..037ff04 100644 --- a/grid/src/test/java/com/cheonjaeung/compose/grid/BoxGridTest.kt +++ b/grid/src/test/java/com/cheonjaeung/compose/grid/BoxGridTest.kt @@ -711,6 +711,456 @@ class BoxGridTest { } } + @Test + fun testFixedRowsAndFixedSizeColumns() { + paparazzi.snapshot { + Column { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.Fixed(2), + columns = SimpleGridCells.FixedSize(80.dp) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.Fixed(2), + columns = SimpleGridCells.FixedSize(80.dp) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + } + } + } + } + + @Test + fun testFixedRowsAndFixedSizeColumnsWithFillFalse() { + paparazzi.snapshot { + Column { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.Fixed(2, fill = false), + columns = SimpleGridCells.FixedSize(80.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.Fixed(2, fill = false), + columns = SimpleGridCells.FixedSize(80.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(100.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + } + } + } + } + + @Test + fun testAdaptiveRowsAndFixedSizeColumns() { + paparazzi.snapshot { + Column { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.Adaptive(60.dp), + columns = SimpleGridCells.FixedSize(80.dp) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.Adaptive(60.dp), + columns = SimpleGridCells.FixedSize(80.dp) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + } + } + } + } + + @Test + fun testAdaptiveRowsAndFixedSizeColumnsWithFillFalse() { + paparazzi.snapshot { + Column { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.Adaptive(60.dp, fill = false), + columns = SimpleGridCells.FixedSize(80.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.Adaptive(60.dp, fill = false), + columns = SimpleGridCells.FixedSize(80.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + } + } + } + } + + @Test + fun testFixedSizeRowsAndFixedSizeColumns() { + paparazzi.snapshot { + Column { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.FixedSize(60.dp), + columns = SimpleGridCells.FixedSize(80.dp) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.FixedSize(60.dp), + columns = SimpleGridCells.FixedSize(80.dp) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + } + } + } + } + + @Test + fun testFixedSizeRowsAndFixedSizeColumnsWithFillFalse() { + paparazzi.snapshot { + Column { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.FixedSize(60.dp, fill = false), + columns = SimpleGridCells.FixedSize(80.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + BoxGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.FixedSize(60.dp, fill = false), + columns = SimpleGridCells.FixedSize(80.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(50.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 1, column = 1) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 2, column = 2) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(50.dp) + .position(row = 3, column = 1) + .background(Color.Red) + ) + } + } + } + } + } + @Test fun testSpacing() { val colors = listOf( diff --git a/grid/src/test/java/com/cheonjaeung/compose/grid/HorizontalGridTest.kt b/grid/src/test/java/com/cheonjaeung/compose/grid/HorizontalGridTest.kt index 4e5c22b..a361fec 100644 --- a/grid/src/test/java/com/cheonjaeung/compose/grid/HorizontalGridTest.kt +++ b/grid/src/test/java/com/cheonjaeung/compose/grid/HorizontalGridTest.kt @@ -17,6 +17,7 @@ import app.cash.paparazzi.Paparazzi import org.junit.Rule import org.junit.Test +@OptIn(ExperimentalGridApi::class) class HorizontalGridTest { @get:Rule val paparazzi = Paparazzi( @@ -307,6 +308,140 @@ class HorizontalGridTest { } } + @Test + fun testFixedSizeRows() { + paparazzi.snapshot { + Column { + HorizontalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.FixedSize(100.dp) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + HorizontalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.FixedSize(100.dp) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Red) + ) + } + } + } + } + } + + @Test + fun testFixedSizeRowsWithFillFalse() { + paparazzi.snapshot { + Column { + HorizontalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + rows = SimpleGridCells.FixedSize(100.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Red) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + HorizontalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + rows = SimpleGridCells.FixedSize(100.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Yellow) + ) + Box( + modifier = Modifier + .size(80.dp) + .background(Color.Red) + ) + } + } + } + } + } + @Test fun testBreakDownToNextLine() { val colors = listOf( diff --git a/grid/src/test/java/com/cheonjaeung/compose/grid/VerticalGridTest.kt b/grid/src/test/java/com/cheonjaeung/compose/grid/VerticalGridTest.kt index 38cc52a..2fb8762 100644 --- a/grid/src/test/java/com/cheonjaeung/compose/grid/VerticalGridTest.kt +++ b/grid/src/test/java/com/cheonjaeung/compose/grid/VerticalGridTest.kt @@ -17,6 +17,7 @@ import app.cash.paparazzi.Paparazzi import org.junit.Rule import org.junit.Test +@OptIn(ExperimentalGridApi::class) class VerticalGridTest { @get:Rule val paparazzi = Paparazzi( @@ -287,6 +288,120 @@ class VerticalGridTest { } } + @Test + fun testFixedSizeColumns() { + paparazzi.snapshot { + Column { + VerticalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + columns = SimpleGridCells.FixedSize(120.dp) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Yellow) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + VerticalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + columns = SimpleGridCells.FixedSize(120.dp) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Yellow) + ) + } + } + } + } + } + + @Test + fun testFixedSizeColumnsWithFillFalse() { + paparazzi.snapshot { + Column { + VerticalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.LightGray), + columns = SimpleGridCells.FixedSize(120.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Yellow) + ) + } + + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + VerticalGrid( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .background(Color.Gray), + columns = SimpleGridCells.FixedSize(120.dp, fill = false) + ) { + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Blue) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Green) + ) + Box( + modifier = Modifier + .size(100.dp) + .background(Color.Yellow) + ) + } + } + } + } + } + @Test fun testBreakDownToNextLine() { val colors = listOf( diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testAdaptiveRowsAndFixedSizeColumns.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testAdaptiveRowsAndFixedSizeColumns.png new file mode 100644 index 0000000..5cba6f1 Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testAdaptiveRowsAndFixedSizeColumns.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testAdaptiveRowsAndFixedSizeColumnsWithFillFalse.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testAdaptiveRowsAndFixedSizeColumnsWithFillFalse.png new file mode 100644 index 0000000..b8cdd70 Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testAdaptiveRowsAndFixedSizeColumnsWithFillFalse.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedRowsAndFixedSizeColumns.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedRowsAndFixedSizeColumns.png new file mode 100644 index 0000000..0689f7b Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedRowsAndFixedSizeColumns.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedRowsAndFixedSizeColumnsWithFillFalse.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedRowsAndFixedSizeColumnsWithFillFalse.png new file mode 100644 index 0000000..8c5a3ba Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedRowsAndFixedSizeColumnsWithFillFalse.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedSizeRowsAndFixedSizeColumns.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedSizeRowsAndFixedSizeColumns.png new file mode 100644 index 0000000..5c3f502 Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedSizeRowsAndFixedSizeColumns.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedSizeRowsAndFixedSizeColumnsWithFillFalse.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedSizeRowsAndFixedSizeColumnsWithFillFalse.png new file mode 100644 index 0000000..efb8e0c Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_BoxGridTest_testFixedSizeRowsAndFixedSizeColumnsWithFillFalse.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_HorizontalGridTest_testFixedSizeRows.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_HorizontalGridTest_testFixedSizeRows.png new file mode 100644 index 0000000..7ecca5f Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_HorizontalGridTest_testFixedSizeRows.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_HorizontalGridTest_testFixedSizeRowsWithFillFalse.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_HorizontalGridTest_testFixedSizeRowsWithFillFalse.png new file mode 100644 index 0000000..7df4488 Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_HorizontalGridTest_testFixedSizeRowsWithFillFalse.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_VerticalGridTest_testFixedSizeColumns.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_VerticalGridTest_testFixedSizeColumns.png new file mode 100644 index 0000000..30a1bfc Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_VerticalGridTest_testFixedSizeColumns.png differ diff --git a/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_VerticalGridTest_testFixedSizeColumnsWithFillFalse.png b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_VerticalGridTest_testFixedSizeColumnsWithFillFalse.png new file mode 100644 index 0000000..1c7d840 Binary files /dev/null and b/grid/src/test/snapshots/images/com.cheonjaeung.compose.grid_VerticalGridTest_testFixedSizeColumnsWithFillFalse.png differ