概览
Compose提供了多个api用来实现各种手势,这些手势包括点击、按压、双击、长按、水平垂直滑动、拖动、双指平移缩放旋转、嵌套欢动效果
各种手势效果介绍
点击手势
代码
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Box(modifier = Modifier
.size(200.dp)
.background(Color.Green)
.clickable {
App.toast("被点击")
}, contentAlignment = Alignment.Center
) {
Text(text = "点击事件")
}
}
效果
单点、按压、双击、长按
代码
@Composable
fun PointerView() {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Box(
modifier = Modifier
.size(200.dp)
.background(Color.Green)
.pointerInput(Unit) {
detectTapGestures(
onTap = {
App.toast("单点事件触发")
},
onDoubleTap = {
App.toast("双击事件")
},
onPress = {
// App.toast("按压事件")
},
onLongPress = {
App.toast("长按事件")
}
)
}, contentAlignment = Alignment.Center
) {
Text(text = "单点、双击、按压、长按事件")
}
}
}
说明
双击、单击、长按都会触发按压的效果回调, pointerInput.detectTapGestures
效果
水平和垂直滑动
代码
val list = (0..255)
Column(
Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
Box(
Modifier
.fillMaxWidth(10f)
.height(100.dp)
.background(Color.Green)
.horizontalScroll(rememberScrollState()),
contentAlignment = Alignment.Center
) {
Text(
text = "安安安安卓,欢迎关注掘金号、公众号、csdn,分享android相关知识,安安安安卓,欢迎关注掘金号、公众号、csdn,分享android相关知识,安安安安卓,欢迎关注掘金号、公众号、csdn,分享android相关知识",
style = TextStyle(color = Color.White, fontSize = 20.sp, fontWeight = FontWeight.Bold)
)
}
repeat(40) {
Box(
Modifier
.height(80.dp)
.fillMaxWidth()
.background(Color(list.random(), list.random(), list.random())),
contentAlignment = Alignment.Center
) {
Text(text = it.toString(), style = TextStyle(color = Color.White, fontSize = 20.sp))
}
}
}
说明
任何控件,只需要调用一下两个修饰符就可以实现滑动效果
.verticalScroll(rememberScrollState())
.horizontalScroll(rememberScrollState())
效果
拖动手势
代码
var offsetX by remember {
mutableStateOf(0f)
}
var offsetY by remember {
mutableStateOf(0f)
}
Box(Modifier.fillMaxSize()) {
Box(
Modifier
.offset { IntOffset(offsetX.toInt(), offsetY.toInt()) }
.size(200.dp)
.background(Color.Green, shape = CircleShape)
.pointerInput(Unit) {
detectDragGestures(onDrag = { pointerInputChange: PointerInputChange, offset: Offset ->
pointerInputChange.consumeAllChanges()//消费滑动
offsetX += offset.x
offsetY += offset.y
})
},
contentAlignment = Alignment.Center
) {
Text(text = "轻按滑动圆")
}
}
说明
效果
多段滑动
代码
val list = (0..255)
val width = 300.dp
val squareSize = 60.dp
val swipeableState = rememberSwipeableState(0)
val sizePx = with(LocalDensity.current) { squareSize.toPx() }
val anchors = mapOf(
0f to 0,
sizePx to 1,
sizePx * 2 to 2,
sizePx * 3 to 3,
sizePx * 4 to 4
) // Maps anchor points (in px) to states
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Row(
Modifier
.width(width)
.height(squareSize)) {
repeat(5) {
Box(
Modifier
.width(squareSize)
.fillMaxHeight()
.background(color = Color(list.random(), list.random(), list.random()))
)
}
}
Box(
modifier = Modifier
.width(width)
.swipeable(
state = swipeableState,
anchors = anchors,
thresholds = { _, _ -> FractionalThreshold(0.3f) },
orientation = Orientation.Horizontal
)
) {
Box(
Modifier
.offset { IntOffset(swipeableState.offset.value.roundToInt(), 0) }
.width(squareSize)
.height(200.dp)
.background(Color.Yellow)
){
Text(text = "滑动滑块")
}
}
}
说明
这是个实验性质的代码
这里的关键代码如下: 这个anchors会把父容器分为五段,当滑动结束,滑动控件会自动平移到合适的区域位置。
val anchors = mapOf(
0f to 0,
sizePx to 1,
sizePx * 2 to 2,
sizePx * 3 to 3,
sizePx * 4 to 4
)
效果
双指手势(平移、缩放、旋转)
代码
var scale by remember { mutableStateOf(1f) }
var rotation by remember { mutableStateOf(0f) }
var offset by remember { mutableStateOf(Offset.Zero) }
val state = rememberTransformableState { zoomChange, offsetChange, rotationChange ->
scale *= zoomChange
rotation += rotationChange
offset += offsetChange
}
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Box(
Modifier
// apply other transformations like rotation and zoom
// on the pizza slice emoji
.graphicsLayer(
scaleX = scale,
scaleY = scale,
rotationZ = rotation,
translationX = offset.x,
translationY = offset.y
)
// add transformable to listen to multitouch transformation events
// after offset
.transformable(state = state)
.background(Color.Green)
.fillMaxSize(0.5f),
contentAlignment = Alignment.Center
){
Text(text = "两指操作,平移,缩放,z轴旋转,单指操作不会有效果", color = Color.White)
}
}
说明
效果
嵌套滑动效果
代码
val toolbarHeight = 48.dp//Topbar的高度
val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() }//topbar高度转换为px
val toolbarOffsetHeightPx =
remember { mutableStateOf(0f) }//topbar的动态垂直平移距离
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y
val newOffset = toolbarOffsetHeightPx.value + delta//更新topbar的动态平移距离
toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)//保证topbar的平移距离在(-toolbarHeightPx, 0f)之间
return Offset.Zero
}
}
}
Box(
Modifier
.fillMaxSize()
.nestedScroll(nestedScrollConnection)
) {
LazyColumn(contentPadding = PaddingValues(top = toolbarHeight)) {
items(100) { index ->
Text("I'm item $index", modifier = Modifier
.fillMaxWidth()
.padding(16.dp))
}
}
TopAppBar(
modifier = Modifier
.height(toolbarHeight)
.offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) },
title = { Text("toolbar offset is ${toolbarOffsetHeightPx.value}") }
)
}
说明
效果
git地址:github.com/ananananzhu…