如何在Collapsing Toolbar+Horizontal Pager子Composable中居中Empty State
问题:Collapsing Toolbar展开时Horizontal Pager子项Empty State无法居中
当前Horizontal Pager的子Composable设置了fillMaxHeight,导致Empty State底部区域被截断,无法在Toolbar展开状态下居中显示。考虑两种思路:
- 获取子Composable可见高度计算后设置居中
- 利用滚动行为API处理
解决方案
核心问题在于外层布局的高度设置错误,导致Pager区域实际高度超出屏幕可见范围,Empty State的居中是基于这个超出高度计算,而非可见区域。通过以下调整修复:
- 将包含Tab和Pager的
Column的height(screenHeight)替换为weight(1f),让它占据Header下方的剩余屏幕空间,而非强制设置为屏幕高度。 - 给HorizontalPager添加
fillMaxHeight()修饰符,确保它填满父布局的可用空间,同时保留wrapContentHeight()实现内容自适应。 - 保持Empty State的父容器使用
fillMaxSize()结合contentAlignment = Alignment.Center,此时父容器高度为可见区域高度,Empty State就能正确居中。
修改后的代码示例
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.Button import androidx.compose.material.Tab import androidx.compose.material.TabRow import androidx.compose.material.TabRowDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.nestedscroll import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.pagerTabIndicatorOffset import kotlinx.coroutines.launch @OptIn(ExperimentalFoundationApi::class, ExperimentalPagerApi::class) @Composable fun CenterViewScreen() { BoxWithConstraints { val scrollState = rememberScrollState() Column( modifier = Modifier .fillMaxSize() .verticalScroll(state = scrollState), ) { Box( modifier = Modifier .height(200.dp) .fillMaxWidth() .background(Color.LightGray), contentAlignment = Alignment.Center, ) { Text(text = "HEADER") } // 替换height(screenHeight)为weight(1f),占据剩余空间 Column(modifier = Modifier.weight(1f)) { val tabList = listOf("Tab1", "Tab2") val pagerState = rememberPagerState(initialPage = 0) val coroutineScope = rememberCoroutineScope() TabRow( modifier = Modifier.fillMaxWidth(), backgroundColor = Color.White, contentColor = Color.Black, selectedTabIndex = pagerState.currentPage, indicator = { tabPositions -> TabRowDefaults.Indicator( Modifier.pagerTabIndicatorOffset(pagerState, tabPositions), ) }, ) { tabList.forEachIndexed { index, title -> Tab( text = { Text(title) }, selected = pagerState.currentPage == index, onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }, ) } } HorizontalPager( state = pagerState, pageCount = tabList.size, modifier = Modifier.fillMaxWidth() .fillMaxHeight() // 添加fillMaxHeight确保填满可用空间 .wrapContentHeight() .nestedScroll( remember { object : NestedScrollConnection { override fun onPreScroll( available: Offset, source: NestedScrollSource, ): Offset { return if (available.y > 0) { Offset.Zero } else { Offset( x = 0f, y = -scrollState.dispatchRawDelta(-available.y), ) } } } }, ), ) { page: Int -> when (page) { 0 -> ListLazyColumn(0) 1 -> ListFlowRow(5) } } } } } } @Composable fun ListLazyColumn(itemsCount: Int) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center, ) { if (itemsCount > 0) { LazyColumn(modifier = Modifier.fillMaxSize()) { items(itemsCount) { index -> Button( onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth(), ) { Text(text = "Button $index") } } } } else { Column( Modifier.align(Alignment.Center), horizontalAlignment = Alignment.CenterHorizontally, ) { Image( painter = painterResource(id = R.drawable.e_commerce_01), contentDescription = "empty state", modifier = Modifier.size(120.dp), ) Text( text = "Centering Empty State", style = TextStyle( fontSize = 18.sp, ), ) } } } } @OptIn(ExperimentalLayoutApi::class) @Composable fun ListFlowRow(items: Int) { FlowRow(modifier = Modifier.fillMaxSize()) { repeat(items) { index -> Button( onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth(), ) { Text(text = "Button $index") } } } }
内容的提问来源于stack exchange,提问作者Htoo Aung Hlaing
相关产品推荐
相关产品推荐

