Android 设备方向改变后,CustomPainter未在正确位置喷漆

Android 设备方向改变后,CustomPainter未在正确位置喷漆,android,dart,flutter,Android,Dart,Flutter,我正在努力学习颤振。我正在使用CustomPainter在一个中心的方形容器上绘制一条对角线,只要点击容器。画家正确地画了线 但是,当设备方向改变且不再位于容器中心时,该线会改变其位置 我使用didChangeMetrics()来检测设备方向何时改变并重新绘制线条。但这一次,这条线并没有按预期在容器的中心绘制。但是,如果再次轻敲容器,则正确绘制线。我调用同一个函数,在didChangeMetrics和onTapDown这两个位置划清界限 我正在使用以下代码: import 'package:fl

我正在努力学习颤振。我正在使用CustomPainter在一个中心的方形容器上绘制一条对角线,只要点击容器。画家正确地画了线

但是,当设备方向改变且不再位于容器中心时,该线会改变其位置

我使用didChangeMetrics()来检测设备方向何时改变并重新绘制线条。但这一次,这条线并没有按预期在容器的中心绘制。但是,如果再次轻敲容器,则正确绘制线。我调用同一个函数,在didChangeMetrics和onTapDown这两个位置划清界限

我正在使用以下代码:

import 'package:flutter/material.dart';
import 'dart:ui';

void main() {
  runApp(MaterialApp(home: HomePage()));
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  Offset start = Offset.zero;
  Offset end = Offset.zero;
  double winLineWidth = 0;
  GlobalKey _containerKey = GlobalKey();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
  }

  @override
  void didChangeMetrics() {
    _drawLine();
  }

  void _drawLine() {
    RenderBox box = _containerKey.currentContext.findRenderObject();
    var _boxOffset = box.getTransformTo(null).getTranslation();
    RenderBox getBox = context.findRenderObject();
    print(getBox.globalToLocal( Offset(_boxOffset.x, _boxOffset.y) ));
    var appBarHeight = 80;
    setState(() {
      start = Offset(_boxOffset.x, _boxOffset.y - appBarHeight);
      end = Offset(_boxOffset.x + 100, _boxOffset.y - appBarHeight + 100);
      print('$start $end');
      winLineWidth = 2;
    });
  }

  @override
  Widget build(BuildContext context) {
    AppBar appBar = AppBar(
      title: Text('Demo'),
    );
    return Scaffold(
      appBar: appBar,
      body: Stack(
        children: <Widget>[
          Center(
            child: GestureDetector(
              onTapDown: (TapDownDetails tapDownDetails) {
                _drawLine();
              },
              child: Container(key: _containerKey,width: 100,height: 100,color: Colors.black),
            ),
          ),
          CustomPaint(painter:WinLine(start: start, end: end, winLineWidth: winLineWidth),
          )
        ],
      ),
    );
  }
}

class WinLine extends CustomPainter {
  Paint _paint;
  Offset start, end;
  double winLineWidth;

  WinLine({this.start, this.end, this.winLineWidth = 8}) {
    _paint = Paint()
      ..color = Colors.red
      ..strokeWidth = winLineWidth;
  }

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawLine(start, end, _paint);
  }

  @override
  bool shouldRepaint(WinLine oldDelegate) {
    return true;
  }
}

导入“包装:颤振/材料.省道”;
导入“dart:ui”;
void main(){
runApp(MaterialApp(home:HomePage());
}
类主页扩展了StatefulWidget{
@凌驾
_HomePageState createState()=>\u HomePageState();
}
类_HomePageState使用WidgetsBindingObserver扩展状态{
偏移开始=偏移0.0;
偏移结束=偏移0.0;
双winLineWidth=0;
GlobalKey _containerKey=GlobalKey();
@凌驾
void initState(){
super.initState();
WidgetsBinding.instance.addObserver(这个);
}
@凌驾
无效处置(){
super.dispose();
WidgetsBinding.instance.removeObserver(此);
}
@凌驾
void didChangeMetrics(){
_抽绳();
}
虚线{
RenderBox=_containerKey.currentContext.FindEnderObject();
var_boxOffset=box.getTransformTo(null.getTranslation();
RenderBox getBox=context.finderNodeObject();
打印(getBox.globalToLocal(偏移量(_-boxOffset.x,_-boxOffset.y));
var-appBarHeight=80;
设置状态(){
开始=偏移量(_-boxOffset.x,_-boxOffset.y-appBarHeight);
结束=偏移量(_-boxOffset.x+100,_-boxOffset.y-appBarHeight+100);
打印(“$start$end”);
winLineWidth=2;
});
}
@凌驾
小部件构建(构建上下文){
AppBar AppBar=AppBar(
标题:文本(“演示”),
);
返回脚手架(
appBar:appBar,
主体:堆栈(
儿童:[
居中(
儿童:手势检测器(
onTapDown:(点击详细信息点击详细信息){
_抽绳();
},
子项:容器(键:_containerKey,宽度:100,高度:100,颜色:Colors.black),
),
),
CustomPaint(画师:WinLine(开始:开始,结束:结束,winLineWidth:winLineWidth),
)
],
),
);
}
}
类WinLine扩展了CustomPainter{
油漆;
偏移开始、结束;
双线宽;
WinLine({this.start,this.end,this.winLineWidth=8}){
_油漆=油漆()
…颜色=颜色。红色
..strokeWidth=winLineWidth;
}
@凌驾
空心油漆(帆布,尺寸){
画布.抽绳(起点、终点、油漆);
}
@凌驾
布尔应重新绘制(WinLine oldDelegate){
返回true;
}
}
如何让CustomPainter在设备改变方向后再次在容器中心重新绘制线条


谢谢您的时间。

您唯一需要做的就是将
drawLine
方法放入
框架回调中:

@覆盖
void didChangeMetrics(){
SchedulerBinding.instance.addPostFrameCallback((){
_抽绳();
});
}

使用此解决方法解决了此问题-。但如果可能的话,我仍然希望得到上述问题的答案。