Android Compose實現(xiàn)伸縮ToolBar的思路詳解
ScrollableAppBar
效果圖

- 當列表向上移動時,會先帶動ToolBar向上位移,等ToolBar向上移動到最大位移量時列表向上滑動
- 當列表向下移動時,會先帶動ToolBar向下位移,等ToolBar向下移動到最大位移量時列表向下滑動
主要思路
布局預覽
伸縮前布局:

伸縮后布局:

實現(xiàn)過程
布局實現(xiàn)
首先我們要定義兩個尺寸變量
// 應用欄高度 private val toolBarHeight = 56.dp // 導航圖標大小 private val navigationIconSize = 50.dp
我們采用Box作為根布局,里面主要包含三個部分,背景圖片,頂部的TooBar以及下面的Title部分,其實現(xiàn)如下
//整體布局實現(xiàn)
Box(modifier = Modifier
.height(scrollableAppBarHeight) //scrollableAppBarHeight 為高度參數(shù),為外部獲取
.fillMaxWidth()
) {
Image(painter = painterResource(id = backgroundImageId), contentDescription = "background", contentScale = ContentScale.FillBounds)
// 自定義應用欄
Row(
modifier = modifier
.height(toolBarHeight) //設置高度為toolBarHeight
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically //設置垂直方向為居中對齊
) {
// 導航圖標
Box(modifier = Modifier.size(navigationIconSize),contentAlignment = Alignment.Center) {
navigationIcon()
}
}
// title定義
Box(
modifier = Modifier
.height(toolBarHeight) //和ToolBar同高
.fillMaxWidth()
.align(Alignment.BottomStart),
contentAlignment = Alignment.CenterStart
) {
Text(text = title,
color = Color.White,
modifier = Modifier.padding(start = 20.dp).matchParentSize(), // 使用 matchParentSize 修飾符保證不影響父 Box尺寸
fontSize = 20.sp
)
}
}
我們主要講解title部分
// title定義
Box(
modifier = Modifier
.height(toolBarHeight) //和ToolBar同高
.fillMaxWidth()
.align(Alignment.BottomStart),
contentAlignment = Alignment.CenterStart
) {
Text(text = title,
color = Color.White,
modifier = Modifier.padding(start = 20.dp).matchParentSize(), // 使用 matchParentSize 修飾符保證不影響父 Box尺寸
fontSize = 20.sp
)
}
首先為了保證title部分在完全收縮后高度和toolBar部分一致,我們設置Box布局高度為toolBarHeight
modifier = Modifier
.height(toolBarHeight) //和ToolBar同高
.fillMaxWidth()
然后定義Box在根布局里面的對齊方式為Alignment.BottomStart
modifier = Modifier
.height(toolBarHeight) //和ToolBar同高
.fillMaxWidth()
.align(Alignment.BottomStart)
之所以這樣設置,是因為我們通過觀察伸縮前和伸縮后的預覽圖可以知道如果保證此部分是底部左邊對齊,那么在根布局向上移動的過程中我們便可以只關心此部分在水平方向的位移即可
接著設置文本部分的對齊方式,保證title是居中靠左對齊的
contentAlignment = Alignment.CenterStart
位移實現(xiàn)
首先,我們要明確ScrollableAppBar最大向上偏移量等于其定義的高度和收縮后的高度,即toolBarHeight的差值,即:
// 應用欄最大向上偏移量
val maxOffsetHeightPx = with(LocalDensity.current) { scrollableAppBarHeight.roundToPx().toFloat() - toolBarHeight.roundToPx().toFloat() }
其次,title部分在水平方向的位移距離其實就是導航圖標的寬度,即:
// Title 偏移量參考值
val titleOffsetWidthReferenceValue = with(LocalDensity.current) { navigationIconSize.roundToPx().toFloat() }
同時需要定義從外部獲取到的偏移量
val toolbarOffsetHeightPx: MutableState<Float> //向上偏移量
最外層布局位移定義
為根布局添加垂直方向上的位移
@Composable
fun ScrollableAppBar(
modifier: Modifier = Modifier,
title: String = stringResource(id = R.string.app_name), //默認為應用名
navigationIcon: @Composable () -> Unit, //導航圖標
@DrawableRes backgroundImageId: Int, // 背景圖片
scrollableAppBarHeight: Dp, //定義的ScrollableAppBar高度
toolbarOffsetHeightPx: MutableState<Float> //向上偏移量
) {
Box(modifier = Modifier
.height(scrollableAppBarHeight)
.offset {
IntOffset(
x = 0,
y = toolbarOffsetHeightPx.value.roundToInt() //設置偏移量
)
}
.fillMaxWidth()
) {
.... // 背景圖等內(nèi)容
}
}
toolBar垂直方向位置不變的實現(xiàn)
設置和父布局相反的位移量保證toolBar處于原位置,即:
// 自定義應用欄
Row(
modifier = modifier
.offset {
IntOffset(
x = 0,
y = -toolbarOffsetHeightPx.value.roundToInt() //保證應用欄是始終不動的
)
}
.height(toolBarHeight)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
... // 導航圖標
}
title水平位移的實現(xiàn)
為了保證title均勻向右位移,用根布局此時向上位移量和最大位移量的商再乘以水平方向上的總位移即可:
x = -((toolbarOffsetHeightPx.value / maxOffsetHeightPx) * titleOffsetWidthReferenceValue).roundToInt()
完整實現(xiàn)
// title部分
Box(
modifier = Modifier
.height(toolBarHeight) //和ToolBar同高
.fillMaxWidth()
.align(Alignment.BottomStart)
.offset {
IntOffset(
x = -((toolbarOffsetHeightPx.value / maxOffsetHeightPx) * titleOffsetWidthReferenceValue).roundToInt(), //水平方向位移
y = 0
)
},
contentAlignment = Alignment.CenterStart
) {
... //title部分
}
項目地址
ScrollableAppBar 如果項目對你有所幫助,如果有改進意見還可以提交 issue
到此這篇關于Android Compose實現(xiàn)伸縮ToolBar的思路詳解的文章就介紹到這了,更多相關Android 伸縮ToolBar內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android編程學習之抽象類AbsListView用法實例分析
這篇文章主要介紹了Android編程學習之抽象類AbsListView用法,較為詳細的分析了抽象類AbsListView的功能、結構、定義及使用注意事項等,需要的朋友可以參考下2015-10-10
android ViewPager實現(xiàn)自動無限輪播和下方向?qū)A點
本篇文章主要介紹了android ViewPager實現(xiàn)自動輪播和下方向?qū)A點,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02

