[英]Flutter: ClipRRect vs Container with BoxDecoration
[英]How can I customize / rotate a BoxDecoration for a Container widget in Flutter?
我有一個小工具,可為公交車站建立圓形的個人資料圖片,截至目前,它具有圍繞個人資料圖片的圓形邊框。 我想更改為虛線的圓形邊框,並通過以虛線形式在個人資料圖片上畫圈/旋轉來設置動畫。 有沒有簡單的方法可以做到這一點? 非常感謝您提供的任何幫助!
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,
),
),
),
);
不幸的是, 簡單的答案是沒有簡單的方法可以做到這一點。 顫抖的人以其無窮的智慧得出的結論是,虛線的性能不足以將其包含在顫振中,因此,沒人會畫出虛線。 (是的,這句話的邏輯上的不連續是故意的。不要誤會我的意思-我喜歡撲撲,開發人員做得很好,但是他們似乎確實是根據性能而不是功能做出了一些半任意的決定。 )。
我所見的原因解釋是,基本上C ++版本會執行與dart代碼類似的操作(除非它直接在GPU上完成),因此他們期望有人最終在dart中實現虛線(可能作為一部分)圖書館?)。 有關進展和討論,請參見此github錯誤 ...,如果您以后希望看到破折號,請對其+1。 如果有足夠的人這樣做,那么最終撲朔迷離的人可能會決定實施它。
但是目前,這意味着沒有簡單的方法可以用虛線制作CircleBorder或任何其他類型的邊框。
但是,只要付出最大的努力 ,就可以准確地實現您想要的=)。 以下是為您提供所需功能的快速代碼。 請注意-它不是非常優化的,並且可能有更簡單的方法來執行此操作,並且您可能會使用裝飾並在其中或其他地方實現繪畫等……但這確實可行。
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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.