Jetpack Compose Row horizontalArrangement constraint - kotlin

How to satisfy both spacedBy(8.dp) and .End
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
}
Row(horizontalArrangement = Arrangement.End) {
}

Adding Spacer as the first row element with weight modifier is equivalent of Arrangement.End:
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Spacer(modifier = Modifier.weight(1f))
Box(
Modifier
.size(30.dp)
.background(Color.Red))
Box(
Modifier
.size(30.dp)
.background(Color.Green))
}
If you need to layout your other items with weight modifier, you can wrap it in one more Row:
Row {
Spacer(modifier = Modifier.weight(1f))
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Box(
Modifier
.size(30.dp)
.background(Color.Red)
)
Box(
Modifier
.size(30.dp)
.background(Color.Green)
)
}
}

Related

How do I make lazyVerticalGrid's scroll and column's verticalScroll, scroll together as one

I practicing jetpack compose, where I have a LazyVerticalGrid, a Text and a lazyColumn composeables, which I put in inside another composable which I called HomeContentScreen and gave it a scroll function, and as you know, the LasyVerticalGrid already has a built-in scroll function, which I tried to disable but it affected the scrolling function.
To Summarize; the three composeables scroll differently, depending on which part of the screen I touch.
So my question is how do I make them all follow the same scroll function (vertically)
Here's the codes.
|
Text Composeable;
#Composable
fun HomeQuote() {
Text(
text = stringResource(R.string.Lorem_ipsum),
style = MaterialTheme.typography.h2,
modifier = Modifier
.paddingFromBaseline(top = 24.dp, bottom = 18.dp)
.padding(horizontal = 18.dp)
.heightIn(min = 56.dp)
)
}
|
LazyVerticalGrid Composable;
#Composable
fun SecondBodyGrid(
modifier: Modifier = Modifier,
onHomeCardClick: (Int) -> Unit = {},
) {
LazyVerticalGrid(
columns = GridCells.Fixed(1),
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = modifier
.height(1450.dp)
//.disabledVerticalPointerInputScroll()
.....
|
LazyRow Composable
#Composable
fun FirstBodyRow(
onHomeCardClick: (Int) -> Unit = {},
) {
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(horizontal = 16.dp),
modifier = Modifier
) {
.....
|
And Finally the Composable I arranged everything, HomeContentScreen;
#Composable
fun HomeContentScreen(
modifier: Modifier = Modifier,
onHomeCardClick: () -> Unit
) {
Column(
modifier
.verticalScroll(rememberScrollState())
.padding(vertical = 16.dp)) {
HomeQuote()
HomeTitleSection(title = R.string.favorite_collections) {
SecondBodyGrid {onHomeCardClick()}
}
HomeTitleSection(title = R.string.align_your_body) {
FirstBodyRow {onHomeCardClick()}
}
}

How to implement Compose Navigation Arguments

I'm practicing Jetpack compose navigation, currently I'm stuck at passing arguments, so the correct information can be displayed when clicked.
I'm trying to navigate from this Destination, MenuScreen;
#Composable
fun HomeScreen(onHomeCardClick: () -> Unit) {
HomeContentScreen(onHomeCardClick = onHomeCardClick)
}
#Composable
fun HomeContentScreen(
modifier: Modifier = Modifier,
onHomeCardClick: () -> Unit
) {
Column(
modifier
.verticalScroll(rememberScrollState())
.padding(vertical = 16.dp)) {
HomeQuote()
....
}
}
To this destination, MenuInfoScreen;
#Composable
fun HomeInfoScreen(){
WelcomeText()
HomeInfoDetails()
}
#Composable
fun WelcomeText() {
Text(
text = "Welcome, to Home Information",
style = MaterialTheme.typography.h3,
modifier = Modifier.padding(horizontal = 12.dp, vertical = 18.dp)
)
}
#Composable
fun HomeInfoDetails(
homeInfo: HomeInfo
) {
Card(
modifier = Modifier
.padding(10.dp)
.clip(CircleShape),
elevation = 10.dp,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
) {
Image(
painter = painterResource(id = homeInfo.homeInfoImageId),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.clip(shape = RoundedCornerShape(topEnd = 4.dp, bottomEnd = 4.dp)),
contentScale = ContentScale.Fit
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = homeInfo.title,
style = MaterialTheme.typography.h3
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = homeInfo.description,
style = MaterialTheme.typography.h5
)
}
}
}
Here's the model I'm trying to follow, HomeInfoModel;
object HomeInfoModel {
val homeInfoModelList = listOf(
HomeInfo(
id = 1,
title = "Monty",
sex = "Male",
age = 14,
description = "Monty enjoys chicken treats and cuddling while watching Seinfeld.",
homeInfoImageId = R.drawable.ab1_inversions
),
.....
)
}
Here's the my NavHost;
NavHost(
navController = navController,
startDestination = Home.route,
modifier = modifier
) {
// builder parameter will be defined here as the graph
composable(route = Home.route) {
HomeScreen(
onHomeCardClick = {}
)
}
....
composable(route = HomeInfoDestination.route) {
HomeInfoScreen()
}
}
}
And my Destinations file;
object Home : KetoDestination {
override val route = "home"
}
....
object HomeInfoDestination : KetoDestination{
override val route = "homeInfo"
}
I know this is a lot and I'm a bit off, but please I've been stuck here for more than a week now. Any little information willl surely come handy.
And Of Course very much appreciated.
Thanks for your help in advance.
You should extract the arguments from the NavBackStackEntry that is available in the lambda of the composable() function.
You can read more in the official android docs https://developer.android.com/jetpack/compose/navigation#nav-with-args

Every element from loop should fill all the free space that is available in the Row

I have elements that I loop through and clicked element changes background to green. I want every element to fill all the free space that is available in the Row. But if I provide weight(1f) it shows only one element that takes all the space, but there should be three elements or whatever count of elements I have passed from outside.
#Composable
fun BottomMenu(
items: List<BottomMenuContent>,
modifier: Modifier = Modifier,
activeHighlightColor: Color = Green,
activeTextColor: Color = Color.White,
inactiveTextColor: Color = Color.Black,
initialSelectedItemIndex: Int = 0
) {
var selectedItemIndex by remember {
mutableStateOf(initialSelectedItemIndex)
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxWidth()
.background(Gray)
.padding(4.dp)
) {
items.forEachIndexed { index, item ->
BottomMenuItem(
item = item,
isSelected = index == selectedItemIndex,
activeHighlightColor = activeHighlightColor,
activeTextColor = activeTextColor,
inactiveTextColor = inactiveTextColor
) {
selectedItemIndex = index
}
}
}
}
#Composable
fun BottomMenuItem(
modifier: Modifier = Modifier,
item: BottomMenuContent,
isSelected: Boolean = false,
activeHighlightColor: Color = Green,
activeTextColor: Color = Color.White,
inactiveTextColor: Color = Color.Black,
onItemClick: () -> Unit
) {
Row( ) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.clickable {
onItemClick()
}
.background(if (isSelected) activeHighlightColor else Color.Transparent)
.weight(1f)
.padding(top = 14.dp, bottom = 14.dp,)
) {
Text(
text = item.title,
color = if(isSelected) activeTextColor else inactiveTextColor
)
}
}}
Remove the weight from the box and instead put it in its parent Row, I modified your code and please look where the weight is placed.
Your BottomMenu
#Composable
fun BottomMenu() {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.background(Color.LightGray)
.fillMaxWidth()
) {
(0..7).forEach {
BottomMenuItem()
}
}
}
Your BottomMenuItem
#Composable
fun RowScope.BottomMenuItem() {
Row(
modifier = Modifier.weight(1f) // remove the weight from the box inside and put it over here instead
) {
Box(
modifier = Modifier
.background(Color.Green)
// remove the weigth(1f) from here
) {
Text(
modifier = Modifier.fillMaxWidth(),
text = "Test",
color = Color.DarkGray
)
}
}
}
Your BottomMenuItem is an extension of a RowScope, so its top level composable can be configured with Row properties such as weight
Output of the code above.

LazyVerticalGrid item full span width [duplicate]

Just like Sliver in Flutter or StaggeredGridLayoutManager in android reyclerview
so I can insert a banner or some thing else into grid layout
Both item and items have argument span, using which you can specify how many of grid placed each item takes:
val colors = listOf(
Color.Gray,
Color.Red,
Color.Cyan,
Color.Blue,
Color.LightGray,
Color.Yellow,
)
val columnsCount = 3
LazyVerticalGrid(columns = GridCells.Fixed(columnsCount)) {
items(6) {
Box(
modifier = Modifier
.height(100.dp)
.fillMaxWidth()
.background(colors[it])
)
}
items(3, span = { GridItemSpan(columnsCount) }) {
Box(
modifier = Modifier
.height(100.dp)
.fillMaxWidth()
.background(colors[it])
)
}
}
Result:

Jetpack compose scrollable table

I need to have a component that scrolls vertically and horizontally.
Here is what I did so far:
#Composable
fun Screen() {
val scope = rememberCoroutineScope()
val scrollOffset = remember {
mutableStateOf(value = 0F)
}
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(space = 16.dp)
) {
items(10) {
SimpleRow(
onScrollOffsetChange = {
scrollOffset.value = it
}
)
}
}
}
#Composable
private fun SimpleRow(
onScrollOffsetChange: (Float) -> Unit,
) {
val lazyRowState = rememberLazyListState()
LazyRow(
modifier = Modifier.fillMaxWidth(),
state = lazyRowState
) {
item {
Text(
text = "firstText"
)
}
for (i in 1..30) {
item {
Text(text = "qwerty")
}
}
}
}
When anyone of these SimpleRow is scrolled I want to scroll all of the SimpleRows together.
And I do not know how many SimpleRows I have because they came from our server.
Is there any kind of composable or trick that can do it for me?
You can use multiple rows inside a column that scrolls horizontally and vertically, like this:
#Composable
fun MainContent() {
val scrollStateHorizontal = rememberScrollState()
val scrollStateVertical = rememberScrollState()
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(state = scrollStateVertical)
.horizontalScroll(state = scrollStateHorizontal)
) {
repeat(40){ c ->
Row {
repeat(40){ r ->
Item("col: $c | row: $r")
}
}
}
}
}
#Composable
fun Item(text: String) {
Text(
modifier = Modifier
.padding(5.dp)
.background(Color.Gray),
text = text,
color = Color.White
)
}