Flutter Android电视应用程序无法使用D Pad进行选择



我正在使用Flutter开发一个Android电视应用程序。我可以运行该应用程序(目前是示例应用程序(。但我不能用键盘选择按钮选择任何东西。

我发现我必须使用这样的东西来实现这个

快捷方式(

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

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

感谢您的帮助。非常感谢。

添加此代码肯定有助于Android TV的"确定/选择"按钮,并且可以扩展到其他映射。完美构建并适用于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( 

您可以使用RawKeyboardListener代替Shortcuts,我使用了以下代码:

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

您也可以使用D-PAD键执行此类操作。

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

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],
),

],
),
),
);

}
}

我希望这能帮助那些面临与我的相同问题的人

我的解决方法是使用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)),
),

使用FocusableActionDetector而不是Shortcuts

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.'),
),
);
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
}
}
}
},

这样你就可以使用长按和短按的快捷

使用上面朋友的方法,这样我们就可以在电视上使用D-pad的长按和轻按功能。只需在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;
},

现在您可以使用具有长按和按压功能的D-pad

最新更新