I have a LazyColumn where the use inputs items into. I want the LazyColumn to display the most recent item. How do I do this? Right now, LazyColumn is reversed, but doesn't stay scrolled to the top of the list.
Here is my LazyColumn:
val listState = rememberLazyListState()
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
reverseLayout = true,
verticalArrangement = Arrangement.Top,
userScrollEnabled = true,
state = listState
) {
items(cardState.size) {}
items(items = getAllData) { card ->
CustomItem(practiceCard = card, navController = navController)
Spacer(Modifier.size(10.dp))
}
And here is the button to add to the list:
cardRepository.allCards.add(
PracticeCard(
viewModel.sentence)
Related
I want to create a Image that add a border to yourself on onClick trigger. Here is my code:
#Composable
fun Dices(#DrawableRes dice: List<Int>, viewModel: DicesViewModel) {
Column(Modifier.padding(top = 28.dp, start = 10.dp, end = 10.dp, bottom = 26.dp), verticalArrangement = Arrangement.Bottom, horizontalAlignment = Alignment.CenterHorizontally) {
Row() {
Image(
painter = painterResource(id = dice[0]),
contentDescription = "Dice",
modifier = Modifier
.padding(2.dp)
.size(110.dp)
.clickable { Modifier.border(2.dp, Color.Black) /* doesnt work */ })
}
}
I have six more of these Image(), below, but i do not pase it here, because it's the same as here.
There is any way to add border to this?
I want to add a border to Image after click on it
Try this:
var isSelected by remember{ mutableStateOf(false)}
modifier = Modifier
.padding(2.dp)
.size(110.dp)
.border(if (isSelected) 2.dp else 0.dp, Color.Black)
.clickable { isSelected = !isSelected }
I'm working with Compose but have Fragments. I need to switch to second page when user click IconButton.
With only xml:
_binding = FragmentFirstScreenBinding.inflate(inflater, container, false)
val viewPager = activity?.findViewById<ViewPager2>(R.id.viewPager)
binding.firstFragmentButton.setOnClickListener{
viewPager?.currentItem = 1
}
In Compose:
AndroidView(factory = { context ->
val viewPager = activity?.findViewById<ViewPager2>(R.id.viewPager)
val view = LayoutInflater.from(context)
.inflate(R.layout.fragment_view_pager, null, false)
viewPager?.currentItem = 1
view
})
Box(
modifier = Modifier
.fillMaxSize()
) {
IconButton(
onClick = { },
modifier = Modifier
.height(90.dp)
.width(90.dp)
.align(Alignment.TopEnd)
) {
Icon(
painter = painterResource(id = R.drawable.ic_baseline_keyboard_arrow_right_24),
contentDescription = "",
)
}
}
Problem with this code is that automatically I switch to second page.
I tried to put viewPager in IconButton on click but I dont get view back and got null when user clicks icon. My question is how to get that viewPager into compose part.
EDIT:
Just put viewPager in onCreateView before
val viewPager = activity?.findViewById<ViewPager2>(R.id.viewPager)
return ComposeView(requireContext()).apply {
setContent {
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()}
}
}
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.
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: