#flutter
Вопрос:
Мне жаль, если название кажется неправильным, я не смог найти лучшего способа его сформулировать. У меня есть сетка контейнеров на экране, и я хочу иметь возможность рисовать на экране, выбирая и перетаскивая по экрану. Я читал об этом GestureDetector
классе, но он обнаруживает только жест, который начинается в одном виджете , я могу сделать onPanDown
, onPanUpdate
, onPanEnd
но это просто дает мне координаты курсора, и я не чувствовал, что это самый элегантный способ сделать это.(Возможно, я ошибаюсь).
Класс Блоков:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class Block extends StatefulWidget {
@override
_BlockState createState() => _BlockState();
}
class _BlockState extends State<Block> {
Color boxColor = Colors.white;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
if (boxColor == Colors.blueGrey[900])
boxColor = Colors.white;
else
boxColor = Colors.blueGrey[900];
setState(() {});
},
child: Container(
height: 20,
width: 20,
decoration: BoxDecoration(
color: boxColor,
border: Border.all(
color: Colors.grey,
width: 1,
)),
),
);
}
}
Класс поиска путей: (Рисование блоков в сетке):
import 'package:flutter/material.dart';
import 'Block.dart';
class PathFinding extends StatefulWidget {
@override
_PathFindingState createState() => _PathFindingState();
}
class _PathFindingState extends State<PathFinding> {
@override
Widget build(BuildContext context) {
List<List<Widget>> grid = [
...List.generate(
40, (index) => [...List.generate(40, (index) => Block())])
];
return Scaffold(
body: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
...grid.map((e) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [...e],
))
],
),
);
}
}
Ответ №1:
Просто передайте обратный вызов в качестве параметра от вашего _PathFindingState
, когда вы создаете Block
.
Во-первых, добавьте к своему 2 дополнительных параметра Block
, которые можно передать при его создании.
class Block extends StatefulWidget {
final void onTap; // The function from the parent to be called
final int id; // An id that is unique to this Block
Block({ this.onTap, this.id });
@override
_BlockState createState() => _BlockState();
}
Затем, в вашем _BlockState
случае , всякий tap
раз, когда обнаруживается a, вызывайте новую функцию, чтобы сообщить Block
классу, который затем сообщит _PathFindingState
классу.
InkWell(
onTap: () {
if (boxColor == Colors.blueGrey[900])
boxColor = Colors.white;
else
boxColor = Colors.blueGrey[900];
setState(() {});
widget.onTap(widget.id); // This line will call the `onTap` function that is present in the `Block`
},
Наконец, в вашем _PathFindingState
,
class _PathFindingState extends State<PathFinding> {
void onTap (int id) {
// A Block with `id` = id has been tapped,
}
@override
Widget build(BuildContext context) {
List<List<Widget>> grid = [
...List.generate(
40, (index) => [...List.generate(40,
(index) => Block(id: index, onTap: onTap) // Pass index as id and the onTap function
)])
];
Этой архитектуре можно следовать для любого Gesture
, что было обнаружено на любом Block
, и вы получите обратный вызов в _PathFindingState
классе, и вы можете делать с ним все, что захотите.