Jetpack Compose DropdownMenu手指跟随点击显示

 更新时间:2022年11月17日 14:09:17   作者:九狼  
这篇文章主要为大家介绍了Jetpack Compose DropdownMenu手指跟随点击位置显示实现方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

DropdownMenu显示时默认会避开点击的view 通常默认显示在左下方

本篇文章教你实现跟随手指按下位置显示

效果图

实现方法

首先要获取到点击的位置之后计算偏移量

先分析两种offset参数

1使用DropdownMenu的offset参数

获取到点击的位置之后计算偏移量, DropdownMenu的offset参数

@Composable
fun DropdownMenu(
    ...
    offset: DpOffset = DpOffset(0.dp, 0.dp)
    ...
)

这种方法比较麻烦,要反向计算偏移量,因为初始位置(x,y)轴的原点在左下角,而不是左上角

2Modifier.offset

将DropdownMenu嵌套在Box里面,调用BoxD的Modifier.offset()改变DropdownMenu的显示位置
这种方案的的初始位置(x,y)轴的原点在左上角
点击的位置就是DropdownMenu的偏移量,

获取到点击的位置

层级结构

Box{
  card()
  Box{
     DropdownMenu()
  }
}

Box创建用于监听点击事件修饰符

在最外层的Box创建一个用于监听点击事件的修饰符,来捕获点击位置

val animatedOffset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }
Box(
    modifier = Modifier
        .fillMaxWidth()
        .pointerInput(Unit) {
            coroutineScope {
                while (true) {
                    //获取点击位置
                    val boxOffset = awaitPointerEventScope {
                        awaitFirstDown().position
                    }
                    //显示DropdownMenu
                    expanded = true
                    launch {
                        animatedOffset.animateTo(
                            boxOffset,
                            animationSpec = spring(stiffness = Spring.StiffnessLow)
                        )
                    }
                }
            }
        }
) 

DropdownMenu外层的Box()设置偏移量

Box(modifier = Modifier.offset {
    IntOffset(
        animatedOffset.value.x.roundToInt(),
        animatedOffset.value.y.roundToInt()
    )
} ) {
    DropdownMenu()
    }

完整代码

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun FullContent(
    modifier: Modifier,
    context: String
) {
    var expanded by remember { mutableStateOf(false) }
    val animatedOffset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .pointerInput(Unit) {
                coroutineScope {
                    while (true) {
                        //获取点击位置
                        val boxOffset = awaitPointerEventScope {
                            awaitFirstDown().position
                        }
                        expanded = true
                        launch {
                            animatedOffset.animateTo(
                                boxOffset,
                                animationSpec = spring(stiffness = Spring.StiffnessLow)
                            )
                        }
                    }
                }
            }
    ) {
        Card(modifier = modifier
            .fillMaxWidth(),
            border = BorderStroke(2.dp, CustomTheme.colors.divider)        
        ) {
            Text(
                text = context,
                modifier = Modifier.padding(6.dp),
                fontSize = 17.sp,
                fontWeight = FontWeight.Normal,
            )
        }
        Box(modifier = Modifier.offset {
            IntOffset(
                animatedOffset.value.x.roundToInt(),
                animatedOffset.value.y.roundToInt()
            )
        } ) {
            DropdownMenu(
                expanded = expanded,
                onDismissRequest = { expanded = false }
            ) {
                DropdownMenuItem(
                    text = {
                        Text(stringResource(id = R.string.app_copy))
                    },
                    onClick = {
                    })
                DropdownMenuItem(
                    text = {
                        Text(stringResource(id = R.string.app_copy))
                    },
                    onClick = {
                    })
                Divider()
                DropdownMenuItem(
                    text = {
                        Text(stringResource(id = R.string.app_copy))
                    },
                    onClick = {
                    })
            }
        }
    }
}

使用方法

FullContent(
    modifier = Modifier.fillMaxWidth(),
    context = "悄悄的我走了,
正如我悄悄的来;
我挥一挥衣袖,
不带走一片云彩。"
)

以上就是Jetpack Compose DropdownMenu手指跟随点击显示的详细内容,更多关于Jetpack Compose DropdownMenu的资料请关注脚本之家其它相关文章!

相关文章

  • Android编程实现设置按钮背景透明与半透明及图片背景透明的方法

    Android编程实现设置按钮背景透明与半透明及图片背景透明的方法

    这篇文章主要介绍了Android编程实现设置按钮背景透明与半透明及图片背景透明的方法,结合实例形式较为详细的分析了Button及ImageButton的背景属性设置技巧,非常简单实用,需要的朋友可以参考下
    2015-12-12
  • Android实现可播放GIF动画的ImageView

    Android实现可播放GIF动画的ImageView

    这篇文章主要为大家详细介绍了Android实现可播放GIF动画的ImageView,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • Android DynamicGrid实现拖曳交换位置功能

    Android DynamicGrid实现拖曳交换位置功能

    这篇文章主要为大家详细介绍了Android DynamicGrid实现拖曳交换位置功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • Android音视频开发之MediaExtactor使用教程

    Android音视频开发之MediaExtactor使用教程

    MediaExtactor在Android音视频开发中负责提取音视频信息和数据流的功能,可以通过该类实现从多媒体文件中剥离得到音频和视频的能力。本文将详细为大家介绍一下它的使用,感兴趣的可以了解一下
    2022-04-04
  • 内存泄漏检测工具LeakCanary源码解析

    内存泄漏检测工具LeakCanary源码解析

    这篇文章主要为大家介绍了内存泄漏检测工具LeakCanary源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Kotlin协程操作之创建启动挂起恢复详解

    Kotlin协程操作之创建启动挂起恢复详解

    本文的定位是协程的创建、启动、挂起、恢复,也会示例一些简单的使用,这里不对suspend讲解,,也不对协程的高级用法做阐述(热数据通道Channel、冷数据流Flow...),本文主要讲协程稍微深入的全面知识
    2022-08-08
  • Android创建外部lib库及自定义View的图文教程

    Android创建外部lib库及自定义View的图文教程

    这篇文章主要给大家介绍了关于Android创建外部lib库及自定义View的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • 轻松实现可扩展自定义的Android滚轮时间选择控件

    轻松实现可扩展自定义的Android滚轮时间选择控件

    这篇文章主要为大家详细介绍了可扩展自定义的Android滚轮时间选择控件,结合WheelView实现滚轮选择日期操作,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • Android 仿微博的点赞功能的实现原理(持续点赞再取消)

    Android 仿微博的点赞功能的实现原理(持续点赞再取消)

    经常玩微博的同志都知道,微博的持续点赞再取消功能,下面小编给大家带来了Android 仿微博的点赞功能的实现原理(持续点赞再取消),感兴趣的朋友跟随脚本之家小编一起看看吧
    2018-03-03
  • Android studio实现菜单操作

    Android studio实现菜单操作

    这篇文章主要为大家详细介绍了Android studio实现菜单操作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10

最新评论