Получение положения одного виджета по отношению к другому

#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. Это то же решение, что и у меня, но скрыто в методе расширения.