Flutter 如何在网格上的 TextFields 之间切换焦点(填字游戏)

Flutter how to switch focus between TextFields on a grid (a crossword)

我正在尝试创建填字游戏。我使用 GridView.count 制作填字游戏网格。我从一个列表中得到了填字游戏的模板,黑色方块用#标记并且只是黑色方块,你不能什么都不做,因为它们应该是。其余的网格单元是 TextFields,用户可以在其中输入字母来制作填字游戏。每个填字游戏都是不同的,所以我必须以编程方式创建网格。我的问题是我需要弄清楚用户想要写的单词是水平的还是垂直的,并在用户书写时让焦点从第一个单元格切换到下一个单元格(白色方块)。如何告诉它走哪条路(水平或垂直)?我还发现了 FocusTraversalGroup 和 FocusTraversalOrder,但是没有关于如何使用它们的例子。

代码如下(代码中s是包含填字游戏模板的List:

根据@DungNgo 建议编辑代码:

class Cells extends StatefulWidget {
  @override
  _CellsState createState() => _CellsState();
}

class _CellsState extends State<Cells> {

  final FocusScopeNode _node = FocusScopeNode(); //new code
  
  @override
  void dispose() {
    _node.dispose(); //new code
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Crossword'),
        ),
        body: SafeArea(
            child: GridView.count(
              crossAxisCount: 15,
              mainAxisSpacing: 2,
              crossAxisSpacing: 2,
              children: List.generate(s.length, (index) {
                return FocusScope( //new code
                    node: _node, //new code
                  child: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                      color: s[index] == '#' ? Colors.black : Colors.white,
                      border: Border.all(color: Colors.black)
                  ),
                  child:
                  s[index] == '#' ?
                  Text( '#' ) :
                 TextField(
                      cursorColor: Colors.black,
                      textAlign: TextAlign.center,
                      textAlignVertical: TextAlignVertical.bottom,
                      decoration: InputDecoration.collapsed(hintText: ""),
                      style: TextStyle( decoration: TextDecoration.none),
                      onChanged: (text){
                      _node.nextFocus(); //new code
                    },
                  ),
                 )
                );
              }),
            )
        )
    );

  }
} 

现在光标会自动聚焦到下一个单元格,但只能水平聚焦。任何人都知道如何让它垂直“移动”?我知道 DirectionalFocusTraversalPolicyMixin 存在并且我看到了这个

focusInDirection(TraversalDirection direction) => FocusTraversalGroup.of(context!)!.inDirection(this, direction);

但我不知道如何实现它! 任何帮助将不胜感激。 谢谢

经过多次修改,我终于找到了一种方法。这是代码:

class Cells extends StatefulWidget {
  @override
  _CellsState createState() => _CellsState();
}

class _CellsState extends State<Cells> {

  isVertical = false; // added a flag
  final FocusScopeNode _node = FocusScopeNode(); 
  
  @override
  void dispose() {
    _node.dispose();
    super.dispose();
  }
  
  // added a diolog to let the user choose the writing direction (horizontal or vertical)

   void _showDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("Direzione"),
          content: Text("Scrivi in verticale?"),
          actions: <Widget>[
            FlatButton(
              child: Text("SI"),
              onPressed: () {
                setState(() {
                  isVertical = true;
                });
                Navigator.of(context).pop();
              },
            ),
            FlatButton(
              child: Text("NO"),
              onPressed: () {
                setState(() {
                  isVertical = false;
                });
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Crossword'),
        ),
        body: SafeArea(
            child: GridView.count(
              crossAxisCount: 15,
              mainAxisSpacing: 2,
              crossAxisSpacing: 2,
              children: List.generate(s.length, (index) {
                return FocusScope( 
                    node: _node,
                  child: Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                      color: s[index] == '#' ? Colors.black : Colors.white,
                      border: Border.all(color: Colors.black)
                  ),
                  child:
                  s[index] == '#' ?
                  Text( '#' ) :
                 TextField(
                      cursorColor: Colors.black,
                      textAlign: TextAlign.center,
                      textAlignVertical: TextAlignVertical.bottom,
                      decoration: InputDecoration.collapsed(hintText: ""),
                      style: TextStyle( decoration: TextDecoration.none),
                      onChanged: (text){
                      isVertical == false ? _node.focusInDirection(TraversalDirection.right) : _node.focusInDirection(TraversalDirection.down); // this is what does it !!
                    },
                  ),
                 )
                );
              }),
            )
        )
    );

  }
} 

还有很多问题需要解决,但我的主要问题已经得到解答。