#flutter
#flutter
Вопрос:
Есть ли лучший способ получить положение одного виджета по отношению к другому?
GlobalKey _key = GlobalKey();
GlobalKey _keyRoot = GlobalKey();
RenderBox box = _key.currentContext.findRenderObject();
Offset position = box.localToGlobal(Offset.zero);
RenderBox box2 = _keyRoot.currentContext.findRenderObject();
Offset position2 = box2.localToGlobal(Offset.zero);
double x = position.dx - position2.dx;
double y = position.dy - position2.dy;
Кроме того, я хотел бы, чтобы позиция указывалась в нижнем левом углу.
Вы делали это раньше?
Ответ №1:
Я поместил свое решение во внешний класс
class Utils {
static Offset getPositionBottomLeft(GlobalKey parentKey, GlobalKey childKey) {
final parentBox = parentKey.currentContext!.findRenderObject() as RenderBox;
final parentPosition = parentBox.localToGlobal(Offset.zero);
final parentHeight = parentBox.size.height;
final childBox = childKey.currentContext!.findRenderObject() as RenderBox;
final childPosition = childBox.localToGlobal(Offset.zero);
final childHeight = childBox.size.height;
final x = childPosition.dx - parentPosition.dx;
final y = (childPosition.dy childHeight - parentPosition.dy - parentHeight).abs();
return Offset(x, y);
}
}
Ответ №2:
Вы можете создать расширение GlobalKey для возврата положения виджета:
extension GlobalKeyEx on GlobalKey {
Offset get globalPosition {
final RenderBox box = currentContext?.findRenderObject();
return box?.localToGlobal(Offset.zero);
}
}
Затем вы вычисляете свое расстояние аналогично тому, что вы уже написали:
double x = _key1.globalPosition.dx - _key2.globalPosition.dx;
double y = _key1.globalPosition.dy - _key2.globalPosition.dy;
Вот пример приложения для его демонстрации:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {@override
createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final key1 = GlobalKey();
final key2 = GlobalKey();
var message = "Tap the button";
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
key: key1,
top: 120,
left: 40,
child: Text("Widget 1"),
),
Positioned(
key: key2,
top: 150,
left: 100,
child: Text("Widget 2"),
),
Positioned(
top: 200,
left: 10,
child: RaisedButton(
child: Text("Tap me"),
onPressed: () {
// Compute the distance between the two widgets
var x = key1.globalPosition.dx - key2.globalPosition.dx;
var y = key1.globalPosition.dy - key2.globalPosition.dy;
// we show the absolute distance between the widgets
setState(() => message = "The distance is X: ${x.abs()}, Y: ${y.abs()}");
},
),
),
Positioned(
top: 250,
left: 10,
child: Text(message),
),
],
);
}
}
extension GlobalKeyEx on GlobalKey {
Offset get globalPosition {
final RenderBox box = currentContext?.findRenderObject();
return box?.localToGlobal(Offset.zero);
}
}
Комментарии:
1. Это то же решение, что и у меня, но скрыто в методе расширения.