欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

flutter疑难杂症之记一次RenderBox测量坐标错误

程序员文章站 2022-06-01 16:53:33
...

    项目中用到精确坐标计算,要求在绘制完成后立即测量控件在屏幕中的坐标,代码如下:

   void initState(){
        ...
      WidgetsBinding.instance.addPostFrameCallback((callback) {
       _calculateAfterLayout();
     });
        ...
   }


  ///求取绘制成功的时候的x和y坐标的位置
  void _calculateAfterLayout() {
    RenderBox screenObject = _screenKey.currentContext.findRenderObject();
    final screenPosition = screenObject.localToGlobal(Offset.zero);
    _curX = screenPosition.dx;
    _curY = screenPosition.dy;
  }

    代码正常情况下没有问题,但是出问题的时候是initstate中请求数据比较缓慢,然后导致计算的结果有偏差,并且在IOS和Android不同的平台上偏差还不一样,在IOS表现为dx偏差,在Android表现为dy偏差,具体如下图:

flutter疑难杂症之记一次RenderBox测量坐标错误
Android设备计算错误
flutter疑难杂症之记一次RenderBox测量坐标错误
ios设备计算错误
​​

    绿色的边界图形为计算而来的坐标展示的位置,它应该在中间屏幕左上角才是正常的,但是现在,这个图形在IOS表现为靠右,在Android表现为靠下。

(由于gif图不清楚,上传一张没有压缩的图片)

flutter疑难杂症之记一次RenderBox测量坐标错误
正常情况下绿色的标记应该在1处

    为什么会出现这样的情况呢,经过仔细观察可以知道,IOS的页面切换是从右往左切换,而Android的页面切换是从下往上,那么我有一个猜想,它们会不会是在切换的过程中被计算了坐标,如下:

flutter疑难杂症之记一次RenderBox测量坐标错误
IOS从右到左滑动,中间某一位置获取dx,dy,因此dx比实际大

 

flutter疑难杂症之记一次RenderBox测量坐标错误
Android从下向上滑动,中间某一位置获取dx,dy,因此dy比实际大

  如果是按照以上的猜想,那么就会出现测量不准确的现象。为了验证我的猜想,特将flutter中的material切换换成了自定义的切换,代码如下:

Navigator.of(context).pushAndRemoveUntil(
                PageRouteBuilder(pageBuilder: (BuildContext context,
                    Animation<double> animation,
                    Animation<double> secondaryAnimation) {
                  // 跳转的路由对象
                  return ScreenPage();
                }, transitionsBuilder: (
                  BuildContext context,
                  Animation<double> animation,
                  Animation<double> secondaryAnimation,
                  Widget child,
                ) {
                  return SlideTransition(
                    position: new Tween<Offset>(
                      begin: const Offset(0.0, 0.0),
                      end: Offset.zero,
                    ).animate(animation),
                    child: new SlideTransition(
                      position: new Tween<Offset>(
                        begin: Offset.zero,
                        end: const Offset(0.0, 0.0),
                      ).animate(secondaryAnimation),
                      child: child,
                    ),
                  );
                }),
                (route) => route == null);

    果然,将路由切换改成非滑动模式,这个bug就没有出现了,如下:

    

flutter疑难杂症之记一次RenderBox测量坐标错误
坐标计算正常

 

    还有一个问题,当第一次测量不准确的时候,对屏幕放大进行测量的坐标是准确的,然后再次缩小到第一次进入的时候的大小,测量坐标又不准确了,并且测量误差和第一次一样,说明对于已经测量过的初始值,Flutter不会再次测量,而是直接赋值。

    虽然问题解决了,但是这种方式只能规避,至于为啥Flutter中会在页面切换过程中而不是切换完成后再计算坐标,调用WidgetsBinding.instance.addPostFrameCallback监听绘制事件完成后才进行计算仍然有误,恐怕这也是Flutter留给我们的坑了。

 

flutter很好,路还很长,让我们一起奋斗前行!