I want to have an appbar in the top of my screen which have two lines:
I wish to implement the above in a scaffold. Following is the code I have written so far.
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun NestedScrollTest() {
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
TopAppBar(
title = { Text(text = "Scroll Behavior Test") },
navigationIcon = {
IconButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Default.Menu, contentDescription = "")
}
},
scrollBehavior = scrollBehavior
)
}
) {
MyTabRowNew()
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.padding(top = it.calculateTopPadding() + 56.dp)) {
items((1..50).toList()) { item ->
Text(modifier = Modifier.padding(8.dp), text = "Item $item")
}
}
}
}
@Composable
fun MyTabRowNew(){
var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3 with lots of text")
Column(
modifier = Modifier.padding(top = 64.dp)
) {
TabRow(selectedTabIndex = state) {
titles.forEachIndexed { index, title ->
Tab(
selected = state == index,
onClick = { state = index },
text = { Text(text = title, maxLines = 2, overflow = TextOverflow.Ellipsis) }
)
}
}
}
}
With this code, the TopAppBar collapses, but the TabBar does not and so looks odd How can I collapse TabBar too along with TopAppBar, when I scroll in LazyColumn.
Thanks
You can actually acheive this with a combination of LazyColumnState and AnimateVisibility. first you need to add this Composable function in your project somewhere:
@Composable
fun LazyListState.isScrollingUp(): Boolean {
var previousIndex by remember(this) { mutableStateOf(firstVisibleItemIndex) }
var previousScrollOffset by remember(this) { mutableStateOf(firstVisibleItemScrollOffset) }
return remember(this) {
derivedStateOf {
if (previousIndex != firstVisibleItemIndex) {
previousIndex > firstVisibleItemIndex
} else {
previousScrollOffset >= firstVisibleItemScrollOffset
}.also {
previousIndex = firstVisibleItemIndex
previousScrollOffset = firstVisibleItemScrollOffset
}
}
}.value
}
what this does it simply detects if the LazyColumn is being scrolled up . now that you have this its simple you just need to detect if the LazyColumn is being Scrolled up if True show the TopBars if not hide them:
val lazyColumnState = rememberLazyListState()
Scaffold(modifier = Modifier.fillMaxSize(),
topBar = {
AnimatedVisibility(visible = lazyColumnState.isScrollingUp()) {
TopAppBar(
title = { Text(text = "Scroll Behavior Test") },
navigationIcon = {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = ""
)
}
}
)
}
}
) { paddingValues ->
//second top bar
Column(modifier = Modifier
.fillMaxSize()
.padding(paddingValues)) {
AnimatedVisibility(visible = lazyColumnState.isScrollingUp()) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(40.dp)
) {
Button(onClick = { /*TODO*/ }, colors = ButtonDefaults.buttonColors(containerColor = Color.Red)) {
Text(text = "5")
}
}
}
LazyColumn(
modifier = Modifier
.fillMaxSize() ,
state = lazyColumnState
) {
items(50) {
Text(
text = it.toString(), modifier = Modifier
.fillMaxWidth()
.height(30.dp)
)
}
}
}
}