【问题标题】:I need to know if a key was down (pressed) while the user clicked on a button我需要知道用户单击按钮时是否按下(按下)键
【发布时间】:2021-07-25 12:23:25
【问题描述】:

在 Flutter 桌面应用程序中,我想知道,当用户用鼠标点击按钮时,他们是否也在按住一个键(如 Shift、Control、Alt 等)。

如何做到这一点?

编辑

我最初的问题不够清楚。

我有一个复选框的动态列表,我想使用 SHIFT+单击来选择最后一个选中的复选框和按下 SHIFT 键选中的复选框之间的所有内容。

我查看了 FocusNode,但这似乎只适用于 1 个元素。

【问题讨论】:

    标签: flutter dart flutter-desktop


    【解决方案1】:

    这可以通过FocusNode 来完成。

    您需要一个有状态的小部件,您可以在其中使用初始化节点。您需要attach 节点并定义在键盘按下时调用的回调。然后可以通过requestFocus向节点请求焦点,以便节点接收键盘事件。

    您还需要在您的build 方法中调用_nodeAttachment.reparent();。您还应该在dispose 中处理该节点。

    下面的示例会打印按下按钮时是否按下 shift 键的 true 或 false。这可以通过 isControlPressedisAltPressed 属性轻松扩展到其他键,例如 control 和 alt。


    完整示例:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Center(
              child: MyWidget(),
            ),
          ),
        );
      }
    }
    
    class MyWidget extends StatefulWidget {
      @override
      _MyWidgetState createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      late final FocusNode focus;
      late final FocusAttachment _nodeAttachment;
      
      bool isShiftPressed = false;
      
      @override
      void initState() {
        super.initState();
        focus = FocusNode(debugLabel: 'Button');
        _nodeAttachment = focus.attach(context, onKey: (node, event) {
          isShiftPressed = event.isShiftPressed;
        });
        focus.requestFocus();
      }
      
      @override
      void dispose() {
        focus.dispose();
        super.dispose();
      }
      
      Widget build(BuildContext context) {
        _nodeAttachment.reparent();
        return TextButton(
          onPressed: () {
            print(isShiftPressed);
          },
          child: Text('Test'),
        );
      }
    }
    

    对于更具体的问题,您仍然可以使用此解决方案。将上面的示例包装在您的复选框列表周围。你可以做一些简单的逻辑来获得你想要的行为。如果我在这里的内容不准确,您应该能够根据需要轻松修改它。这证明您可以根据需要使用此方法,但是,即使逻辑中的某些细节不准确:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Center(
              child: MyWidget(),
            ),
          ),
        );
      }
    }
    
    class MyWidget extends StatefulWidget {
      @override
      _MyWidgetState createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      late final FocusNode focus;
      late final FocusAttachment _nodeAttachment;
      
      bool isShiftPressed = false;
      
      List<bool> checkboxStates = List.filled(5, false);
      
      int lastClicked = -1;
      
      @override
      void initState() {
        super.initState();
        focus = FocusNode(debugLabel: 'Button');
        _nodeAttachment = focus.attach(context, onKey: (node, event) {
          isShiftPressed = event.isShiftPressed;
        });
        focus.requestFocus();
      }
      
      @override
      void dispose() {
        focus.dispose();
        super.dispose();
      }
      
      Widget build(BuildContext context) {
        _nodeAttachment.reparent();
        return Column(
          children: List.generate(checkboxStates.length, (index) => Checkbox(
            value: checkboxStates[index],
            onChanged: (val) {
              if(val == null) {
                return;
              }
              
              setState(() {            
                if(isShiftPressed && val) {
                  if(lastClicked >= 0) {
                    bool loopForward = lastClicked < index;
                    if(loopForward) {
                      for(int x = lastClicked; x < index; x++) {
                        checkboxStates[x] = true;
                      }
                    }
                    else {
                      for(int x = lastClicked; x > index; x--) {
                        checkboxStates[x] = true;
                      }
                    }
                  }
                }
                checkboxStates[index] = val;
              });
              
              if(val) {
                lastClicked = index;
              }
              else {
                lastClicked = -1;
              }
              
              print('Checkbox $index: $isShiftPressed');
            }
          )),
        );
      }
    }
    

    【讨论】:

    • 非常感谢您的回复。我现在意识到我一定没有足够清楚地说明我的问题。请查看我原来问题中的修改。
    • 是的,看到了您的编辑,但还没有时间测试它。我会在实施后立即通知您。谢谢。
    • 终于有时间试一试,果然奏效了。谢谢。将您的答案标记为正确答案。
    猜你喜欢
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多