如何关闭在单击通常展开它的按钮时无法聚焦的展开下拉菜单

How to dismiss an expanded drop down menu that is not focusable when clicking the button that normally expands it

提问人:mpellegr 提问时间:11/10/2023 更新时间:11/15/2023 访问量:48

问:

赏金将于明天到期。这个问题的答案有资格获得 +50 声望赏金。Mpellegr希望引起人们对这个问题的更多关注

我有一个按钮可以展开我的可组合项中的下拉菜单。我将下拉菜单设置为不使用焦点(我必须这样做,以便在展开下拉菜单时键盘不会被关闭)。现在我遇到了一个问题,即在菜单已经展开时单击展开按钮以显示菜单会导致两次重组,导致菜单仍然被展开并且没有按预期关闭。第一次重构时,它会关闭菜单并将我的 rememebered 值设置为 false。然后,当调用按钮的 lambda 时,将设置回 true,从而导致第二次重组,再次展开菜单。如果菜单已展开,如何允许通过单击展开按钮来关闭菜单?PopupProperties(focusable = false)expandedonClickexpanded

var expanded by remember { mutableStateOf(false) }
Box() {
    IconButton(onClick = { expanded = true })
    DropdownMenu(
        expanded = expanded,
        onDismissRequest = { expanded = false },
        properties = PopupProperties(focusable = false)
    )
}
拉菜单 android-jetpack-compose

评论

1赞 Ahsan Ullah Rasel 11/15/2023
您可以通过检查扩展状态是否为 false 来将扩展状态分配给 true。如果为 false,则赋值为 true。如果为 true,则忽略。或者,您也可以引入 which 仅在您的值从一种状态更改为另一种状态时才会重组。否则,它不会重构。derivedStateOf
0赞 mpellegr 11/16/2023
@AhsanUllahRasel 不幸的是,第一种方法不起作用,因为在注册点击时立即设置为 false,它将始终为 false。出于同样的原因,我认为第二种方法行不通。我都尝试过,所以任何建议都值得赞赏。expandedonDismissRequest
0赞 mpellegr 11/16/2023
我发现的最佳解决方案是引入使用 100 毫秒的延迟。这通常效果很好,但似乎非常棘手。如果用户在展开菜单时单击该按钮,它实际上不会再次展开菜单。由于这应该比 100 毫秒更快,我认为这可以工作。System.currentTimeMillis()
0赞 Phil Dukhov 11/16/2023
对我来说看起来像一个错误,因为弹出窗口注册了点击,它不应该传递到视图。我建议您在问题跟踪器上创建一个错误报告,同时延迟解决方法听起来不错。
0赞 mpellegr 11/17/2023
@PhilDukhov我以为这是按预期工作的,因为菜单没有焦点,这难道不意味着其他任何可聚焦的东西都会对用户输入做出反应吗?
1赞 Phil Dukhov 11/17/2023
@mpellegr根据文档,focusable 应该只控制“IME 事件和按键”。

答:

1赞 mpellegr 11/21/2023 #1

我能找到的唯一解决方案是一个棘手的解决方法,即在对单击按钮做出反应之前使用 100 毫秒的延迟。在大多数情况下效果很好,但真正快速的点击似乎“什么都不做”。

    var dismissedTimeMillis by remember { mutableStateOf<Long?>(null) }
    var expanded by remember { mutableStateOf(false) }
    Box() {
       IconButton(onClick = 
           dismissedTimeMillis.let {
               if (it == null || (System.currentTimeMillis() - it) > 100L) {
                   expanded = true
               }
           })
       DropdownMenu(
           expanded = expanded,
           onDismissRequest = { 
               expanded = false 
               dismissedTimeMillis = System.currentTimeMillis()
           },
           properties = PopupProperties(focusable = false)
       )
   }
0赞 Phil Dukhov 11/21/2023 #2

这看起来像一个错误,因为根据文档,focusable 应该只控制“IME 事件和按键”。

因此,延迟解决方法应该有效,直到它被修复。