gpt4 book ai didi

flutter - Shift + Tab和箭头(也为D-PAD)键不适用于TextFormField的焦点遍历

转载 作者:行者123 更新时间:2023-12-03 03:57:39 25 4
gpt4 key购买 nike

我正在开发一个应可在Android移动设备和Android TV上使用的应用程序。该应用程序在登录和注册表单中具有关注焦点的字段。这是最小的可复制示例:

import 'package:flutter/material.dart';

void main() => runApp(TestApp());

class TestApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Test App'),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(8.0),
child: TestWidget(),
),
),
);
}
}

class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: List<Widget>.generate(5, (int index) => TextFormField(
decoration: InputDecoration(
labelText: 'Field ${index + 1}',
),
)),
);
}
}

使用 Tab键将焦点移到下一个字段,但是按 Shift+Tab时上一个字段没有获得焦点。同样,箭头键和Android TV远程D-PAD键都不能用于 TextFormField的焦点遍历,但也可以用于其他可聚焦的小部件。

最佳答案

这是一个长期未决的问题,但是我们开始:
到目前为止,对Android TV的支持还有些不稳定。但是有一些更简单(但不是那么简单)的解决方法可以为我们提供帮助。
基本上从阅读此中篇文章开始:
Adding Android TV support to your Flutter App
首先要做的重要事情是通过将ap包装在Shortcut小部件中来增加对电视 Remote Dpad的支持:

return Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.select): ActivateIntent(),
},
child: MaterialApp(
...
);
据推测,这会将 select事件从键盘转发到 activate意图。 🤷️
到目前为止,您所有的可选内容(按钮等)都应该可以使用。 TextFormFields可能仍然不会。
然后在GitHub上检查以下Flutter问题: Focus gets lost on Android TV #49783
嗯...我不知道。这是一个漫长的问题,除了基于 RawKeyboardListener的方法外,我在这里找不到简单的解决方案。这是(无意间)我有点想的方式。
几天前开始这项工作时,我不了解 Shortcut方法,因此我在pub.dev focusnode_widgets上查看了此软件包。我检查了一下代码,了解到这样做的人手头有一个非常具体的问题。因此,我剥离了他的示例,并重新实现了他的类 _FocusNodeEnterTapActionableWidget(他似乎真的很喜欢 looooooooooong 类名...)。
注意:我不会在此处粘贴此代码,因为没有太大的区别,但是我所做的是创建了一个包装器小部件,该小部件可创建所需的小部件并能够处理所有必需的dpad事件-包括以下功能走过 TextFormField
在以下示例中, _FocusableWidget替代了 _FocusNodeEnterTapActionableWidget
/// get the type from a generic parameter
Type typeOf<T>() => T;

/// if you have large an scrollable pages with large gaps in between of focusable widgets
/// you need something to go to...
/// I used this to navigate through a help/about page
class FocusableAnchor extends StatelessWidget {
@override
Widget build(BuildContext context) => _FocusableWidget(
autoFocus: false,
handleEnterTapAction: (ctx) {},
child: Container(),
focusedBackgroundColor: Colors.transparent,
nonFocusedBackgroundColor: Colors.transparent,
);
}

/// there's another class I will leave out - it's just a wrapper for a given child
/// but I use a custom Android plugin to determine, whether I'm on a TV or not
/// TV: wrap the child widget, No TV: just use the child widget as-is.

/// this is the base wrapper, that is quite large, because it basically has all
/// (some renamed) parameters, needed to create the following widgets:
/// IconButton, FloatingActionButton, MaterialButton, FlatButton, RaisedButton
/// DropdownButton (doesn't really work though, I don't understand why), ListTile
/// CheckboxListTile, RadioListTile (these both are shaky as well)
/// Switch, ActionChip, TextFormField
class FocusableValue<T extends Widget, U> extends StatelessWidget {
FocusableValue({
Key key,
// the key of the widget to create
this.widgetKey,
// IconButton, FloatingActionButton
this.icon, // DropdownButton
this.onPressed,
this.onLongPress,
this.tooltip,
// ... many more
// explicitly set widget
this.widget,
this.colorFocused = true,
}) : super(key: key);

final Key widgetKey;

final Widget icon;
final void Function() onPressed;
final void Function() onLongPress;
final String tooltip;

final T widget;

final bool colorFocused;

// a former colleague decided to use Kiwi for DI...
final _uiMode = inject<UiModePlugin>();

@override
Widget build(BuildContext context) => FutureBuilder(
future: _uiMode.getUiModeType(),
initialData: null,
builder: (ctx, snap) {
if (!snap.hasData || snap.hasError || snap.data == null) {
return Container();
}
var widget = this.widget;
Function(BuildContext) onAction;
Color focusBgColor;
if (widget == null) {
final type = typeOf<T>();
switch (type) {
case IconButton:
widget = IconButton(
key: widgetKey,
icon: icon,
onPressed: onPressed,
tooltip: tooltip,
// ignore: avoid_as
) as T;
onAction = (ctx) => onPressed();
focusBgColor = colorAltDarkTransparent;
break;
// basically create your target here, e.g. TextFormField
// TextFormField doesn't need to set the onAction function, though
}
}

Decoration _decorate(Color color) {
if (color == null) return null;
return BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(3.0),
boxShadow: kElevationToShadow[1],
);
}

EdgeInsetsGeometry _padding(bool apply) {
if (!apply) return null;
return EdgeInsets.only(
top: 5.0,
right: 5.0,
bottom: 5.0,
left: 5.0,
);
}

BoxConstraints _constraints(bool apply) {
if (!apply) return null;
return BoxConstraints.tightFor(height: 37.0);
}

return UIMode.tv == snap.data
? _FocusableWidget(
autoFocus: false,
handleEnterTapAction: onAction ?? (ctx) {},
child: widget,
focusedBackgroundColor: null,
nonFocusedBackgroundColor: null,
focusedBackgroundDecoration:
colorFocused ? _decorate(focusBgColor) : null,
nonFocusedBackgroundDecoration: null,
padding: colorFocused ? _padding(focusBgColor != null) : null,
constraints:
colorFocused ? _constraints(focusBgColor != null) : null,
)
: widget;
},
);
}

/// for the most widgets, except for DropdownButton, RadioListTile I can use this wrapper
class Focusable<T extends Widget> extends FocusableValue<T, dynamic> {
Focusable({
Key key,
Key widgetKey,
Widget icon,
Function() onPressed,
Function() onLongPress,
String tooltip,
// more parameter to create other widgets
T widget,
bool colorFocused = true,
}) : super(
key: key,
widgetKey: widgetKey,
icon: icon,
onPressed: onPressed,
onLongPress: onLongPress,
tooltip: tooltip,
// pass all the other parameters here
widget: widget,
colorFocused: colorFocused,
);
}
这很乏味,但是在我的大多数情况下,它是可行的。我只需要弄清楚 CheckboxListTileRadioListTile-它们在我的(非常繁琐的)自定义对话框中不起作用。
我希望这会有所帮助。

关于flutter - Shift + Tab和箭头(也为D-PAD)键不适用于TextFormField的焦点遍历,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59876983/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com