flutter는 canvas로 테두리를 그리고 애니메이션 효과를 실현합니다
6555 단어 flutter 성장canvas프레임 애니메이션flutter
import 'dart:ui';
import 'package:flutter/material.dart';
class CutDownBorderButton extends StatefulWidget {
const CutDownBorderButton(
{Key? key,
this.radius,
required this.width,
required this.height,
required this.cutController,
this.initBorderColor,
this.activeBorderColor,
this.borderWidth})
: super(key: key);
@override
_CutWidgetState createState() => _CutWidgetState();
final double? radius;
final double width;
final double height;
final Color? initBorderColor;
final Color? activeBorderColor;
final double? borderWidth;
final CutController cutController;
}
class _CutWidgetState extends State {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return CustomSingleChildLayout(
delegate: _SingleChildLayoutDelegate(Size(widget.width, widget.height)),
child: CustomPaint(
painter: BorderPainter(
progress: widget.cutController.value /
widget.cutController.duration!.inSeconds,
radius: widget.radius,
width: widget.width,
height: widget.height,
borderWidth: widget.borderWidth,
initBorderColor: widget.initBorderColor,
activeBorderColor: widget.activeBorderColor,
boxColor: Colors.amber)));
}
}
class _SingleChildLayoutDelegate extends SingleChildLayoutDelegate {
final Size size;
_SingleChildLayoutDelegate(this.size);
@override
Size getSize(BoxConstraints constraints) {
return size;
}
@override
bool shouldRelayout(_SingleChildLayoutDelegate oldDelegate) {
return this.size != oldDelegate.size;
}
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return BoxConstraints.tight(size);
}
@override
Offset getPositionForChild(Size size, Size childSize) {
return Offset((size.width - childSize.width) / 2,
(size.height - childSize.height) / 2);
}
}
class BorderPainter extends CustomPainter {
BorderPainter(
{required this.width,
required this.height,
required this.progress,
required this.boxColor,
this.initBorderColor,
this.activeBorderColor,
this.radius,
this.borderWidth});
final double? radius;
final double? borderWidth;
final double width;
final double height;
final double progress;
final Color boxColor;
final Color? initBorderColor;
final Color? activeBorderColor;
@override
void paint(Canvas canvas, Size size) {
Rect rect = Rect.fromCenter(
center: Offset(width / 2, height / 2), width: width, height: height);
RRect rRect = RRect.fromRectAndRadius(rect, Radius.circular(radius!));
Paint paintRect = Paint()
..color = boxColor
..style = PaintingStyle.fill;
canvas.drawRRect(rRect, paintRect);
canvas.save();
Paint initBorder = Paint()
..color = initBorderColor ?? Colors.red
..style = PaintingStyle.stroke
..strokeWidth = borderWidth ?? 5;
Paint activeBorder = Paint()
..color = activeBorderColor ?? Colors.grey
..style = PaintingStyle.stroke
..strokeWidth = borderWidth ?? 5;
Path path = Path()
..moveTo(width / 2, 0)
..relativeLineTo(width / 2 - radius!, 0)
..relativeArcToPoint(Offset(radius!, radius!),
radius: Radius.circular(radius!))
..relativeLineTo(0, height - radius! * 2)
..relativeArcToPoint(Offset(-radius!, radius!),
radius: Radius.circular(radius!))
..relativeLineTo(-width + radius! * 2, 0)
..relativeArcToPoint(Offset(-radius!, -radius!),
radius: Radius.circular(radius!))
..relativeLineTo(0, -height + radius! * 2)
..relativeArcToPoint(Offset(radius!, -radius!),
radius: Radius.circular(radius!))
..relativeLineTo(width / 2 - radius!, 0)
..close();
canvas.drawPath(path, initBorder);
path.addRRect(rRect);
PathMetrics pathMetrics = path.computeMetrics();
PathMetric pathMetric = pathMetrics.first;
Path extPath = pathMetric.extractPath(0, pathMetric.length * progress);
canvas.drawPath(extPath, activeBorder);
canvas.restore();
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
class CutController extends AnimationController {
CutController({required TickerProvider vsync, int durationInt = 30})
: super(
reverseDuration: Duration(milliseconds: durationInt * 1000),
duration: Duration(milliseconds: durationInt * 1000),
lowerBound: 0,
upperBound: durationInt.toDouble(),
vsync: vsync);
}
사용 예:
import 'package:flitter_okgo/cut_down_border_button.dart';
import 'package:flitter_okgo/hand_written_board.dart';
import 'package:flutter/material.dart';
class CutDownBorderPage extends StatefulWidget {
@override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State
with SingleTickerProviderStateMixin {
late CutController controller = CutController(vsync: this, durationInt: 3);
@override
void initState() {
super.initState();
controller.addListener(() {
setState(() {});
});
}
Widget get initFloatingActionButton {
return FloatingActionButton(
backgroundColor: Colors.grey,
elevation: 1,
focusElevation: 1,
onPressed: () {
controller.forward();
},
child: Icon(Icons.android),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
floatingActionButton: initFloatingActionButton,
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
body: Center(
child: Stack(
children: [
CutDownBorderButton(
cutController: controller,
radius: 25,
width: 100,
height: 100,
),
Container(
width: 100,
height: 100,
child: Center(
child: Text('${controller.value.round()}'),
),
),
],
)),
);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
flutter 팔레트 2.0 지우개손으로 쓴 것을 실현하는 기초 위에서 지우개 기능을 추가하다 사용 시범...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.