JetPack Compose Scroll together multiple LazyColumn simultaneously - android

I want multiple All LazyColumn scroll simultaneously
I can't use LazyHorizontalGrid or LazyVerticalGrid because of inner layout what two layout is different.
How can i share scrolling in multiple LazyColumn?
#Composable
fun TableScreen2(list: List<Time>, cal: Calendar, df: DateFormat) {
LazyRow(Modifier.fillMaxSize()) {
item {
LazyColumn(
modifier = Modifier
.fillParentMaxHeight()
) {
items(count = list.first().timeList.size / 2) {
Column(
modifier = Modifier
.width(60.dp)
.height(50.dp),
verticalArrangement = Arrangement.Top
) {
Text(df.format(stateCal.time))
stateCal.add(Calendar.MINUTE, 30)
}
}
}
}
items(4) { listIndex ->
LazyColumn(modifier = Modifier.fillParentMaxHeight()) {
itemsIndexed(list[listIndex].timeList) { timeIndex, timeItem ->
Box(
modifier = Modifier
.height(30.dp)
.width(60.dp)
.background(Color.Gray),
contentAlignment = Alignment.Center
) {
Text(text = "$timeIndex")
}
}
}
}
}
}
here is gif

A single LazyColumn, where each entry in the lazy column is a row of 5 items looks like it would fit what you want.

Related

Change Alignment of particular child item in LazyColumn jetpack compose

I am using LazyColumn in my #Compsoable screen. Inside LazyColumn there are so many child and which align verticalArrangement = Arrangement.Top and horizontalAlignment = Alignment.CenterHorizontally. But in one child Item I want to use from Start. Can we do that?
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
) {
item {
ommonContent()
}
item {
HoldDescription()
}
item {
WarningMessage()
}
item {
Devices() // change this item from Start..
}
// more item in here
}
Expected Output
I tried with these answer to Modifier.align(Alignment.Start) but it gives me error
#Composable
fun Devices(
isEmpty: Boolean,
) {
AnimatedVisibility(
isEmpty,
modifier = Modifier.align(Alignment.Start)
) {
Text()
}
}
Error in Image
To apply the align modifier you can scope your composable with the required scope.
You can use:
#Composable
fun ColumnScope.Devices(
isEmpty: Boolean,
) {
AnimatedVisibility(
isEmpty,
modifier = Modifier.fillMaxWidth().align(Alignment.Start)
) {
Text("xxx")
}
}
Otherwise you can use:
#Composable
fun Devices(
modifier: Modifier,
isEmpty: Boolean,
) {
AnimatedVisibility(
isEmpty,
modifier = modifier
) {
Text("xxx")
}
}
and then
item(){
Column() {
Devices(
modifier = Modifier.fillMaxWidth().align(Alignment.Start),
isEmpty = true)
}
}

Jetpack compose LazyGridView not scroll on Column

When trying to put a LazyVerticalGrid inside a scrollable Column I get the following error:
java.lang.IllegalStateException: Nesting scrollable in the same direction layouts like LazyColumn and Column(Modifier.verticalScroll()) is not allowed. If you want to add a header before the list of items please take a look on LazyColumn component which has a DSL api which allows to first add a header via item() function and then the list of items via items().
I am not making a traditional list, I just have alot of elements that are too big to fit on the screen. Therefore I want the column to scroll so I can see all the elements. Here is my code:
you need to use an item with a span attribute. Assume that your grid view has three items in every row, you can put your item wherever you want with the scrollable screen.
LazyVerticalGrid(cells = GridCells.Fixed(4)) {
item(span = { GridItemSpan(4) }) { Header() }
item(span = { GridItemSpan(4) }) { AnotherView() }
items(gridItems) { GridItemView(it) }
}
If you want to keep some UI elements sticky at the top or bottom, you can play with the Modifier. weight(), for example:
#Composable
fun SomeScreenContent() {
val gridItems = List(30){ it.toString() }
Column(modifier = Modifier.fillMaxSize()) {
SomeTopContent(modifier = Modifier.weight(0.2f))
LazyVerticalGrid(
modifier = Modifier.weight(0.6f),
columns = GridCells.Fixed(4),
contentPadding = PaddingValues(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(gridItems) { item ->
GridItem(item)
}
}
SomeBottomContent(modifier = Modifier.weight(0.2f))
}
}
#Composable
fun SomeTopContent(modifier:Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.background(Color(0xff5077FC)),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(text = "Top")
}
}
#Composable
fun SomeBottomContent(modifier:Modifier = Modifier) {
Row(
modifier = modifier
.fillMaxWidth()
.background(Color(0xff4EE180)),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(text = "Bottom")
}
}
#Composable
fun GridItem(item: String) {
Card(modifier = Modifier.size(100.dp)) {
Text(text = item)
}
}
Or just use the Scaffold composable function...

Jetpack compose - lazycolumn fillMaxHeight modifier hides widgets below, but not destroying widgets above

I'm trying to build a simple chat screen, with a header, a footer (text field) and the messages part which is a lazycolumn. I've seen many people using such methods like the ones below: (fill parent max height, size etc.)
https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/LazyItemScope
All I can put in lazycolumn modifiers is fillMaxHeight, width or size, if I use fillMaxHeight, it destroys the footer, if I don't use anything, the lazycolumn expands until the bottom of the screen, so it does the same behaviour. What am I doing wrong? Why does it behave like this? I can't put images because I don't have enough reputation...
Here is the full code:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Surface() {
Column(Modifier.background(Color.Green)) {
ProfileCard("Kate", "Available")
Conversation(messages = SampleData.conversationSample)
SimpleTextField()
}
}
}
}
}
#Composable
fun Conversation(messages: List<Message>) {
LazyColumn(
modifier = Modifier
.background(color = MainBg).fillMaxHeight(),
reverseLayout = true,
) {
items(messages) { message ->
MessageCard(message)
}
}
}
#Composable
fun MessageCard(message: Message) {
var isExpanded by remember { mutableStateOf(false) }
Column() {
Text(
text = message.message,
color = com.boradincer.hellojetpack.ui.theme.PrimaryText,
modifier = Modifier
.padding(vertical = 4.dp, horizontal = 16.dp)
.clip(RoundedCornerShape(4.dp))
.background(color = LightBg)
.clickable { isExpanded = !isExpanded }
.padding(horizontal = 8.dp, vertical = 5.dp),
maxLines = if (isExpanded) Int.MAX_VALUE else 2
)
}
}
Apply Modifier.weight(1f) to the LazyColumn
Column(){
Header()
LazyColumn(Modifier.weight(1f)) {
//....
}
Footer()
}
Using fillMaxHeight() the modifier will make the LazyColumn fill the whole available height.
The weight modifier requires a ColumnScope.
In your case use the modifier as parameter:
#Composable
fun Conversation(
modifier: Modifier = Modifier,
messages: List<Message>
){
LazyColumn(modifier) {
//...
}
}
Column(){
//
Conversation(
modifier = Modifier.weight(1f),
messsages = list
) {
//....
}
}

Swipe to refresh is not working if LazyGridView has no child in compose

I'm using SwipeRefresh view in compose (from accompanist). I have LazyVerticalGrid inside it, and grid populates paging data from network. If there's no content in paging data, i'm showing empty state view. When there's some data, swipe-to-refresh is working. Issue is, i'm not able to do swipe-to-refesh in LazyVerticalGrid if there's no data, but same is working in LazyColumn (both case has NoContentView shown).
#Composable
fun GridItems(
searchViewModel: SearchViewModel
) {
var isRefreshing by remember { mutableStateOf(false) }
val posts = remember { searchViewModel.posts }.collectAsLazyPagingItems()
Scaffold(
topBar = { MyTopBar() }
) { innerPadding ->
SwipeRefresh(
state = rememberSwipeRefreshState(isRefreshing = isRefreshing),
onRefresh = { searchViewModel.getPosts() }
) {
Column(modifier = Modifier.padding(innerPadding)) {
LazyVerticalGrid(
cells = GridCells.Fixed(3),
modifier = modifier.padding(horizontal = 3.dp)
) {
items() {
MySinglePostItem()
}
posts.apply {
when {
//Other loadState here
// Show below view if no item is present in paging data
loadState.refresh is LoadState.NotLoading && loadState.append.endOfPaginationReached && posts.itemCount < 1 -> {
NoContentView(Modifier.fillMaxSize())
}
}
}
}
}
}
}
}
#Composable
fun NoContentView(modifier: Modifier = Modifier) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
modifier = Modifier.size(48.dp),
painter = painterResource(id = R.drawable.ic_outlined_image_no_content)
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(id = R.string.empty_posts_message),
fontSize = 15.sp
)
}
}
}
As Accompanist states in its documentation SwipeRefresh needs some content that is scrollable in order to be able to react to swipe gestures.
So perhaps having too few elements Compose automatically makes a LazyColumn/LazyVerticalGrid non-scrollable in order to optimize things?
My best guess would be to show a Scrollable-Column when you have no items to show and a LazyVerticalGrid otherwise.
SwipeRefresh(...) {
if (loadState.refresh is LoadState.NotLoading && loadState.append.endOfPaginationReached && posts.itemCount < 1) {
Column(Modifier.verticalScroll(rememberScrollState())) {
NoContentView(Modifier.fillMaxSize())
}
} else {
LazyVerticalGrid(...) {
// ...
}
}
}

How to make a lazy column item occupy the complete height in Jetpack compose?

I am trying to work with the compose lazy column, i want each item of my lazy column to have the maximum height , I tried the below code but it is not giving the expected result
Code
val itemsList: List by mainScreenViewModel.portfolioItems.observeAsState(listOf())
Box(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.matchParentSize()) {
LazyColumn(
content = {
itemsIndexed(itemsList) { index, item ->
Text(text = "Hello", modifier = Modifier.fillMaxHeight())
}
},
)
}
}
fillMaxHeight()/fillMaxWidth() do not work correctly for vertical and horizontal scrolling list respectively. Instead we can use fillParentHeight() and fillParentWidth() respectively provided in LazyItemScope.
Sample Code:
LazyColumn(
modifier = modifier.fillMaxHeight()) {
items(count = 3) {
Column(modifier = Modifier.fillParentMaxHeight()) {
Text(
text = "Item $it",
modifier = Modifier.fillMaxWidth()
)
Divider(Modifier.height(2.dp))
}
}
}
Refer for more details: https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/LazyItemScope

Categories

Resources