• Flutter InteractiveViewer CustomPaint的使用总结


    最近产品上有个图片编辑的需求,需要对编辑区域做放大和缩小, 以方便用户编辑图片。做起来远比博主当初预想的要难受。这期间遇到几个问题。一一做一下记录。

    如果只是单纯的缩放,没有对缩放的内容进行改变和更新, 那么基本没啥问题。

    这是基本的使用。

    1. InteractiveViewer(
    2. transformationController: controller,
    3. boundaryMargin: const EdgeInsets.all(double.infinity),
    4. minScale: 0.5,
    5. maxScale: 3.0,
    6. constrained: false,
    7. scaleEnabled: true,
    8. panEnabled: false,
    9. onInteractionStart: (ScaleStartDetails details) {
    10. if (details.pointerCount > 1) {
    11. widget.controller.value.moving = false;
    12. // logger
    13. // .i("onInteractionStart,two, ${details.localFocalPoint}");
    14. } else {
    15. // 单指
    16. if (allowDraw) {
    17. widget.controller
    18. .onDragStartCallback(details, controller, measuredRect,statusBarHeight);
    19. // logger.i(
    20. // "onInteractionStart, single, ${details.localFocalPoint}");
    21. }
    22. }
    23. },
    24. onInteractionUpdate: (ScaleUpdateDetails details) {
    25. // logger.i(
    26. // "onInteractionUpdate,pointerCount, ${details.pointerCount}");
    27. if (details.pointerCount > 1) {
    28. widget.controller.value.moving = false;
    29. // logger
    30. // .i("onInteractionUpdate,two, ${details.localFocalPoint}");
    31. allowDraw = false;
    32. } else {
    33. // 单指
    34. if (allowDraw &&
    35. details.focalPointDelta != const Offset(0, 0)) {
    36. widget.controller.onDragUpdateCallback(
    37. details, controller, measuredRect, statusBarHeight);
    38. // logger.i(
    39. // "onInteractionUpdate, single, ${details.localFocalPoint}");
    40. }
    41. }
    42. },
    43. onInteractionEnd: (ScaleEndDetails details) {
    44. // logger.i(
    45. // "onInteractionEnd,pointerCount, ${details.pointerCount}");
    46. if (details.pointerCount > 1) {
    47. widget.controller.value.moving = false;
    48. // logger.i("onInteractionEnd, two");
    49. } else if (details.pointerCount == 1) {
    50. } else if (details.pointerCount == 0) {
    51. widget.controller.onDragEndCallback(details);
    52. allowDraw = true;
    53. // logger.i("onInteractionEnd single");
    54. }
    55. }

    下面都是针对CustomPaint缩放导致的问题。

    1.drawpath问题, 用drawline/drawpoint替换。

    flutter 渲染器,哪怕是最新的impeller都有问题(官网上bug),原因是flutter目前还不能直接控制硬件层。drawPath方法在缩放的情况下,有性能问题,卡帧,掉帧,甚至crash。 说是会有一些计算什么。简单的图形就用drawline/drawpoint实现。如果要用到贝塞尔曲线,那就没有办法了。

    2.图层层数尽可能的少。

    save()/savelayer(), 尽可能的少调。多了同样会有性能问题,卡帧,掉帧,甚至crash。所以要优化图层。

    3.无法缩小。

    这个简单,就加上这句代码:

    boundaryMargin: const EdgeInsets.all(double.infinity),

    4.位置偏移问题。放大缩小后的手指点位置不对。

    区域缩放后,手指点击的区域和原图编辑区域,这儿有个映射关系。

    1. scale = transformationController.value.getMaxScaleOnAxis();//实时
    2. double width = details.localFocalPoint.dx -((1.sw - measuredRect.width)*scale/2)-
    3. transformationController.value.getTranslation().x;
    4. double height = details.localFocalPoint.dy -((1.sh - measuredRect.height)*scale/2)-
    5. transformationController.value.getTranslation().y;
    6. currentPosition = Offset(width / scale, height / scale);

    代码中,实时获取缩放值transformationController.value.getMaxScaleOnAxis(); 而不是回调函数中的参数。那个是基于上次的。

    5. RepaintBoundary和 shouldRepaint()解决无意义刷新。

    在缩放时,CustomPaint会反复刷新,尽可能避免不必要的刷新。做到在缩放时不刷新,在编辑时刷新。

    6. crash问题

    你可能会碰到这样的crash:

    1. * thread #9, name = 'io.flutter.1.ui', stop reason = EXC_BAD_ACCESS (code=1, address=0x105ea4000)
    2.     frame #0: 0x0000000107feed54 Flutter`flutter::DisplayListBuilder::Restore() + 284
    3. Flutter`flutter::DisplayListBuilder::Restore:
    4. ->  0x107feed54 <+284>: ldrsb  w8, [x24]
    5.     0x107feed58 <+288>: sub    w8, w8, #0x17
    6.     0x107feed5c <+292>: cmp    w8, #0x1
    7.     0x107feed60 <+296>: b.hi   0x107fef1e4               ; <+1452>
    8. Target 0: (Runner) stopped.

    这是flutter SDK导致的问题。3.22.0开始引入的问题, 写这篇文章时最新是3.22.2。解决这个问题就是退回到上一个版本, 3.19.6.

  • 相关阅读:
    java毕业设计选题基于SpringBoot项目源码体育用品购物商城-协同过滤推荐算法
    Elasticsearch7教程(2) 更新文档 painless script案例
    FL Studio 20.9水果编曲软件中文汉化补丁包
    利用 JSqlParser 防止 SQL 注入
    CentOS8编译安装curl 7.84.0
    ceval 数据集明文位置编码嵌入
    四川翌加:横拍和竖拍抖音短视频哪个更好
    根据GWAS数据估算样本量N和使用千人基因组填充maf的参考文献
    httpx.HTTPStatusError: Client error ‘429 Too Many Requests‘ for url ‘
    如何使用腾讯云轻量应用服务器以及WordPress搭建个人博客(详细图文教程)
  • 原文地址:https://blog.csdn.net/zjuter/article/details/139502218