Flutter Android TV 应用无法使用 D Pad 进行选择

问题描述 投票:0回答:7

我正在使用 Flutter 开发 Android TV 应用程序。我可以运行该应用程序(目前是示例应用程序)。但我无法使用方向键选择按钮选择任何内容。

我发现我必须使用类似的东西才能实现这一目标

快捷方式(

    shortcuts: {
      LogicalKeySet(LogicalKeyboardKey.select):
          const Intent(ActivateAction.key)
    },
    child: MaterialApp())

但是它在代码中给了我一个错误。我做错了什么?

如有任何帮助,我们将不胜感激。谢谢你。

android flutter flutter-layout android-tv d-pad
7个回答
9
投票

添加此代码肯定对 Android TV OK/Select 按钮有帮助,并且可以扩展到其他映射。为 flutter 1.24-dev 构建并完美运行

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return Shortcuts(
      shortcuts: <LogicalKeySet, Intent>{
        LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
      },
      child: MaterialApp( 

1
投票

您可以使用 RawKeyboardListener 代替快捷方式,我使用了以下代码:

 body: RawKeyboardListener(
        autofocus: true,
        focusNode: _focusNode,
        onKey: _onKey,
        child:Center())
 

    void _onKey(RawKeyEvent e) {
    controls();

    if (e.runtimeType.toString() == 'RawKeyDownEvent') {
      switch (e.logicalKey.debugName) {
        case 'Media Play Pause':
        case 'Select':
          setState(() {
            if (_videoViewController.value.isPlaying) {
              _videoViewController.pause();
            } else {
              _videoViewController.play();
            }
          });
          break;
      }
    }`

现在,如果您想要快进或快退,只需使用 RawKeyboardListener 即可 具体情况来处理。

您还可以使用方向键来执行此类操作。


0
投票

可能这是一个迟到的答案。但我在电视应用程序上遇到了同样的问题。如果您的应用程序中没有文本字段,则上述步骤适用。如果您在应用程序中使用 textfeilds,则应该使用 FocasableActionDetector 小部件。 FocusableActionDetector 包括快捷方式、操作和焦点小部件。我处理事情的方式是,我创建了一个 FocusNode 列表,并将它们分配给页面中的可聚焦小部件。然后我将使用 FocusableActionDetector 包装所有可聚焦的小部件,并在 FocusableActionDetector 的操作参数中提供必要的按键逻辑。这是如何实现它的示例。

    class LoginPage extends StatefulWidget {
      LoginPage({Key? key}) : super(key: key);
    
      @override
      State<LoginPage> createState() => _LoginPageState();
    }

 class _LoginPageState extends State<LoginPage> {
  GlobalKey<FormState> get loginFormKey => formKey ??= GlobalKey<FormState>();

  int loginIndex = 0;

  list<FocusNode> loginNodes = <FocusNode>[];

 


  @override
  void initState() {
  for (var i = 0; i < 5; i++) {
      loginNodes.add(FocusNode(debugLabel: 'loginNode $i'));
    }

    super.initState();
  }

  @override
  void dispose() {
  loginNodes.dispose();

    super.dispose();
  }

  Map<ShortcutActivator, Intent> navigationIntents = {
    LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
    LogicalKeySet(LogicalKeyboardKey.arrowRight): const RightbuttonIntent(),
    LogicalKeySet(LogicalKeyboardKey.arrowLeft): const LeftbuttonIntent(),
    LogicalKeySet(LogicalKeyboardKey.arrowUp): const UpbuttonIntent(),
    LogicalKeySet(LogicalKeyboardKey.arrowDown): const DownbuttonIntent(),
    LogicalKeySet(LogicalKeyboardKey.goBack): const BackButtonIntent()
    //LogicalKeySet(LogicalKeyboardKey.back)
  };

 

  @override
  Widget build(BuildContext context) {
   

    return
      
    
     FocusableActionDetector(
        shortcuts: navigationIntents,
        actions: <Type, Action<Intent>>{
          DownbuttonIntent: CallbackAction<DownbuttonIntent>(
            onInvoke: (intent) {
              // if (loginIndex <= 0) loginIndex = 0;

              if (loginIndex <= loginNodes.length - 1) {
                loginIndex++;
                log('index in downIntent if is $loginIndex');
                FocusScope.of(context).requestFocus(loginNodes[loginIndex]);
              } else if (loginIndex > loginNodes.length - 1) {
                loginIndex = 4;
                log('index in downIntent else is $loginIndex');
                FocusScope.of(context).requestFocus(loginNodes[3]);
              }
              // log('index in downIntent is $loginIndex');

              return KeyEventResult.ignored;
            },
          ),
          UpbuttonIntent: CallbackAction<UpbuttonIntent>(
            onInvoke: (intent) {
              if (loginIndex >= 0) {
                loginIndex--;
                FocusScope.of(context).requestFocus(loginNodes[loginIndex]);
                log('index in upIntent else is $loginIndex');
              } else if (loginIndex <= 0) {
                loginIndex = 0;
                log('index in upIntent if is $loginIndex');
                FocusScope.of(context).requestFocus(loginNodes[0]);
                loginNodes.refresh();
              }

              return KeyEventResult.ignored;
            },
          ),
        },
        child: AuthScreenWrapper(
        
          authForm: AuthForm(
            formKey: loginFormKey,
            title: 'login'.tr,
            subtitle: 'login_to_continue'.tr,
            formComponents: [
              EmailInputField(emailFocus: loginNodes[0]),

              PasswordInputField(passwordFocus: loginNodes[1]),

              KeepMeForgotButtons(
                rememberNode: loginNodes[2],
              ),

           
              LoginButton(
                btnNode: loginNodes[3],
              ),

              
            ],
          ),
        ),
      );
  
  }
}

我希望这对遇到与我相同问题的人有所帮助


0
投票

我的解决方法是使用 Focus 小部件并使用它的 onKey 函数来模拟按键。

                  Focus(
                    onKey: (node, event) {
                      if (event.logicalKey == LogicalKeyboardKey.select && node.hasFocus) {
                        setState(() {
                          _debug = 'Pressed';
                        });
                        return KeyEventResult.handled;
                      }
                      return KeyEventResult.ignored;
                    },
                    child: ElevatedButton(onPressed: () {}, child: Text(_debug)),
                  ),

0
投票

使用 FocusableActionDetector 而不是快捷方式

Scaffold(
      body: FocusableActionDetector(
        shortcuts: {
          LogicalKeySet(LogicalKeyboardKey.select): ActivateIntent(),
        },
        actions: <Type, Action<Intent>>{
          ActivateIntent: CallbackAction<ActivateIntent>(
            onInvoke: (intent) {
              // Do something when the select key is pressed.
            },
          ),
        },
        child: Text('This text will be focused when the select key is pressed.'),
      ),
    );

0
投票
return Shortcuts(
      shortcuts: <LogicalKeySet, Intent>{
        LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
      },
      child: Actions(
        actions: <Type, Action<Intent>>{
          ActivateIntent: CallbackAction<ActivateIntent>(
            onInvoke: (intent) {
              // Only start the long-press timer if it is not already active
              if (longPressTimer == null || !longPressTimer!.isActive) {
                longPressTimer = Timer(Duration(milliseconds: 500), () {
                  // Execute an action after 500 milliseconds (adjust the duration as needed)
                  print("Select LongPress");

                  // Add your long-press action here
                });
              }
            },
          ),
        },
        child: RawKeyboardListener(
            focusNode: FocusNode(),
            onKey: (event) {
              if (event is RawKeyUpEvent) {
                if (event.logicalKey == LogicalKeyboardKey.select) {
                  // Cancel the long-press timer and execute the action for short press
                  if (longPressTimer != null && longPressTimer!.isActive) {
                    longPressTimer!.cancel();
                    print("Select Short Press");
                    const ActivateIntent();
                    // Add your short-press action here
                  }
                }
              }
            },

这样你就可以通过快捷键使用长按和短按


0
投票

使用上面朋友的方法,这样我们就可以在电视上使用方向键长按和点击功能。只需在 main.dart 中使用它即可

class MyApp extends StatelessWidget with RouteAware {
  final String? filePath;

  const MyApp({Key? key, this.filePath}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Shortcuts(
      shortcuts: <LogicalKeySet, Intent>{
        LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
      },

并且在你长按这个的焦点

    onKey: (node, event) {
            if (event.logicalKey == LogicalKeyboardKey.select &&
                node.hasFocus) {
              if (event is RawKeyDownEvent) {
                _longPressTimer =
                    Timer(Duration(milliseconds: 500), () {
                  _isLongPressDetected = true;
                  print("Long press detected");
                  // Implemente a ação que deseja realizar para o long press
                });
              } else if (event is RawKeyUpEvent) {
                _longPressTimer?.cancel();
                if (!_isLongPressDetected) {
                  print("Short press detected");
                  // Implemente a ação que deseja realizar para o short press
                }
                _isLongPressDetected =
                    false; // Reseta a variável de controle para o próximo pressionamento
                return KeyEventResult.handled;
              }
            }
            return KeyEventResult.ignored;
          },

现在您可以使用具有长按和按下功能的方向键

© www.soinside.com 2019 - 2024. All rights reserved.