1.从 Swipeable 迁移到 AnchoredDraggable
效果
使用 anchoredDraggable修饰符
DrawerState 定义抽屉起始状态
sealed interface DrawerState {
data object Open : DrawerState
data object Closed : DrawerState
}
定义DrawerStateSaver保持当前抽屉状态
private val DrawerStateSaver = Saver<DrawerState, String>(save = {
when (it) {
is DrawerState.Open -> "Open"
is DrawerState.Closed -> "Closed"
}
}, restore = {
when (it) {
"Open" -> DrawerState.Open
"Closed" -> DrawerState.Closed
else -> DrawerState.Closed // 默认值
}
})
使用offset/anchoredDraggable修饰符来进行拖拽平移效果
摆脱使用Modifier.draggable()
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun MineScreen(modifier: Modifier = Modifier) {
val context = LocalContext.current
val density = LocalDensity.current
//关闭状态时,剩余60.dp
val drawerWidthClosed = remember(context) {
with(density) { 60.dp.toPx() }
}
val drawerWidthOpen = remember(context) {
min(
context.resources.displayMetrics.widthPixels,
context.resources.displayMetrics.heightPixels
) * 0.6f
}
//创建一个拖拽锚点实例
val anchors = remember {
DraggableAnchors {
//完全打开
DrawerState.Open at 0f
//关闭剩余
DrawerState.Closed at drawerWidthOpen - drawerWidthClosed
}
}
//保持抽屉状态
val drawerState = rememberSaveable(saver = DrawerStateSaver) {
DrawerState.Closed
}
//定义AnchoredDraggableState
val state =
remember {
AnchoredDraggableState(
initialValue = drawerState,
anchors = anchors
)
}
//定义flingBehavior
//默认位置阈值 50%
val flingBehavior = AnchoredDraggableDefaults.flingBehavior(
state = state, animationSpec = spring(dampingRatio = 0.4f, stiffness = 400f)
)
val scope = rememberCoroutineScope()
//抽屉开闭
fun toggleDrawerState() {
scope.launch {
if (state.currentValue == DrawerState.Open) {
state.animateTo(
DrawerState.Closed,
//给一个回弹动画
animationSpec = spring(dampingRatio = 0.6f)
)
} else {
state.animateTo(DrawerState.Open)
}
}
}
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.onSurface),
) {
//主界面内容
Box(){}
//定义抽屉组件
Box(
modifier = Modifier
.fillMaxHeight()
.width(with(density) { drawerWidthOpen.toDp() })
.then(modifier)
.offset {
//读取偏移量
IntOffset(x = state.requireOffset().toInt(), y = 0)
}
.graphicsLayer {
//打开状态阴影
shadowElevation = if (state.currentValue == DrawerState.Open) 16f else 0f
// translationX = state.requireOffset()
val scale = lerp(0.9f, 0.5f, state.requireOffset() / drawerWidthOpen)
scaleY = scale
}
.anchoredDraggable(
state = state,
orientation = Orientation.Horizontal,
flingBehavior = flingBehavior
)
.align(Alignment.CenterEnd)
.background(
MaterialTheme.colorScheme.tertiary,
shape = RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp)
)
) {
Column(
modifier = Modifier
.fillMaxSize()
.clickable {
toggleDrawerState()
}
.padding(10.dp)
) {
Icon(
modifier = Modifier
.padding(bottom = 10.dp)
.size(20.dp)
.clickable {
toggleDrawerState()
},
imageVector = Icons.Default.Menu,
contentDescription = "menu",
tint = Color.White
)
Text(
"阿斯埃苏阿斯埃苏阿斯埃苏" + "阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏" + "阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯" + "埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏阿斯埃苏",
color = Color.White
)
}
}
}
}