MinHight for an expandable card item in lazy column in Compose - android

I have a Card as an expandable item in LazyColumn, the initial height I want is 50dp, and the max is WrapContaintHeight, I'm trying playing with Modifiers to set the min and the max, here is what I did
.height(50dp)
.heightIn(min = 50dp, max = WrapContaintHeight)
But it always previews the card height like WrapContaintHeight as the initial height, what I want is the initial height to be 50dp, and when I expand it by clicking on the card to be WrapContaintHeight, I already have a code to control the expand state

you need to create a boolean variable for click to item.
.height(if(isFullSize) 100.dp else 50.dp)

Related

Display another composable layout if one is two wide for screen

Context:
In the app, there are dynamic questions from the backend asking users to select an option, usually two or three options.
The first choice design is to display the options as buttons in a row. But sometimes, the button texts could be very long that the buttons or the texts are not displayed properly on a mobile phone. In this case, the options should be displayed as a dropdown.
What tried:
To get the width of the button row, I tried to create a mutableState isBtnStyle var, pass a callback lambda to the button layout composable, get and pass back the row width, compare the row width with the screen width, and if the row width is bigger, display the dropdown layout.
val screenWidth = Resources.getSystem().displayMetrics.widthPixels
var isBtnStyle by remember {mutableStateOf(true)}
val rowWidth = { width: Int ->
if ( width > screenWidth ) isBtnStyle = false
}
if(isBtnStyle){
btnStyleComposable(rowWidth)
} else {
dropdownStyleComposable()
}
The problem:
The button layout composable is always displayed first for measuring the width, then the dropdown composable is displayed if the button layout is too wide for the screen.
Question:
How could I get the width of the row of buttons before the row is visually displayed, so the decision can be made on which composable layout to be displayed?
Thank you
Here is your answer.
For sake of minimum message length, I will add that I prefer to use Modifier.onPlaced.

Compose: LazyVerticalGrid with variable contentPadding

I want to display a LazyVerticalGrid with three columns. At the top, I want a header that spans all columns and scrolls with the content. This works fine using an item at the beginning that sets the span to maxLineSpan.
However, I want the main content of the grid to have a contentPadding of 16 dp. At the same time, the header is supposed to be full-bleed, i.e. the contentPadding should not apply to the header.
What is the best way to achieve this with LazyVerticalGrid? Manually adding start/end padding to the content items based on the column they're in seems to be not an option, as the width of the item in the middle doesn't scale proportionally.

android, how to set a same height for my cards without hardcode in lazy row

I have a lazy row with items that have wrap content height.
my problem is that some texts of these items is visible or invisible base of that item. so the height of that cart is not fix and it will change.
how can I find the max height of that item (with all texts) and set that height to all items.
I do not want to set a hard code height to my items (like 300.dp)
as you can see in this image: the below button change its position based on the card's height.
I want that button fix in its place and not move up and down.
https://i.stack.imgur.com/R0Tc6.png
how can I fix that problem?
Have you tried experimenting around onGloballyPositioned{..} modifier property?
val localDensity = LocalDensity.current
Text(modifier = Modifier
.onGloballyPositioned { thisText ->
with (localDensity) {
thisText.size.height.toDp()
}
},
text = "Text"
)
Edit: Intrinsic Measurement is not allowed in LazyList components, have a look at this post, looks like similar to yours.
Jetpack Compose: Row with all items same height
Also, Constraintlayout maybe a good thing to experiment on.
One of the rules of Compose is that you should only measure your children once; measuring children twice throws a runtime exception. However, there are times when you need some information about your children before measuring them.
If you have a look at the Android documentation for Intrinsic Measurements, you will have a clear idea of what to do. In your scenario, you need to force Compose to measure the size of your children to adjust the parent composable's dimensions accordingly.
This medium article gives an easier example on how to use IntrinsicSize in Compose.

Current scroll position value in pixels in LazyColumn Jetpack Compose

I want to have the total scroll position in px in LazyColumn.
The column itself has a ScrollState which has a value (Described in the document as the current scroll position value in pixels), But LazyColumn ScrollState hasn't this field, I want the exact equivalent of Column ScrollState scroll position value for LazyColumn, How I can achieve that with the help of LazyScrollState?
The reason it exists in Column is because it knows about all the items (rows) when it's being generated.
But LazyColumn only displays a portion of the total views at any given moment, and when you scroll, it continuously re-generates the views on the screen (plus a couple above and/or below the visible area), so it never actually calculates the total height of all the rows. If you wanted to get the scroll position, you would have to manually calculate it. If the height of each row is the same, it'll work pretty well. But if the heights are different, then you won't be able to get the exact scroll position (your calculations will fluctuate depending on the height of the rows that are currently displayed). But here's what you have to do to calculate it yourself:
Calculate the total size of all the items
val totalItems = lazyListState.layoutInfo.totalItemsCount
val itemLengthInPx = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull()?.size ?: 0
val totalLengthInPx = totalItems * itemLengthInPx
Calculate the current scroll position
val scrollPos = (lazyListState.firstVisibleItemIndex * itemLengthInPx) / totalLengthInPx
But as I mentioned earlier, this calculation depends on the height of each item (itemLengthInPx), and it works perfectly if it's the same for all the views. But you can see how it'll fluctuate if each view has a different height
The scroll amount can be obtained, no calculation required, in the items themselves, by attaching an onGloballyPosition{ it.positionInParent()} modifier to one or more items.
Then, the items can do what they need to do with their own scroll position, such as offsetting some screen-drawing y coordinate.
Or, if you need the scroll offset in the parent LazyColumn, you could have one item (perhaps an item with zero height, though I've not tested that) at the very top of your list of items, that reports back its position to the parent (perhaps by updating a mutableState that was passed to the item by the parent) whenever it moves.
I had the same need and onGloballyPosition{ it.positionInParent()} addressed it very nicely.
You can get it by firstVisibleItemScrollOffset.
('androidx.activity:activity-compose:1.3.1')
val listState = rememberLazyListState()
val itemHeight = with(LocalDensity.current) { 80.dp.toPx() } // Your item height
val scrollPos = listState.firstVisibleItemIndex * itemHeight + listState.firstVisibleItemScrollOffset
Text(text = "scroll: $scrollPos")
LazyColumn(state = listState) {
// Your items here
}
Also, you can set the scroll position to listState, like this:
LaunchedEffect(key1 = "Key") {
delay(1000) // To show scroll explicitly, set the delay
listState.scrollBy(itemHeight * 2)
}

Calculate maximum itemview height in recyclerview before setting data (onBindViewHolder)

We have horizontal recycler view. Each item view of recycler view contains a textView.
Width of each item view is constant, 100dp. Height is dynamic & we have to set it as per the max data.
List of string is coming from server & hence any data can come. So, e.g. 1st cell can have text of 1 line whereas 2nd cell can have text of 4 lines.
Requirement:
We have to calculate maximum height of the cell (i.e cell consuming max height due to biggest text) and set that maximum height to all cells of recycler view.
This is required because we want height of all item views to be same & also making biggest text visible to user without getting cut (ellipse).
One of the ways that I know:
Before setting adapter, we can iterate the list containing Strings. We can create a dummy textview (invisible to user & width 100 dp). We can set each of the text in the textview & then get height of the textview. We will save the maximum height to adapter while calling setAdapter.
Is this good approach?
Please help.

Categories

Resources