首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何定制/旋转容器小部件的BoxDecoration?

问如何定制/旋转容器小部件的BoxDecoration?
EN

Stack Overflow用户
提问于 2018-07-03 17:29:57
回答 1查看 3.2K关注 0票数 0

我有一个Widget,它为公共汽车站构建一个圆形的配置文件图片,现在它有一个围绕概要文件图片的圆形边界,如下所示。我想改变圆形边框,改为虚线,并通过旋转/旋转的轮廓图片的虚空形式,也动画。有什么简单的方法吗?非常感谢您能提供的任何帮助!

​

​

代码语言:javascript
复制
return new Transform(
  transform: new Matrix4.diagonal3Values(
    animation.avatarSize.value,
    animation.avatarSize.value,
    1.0,
  ),
  alignment: Alignment.center,
  child: new Container(
    width: 110.0,
    height: 110.0,
    decoration: new BoxDecoration(
      shape: BoxShape.circle,
      border: new Border.all(
        color: Colors.white30,
      ),
    ),
    margin: const EdgeInsets.only(
      top: 24.0,
      left: 16.0,
    ),
    padding: const EdgeInsets.all(3.0),
    child: new ClipOval(
      child: new Image.asset(
        stopName.avatar,
      ),
    ),
  ),
);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-04 00:13:28

不幸的是,简单的答案是,没有简单的方法可以做到这一点。颤栗的人在他们无限的智慧已经得出结论,虚线的表现不够,包括在颤振,因此,没有人将永远不需要画虚线。(是的,这句话的逻辑上的不连续性是故意的。别误会我--我喜欢颤栗,开发人员做得很好,但他们似乎做了一些基于性能而不是功能的半武断的决定)。

我所看到的解释是,基本上C++版本将执行类似于dart代码的操作(除非它是直接在GPU上完成的),因此他们期望有人最终在dart中实现虚线(可能是库的一部分)。有关进展和讨论,请参见这个github虫 ..。如果你想在未来看到破折号的话。如果有足够多的人这样做,那么最终颤栗的人们可能会决定实施它。

但就目前而言,这意味着用虚线制作CircleBorder或任何其他类型的边框是不容易的。

然而,只要尽最大的努力,你想要的东西就能实现=)。下面是为您快速削减的代码,以实现您想要的。请注意-它不是很优化,可能有更容易的方法来做,你可能会使用装饰和实现油漆等在那里或其他什么.但这确实管用。

代码语言:javascript
复制
import 'dart:math';

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: new SafeArea(
        child: Column(
          children: [
            new DashedCircle(
              child: new ClippedDrawing(),
            )
          ],
        ),
      ),
    );
  }
}

class ClippedDrawing extends StatelessWidget {
  @override
  Widget build(BuildContext context) => new ClipOval(
        child: new Container(
          color: Colors.red,
        ),
      );
}

class DashedCircle extends StatefulWidget {
  final Widget child;

  const DashedCircle({Key key, this.child}) : super(key: key);

  @override
  DashedBorderState createState() => new DashedBorderState();
}

class DashedBorderState extends State<DashedCircle> with TickerProviderStateMixin<DashedCircle> {
  AnimationController controller;
  Animation<double> animation;

  @override
  void initState() {
    super.initState();
    controller = new AnimationController(vsync: this, duration: Duration(seconds: 10));
    animation = new Tween(begin: 0.0, end: pi * 2.0).animate(controller);
    controller.repeat();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: animation,
      builder: (context, child) {
        return new CustomPaint(
          painter: OvalPainter(
              color: Colors.blue, borderWidth: 1.0, dashLength: 5.0, spaceLength: 2.0, offset: animation.value),
          child: child,
        );
      },
      child: Container(
        width: 110.0,
        height: 110.0,
        padding: EdgeInsets.all(3.0),
        child: widget.child,
      ),
    );
  }
}

class OvalPainter extends CustomPainter {
  final Color color;
  final double borderWidth;
  final double dashLength;
  final double spaceLength;
  final double offset;

  OvalPainter(
      {@required this.borderWidth,
      @required this.dashLength,
      @required this.spaceLength,
      @required this.offset,
      @required this.color});

  double lastShortestSide;
  double lastDashLength;
  double lastSpaceLength;

  Path lastPath;

  @override
  void paint(Canvas canvas, Size size) {
    Rect rect = Offset.zero & size;

    var radius = rect.shortestSide / 2;

    canvas.translate(radius, radius);
    canvas.rotate(offset);

    Path path;
    if (lastShortestSide == rect.shortestSide &&
        dashLength == lastDashLength &&
        spaceLength == lastSpaceLength &&
        lastPath != null) {
      path = lastPath;
    } else {
      path = _getDashedCircularPath(rect.shortestSide / 2, dashLength, spaceLength);
      lastPath = path;
      lastShortestSide = rect.shortestSide;
      lastDashLength = dashLength;
      lastSpaceLength = spaceLength;
    }

    canvas.drawPath(
      path,
      new Paint()
        ..style = PaintingStyle.stroke
        ..color = color
        ..strokeWidth = borderWidth,
    );
  }

  @override
  bool shouldRepaint(OvalPainter oldDelegate) {
    return offset != oldDelegate.offset ||
        color != oldDelegate.color ||
        borderWidth != oldDelegate.borderWidth ||
        dashLength != oldDelegate.dashLength ||
        spaceLength != oldDelegate.spaceLength;
  }

  static Path _getDashedCircularPathFromNumber(double radius, int numSections, double dashPercentage) {
    var tau = 2 * pi;
    var actualTotalLength = tau / numSections;
    var actualDashLength = actualTotalLength * dashPercentage;

    double offset = 0.0;
    Rect rect = new Rect.fromCircle(center: Offset.zero, radius: radius);

    Path path = new Path();
    for (int i = 0; i < numSections; ++i) {
      path.arcTo(rect, offset, actualDashLength, true);
      offset += actualTotalLength;
    }

    return path;
  }

  static Path _getDashedCircularPath(double radius, double dashLength, double spaceLength) {
    // first, find number of radians that dashlength + spacelength take
    var tau = 2 * pi;
    var circumference = radius * tau;
    var dashSpaceLength = dashLength + spaceLength;
    var num = circumference / (dashSpaceLength);
    // we'll floor the value so that it's close-ish to the same amount as requested but
    // instead will be the same all around
    var closeNum = num.floor();

    return _getDashedCircularPathFromNumber(radius, closeNum, dashLength / dashSpaceLength);
  }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51160107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档