设备方向更改后,CustomPainter无法在正确的位置绘画

时间:2019-05-06 21:37:46

标签: android dart flutter

我正在尝试学习Flutter。每当轻按容器时,我都会使用CustomPainter在对中的方形容器上绘制对角线。 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;
  }
}

即使在设备更改方向后,如何使CustomPainter再次在容器的中心重画该线。

感谢您的时间。

1 个答案:

答案 0 :(得分:0)

您唯一要做的就是将drawLine方法放在FrameCallback中:

@override
void didChangeMetrics() {
  SchedulerBinding.instance.addPostFrameCallback((_) {
    _drawLine();
  });
}