深入探索 Flutter 鸿蒙版的画笔使用与高级自定义动画

简介: 本文深入探讨了 Flutter 中的绘图功能,重点介绍了 CustomPainter 和 Canvas 的使用方法。通过示例代码,详细讲解了如何绘制自定义图形、设置 Paint 对象的属性以及实现高级自定义动画。内容涵盖基本绘图、动画基础、渐变动画和路径动画,帮助读者掌握 Flutter 绘图与动画的核心技巧。

写在前面
在 Flutter 中,绘图是一项强大的功能,可以帮助开发者创建自定义界面和独特的视觉效果。通过 CustomPainter 和 Canvas,我们可以实现复杂的图形和动画。本文将深入探讨 Flutter 中的画笔使用,包括如何编写高级自定义动画。

一、什么是 CustomPainter?
CustomPainter 是 Flutter 提供的一种用于绘制自定义图形的类。通过继承 CustomPainter,你可以重写 paint 和 shouldRepaint 方法,从而在 Canvas 上绘制任意形状、路径、文本等。

CustomPainter 的基本使用
import 'package:flutter/material.dart';

class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;

canvas.drawCircle(Offset(size.width / 2, size.height / 2), 50, paint);

}

@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}

class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('CustomPainter 示例')),
body: CustomPaint(
size: Size(200, 200),
painter: MyPainter(),
),
);
}
}

在这个示例中,我们创建了一个自定义画笔 MyPainter,在 Canvas 上绘制了一个蓝色的圆。

二、Paint 对象的属性
Paint 对象是绘制图形的核心。它有多个属性,可以控制绘制的样式和效果:

color:绘制颜色。
style:绘制样式,包括填充(PaintingStyle.fill)和描边(PaintingStyle.stroke)。
strokeWidth:描边的宽度。
strokeCap:描边的结束样式,如圆形(StrokeCap.round)或方形(StrokeCap.square)。
shader:用于渐变效果的着色器。
示例:使用 Paint 对象、
final paint = Paint()
..color = Colors.red
..style = PaintingStyle.stroke
..strokeWidth = 5;

canvas.drawRect(Rect.fromLTWH(50, 50, 100, 100), paint);
在这个示例中,我们使用 Paint 对象绘制了一个红色的矩形,宽度为 5 的描边。

三、实现高级自定义动画

  1. 动画基本概念
    在 Flutter 中,动画主要通过 Animation 和 AnimationController 实现。AnimationController 控制动画的进度,而 Animation 描述动画的值变化。

  2. 创建一个简单的动画
    下面是一个使用 CustomPainter 和 AnimationController 创建简单动画的示例:

class AnimatedPainter extends StatefulWidget {
@override
_AnimatedPainterState createState() => _AnimatedPainterState();
}

class _AnimatedPainterState extends State
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation _animation;

@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);

_animation = Tween<double>(begin: 50, end: 100).animate(_controller);

}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('动画绘制示例')),
body: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return CustomPaint(
size: Size(200, 200),
painter: MyAnimatedPainter(radius: _animation.value),
);
},
),
);
}
}

class MyAnimatedPainter extends CustomPainter {
final double radius;

MyAnimatedPainter({required this.radius});

@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;

canvas.drawCircle(Offset(size.width / 2, size.height / 2), radius, paint);

}

@override
bool shouldRepaint(MyAnimatedPainter oldDelegate) => radius != oldDelegate.radius;
}

解析代码
AnimationController:创建一个持续时间为 2 秒的动画控制器,并设置为循环。
Tween:定义动画的起始值和结束值(圆的半径)。
AnimatedBuilder:在动画变化时重建 CustomPaint,以更新绘制的圆的半径。
四、创建更复杂的自定义动画

  1. 渐变动画
    在动画中引入渐变效果,可以使用 Shader 属性来实现:

class GradientAnimatedPainter extends CustomPainter {
final double radius;

GradientAnimatedPainter({required this.radius});

@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..shader = RadialGradient(
colors: [Colors.red, Colors.blue],
stops: [0.5, 1],
).createShader(Rect.fromCircle(center: Offset(size.width / 2, size.height / 2), radius: radius));

canvas.drawCircle(Offset(size.width / 2, size.height / 2), radius, paint);

}

@override
bool shouldRepaint(GradientAnimatedPainter oldDelegate) => radius != oldDelegate.radius;
}

  1. 结合路径动画
    结合路径和自定义动画,可以创建更加复杂的效果。例如,沿路径绘制图形:

class PathAnimationPainter extends CustomPainter {
final double progress;

PathAnimationPainter({required this.progress});

@override
void paint(Canvas canvas, Size size) {
final path = Path()
..moveTo(50, 100)
..lineTo(150, 100)
..lineTo(100, 50)
..close();

final paint = Paint()
  ..color = Colors.green
  ..style = PaintingStyle.fill;

canvas.drawPath(Path.combine(PathOperation.intersect, path, path), paint);
canvas.drawCircle(Offset(100 * progress, 50), 5, Paint()..color = Colors.red);

}

@override
bool shouldRepaint(PathAnimationPainter oldDelegate) => progress != oldDelegate.progress;
}

  1. 综合示例:完整代码
    将上述所有元素组合成一个完整的例子,创建一个包含路径和渐变动画的画布:

class ComplexAnimationExample extends StatefulWidget {
@override
_ComplexAnimationExampleState createState() => _ComplexAnimationExampleState();
}

class _ComplexAnimationExampleState extends State
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation _animation;

@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 4),
vsync: this,
)..repeat(reverse: true);

_animation = Tween<double>(begin: 0, end: 1).animate(_controller);

}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('复杂动画示例')),
body: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return CustomPaint(
size: Size(200, 200),
painter: PathAnimationPainter(progress: _animation.value),
);
},
),
);
}
}

写在最后
在 Flutter 中,CustomPainter 和 Canvas 提供了强大的绘图能力,适合实现各种自定义图形和动画。通过结合 Animation 和 AnimationController,你可以创建平滑且复杂的动画效果。本文介绍了基本的画笔使用、动画控制,以及如何将它们结合实现高级自定义动画的技巧。

希望本篇博客能帮助你更好地理解 Flutter 中的画笔使用与动画创建,开启你的创作之旅!如果你对 Flutter 动画有任何问题或想法,欢迎在评论区讨论!
————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/lbcyllqj/article/details/142967695

目录
相关文章
|
28天前
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
116 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
2天前
|
缓存 Java 测试技术
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
28 3
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
|
25天前
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
75 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
2月前
|
人工智能 前端开发 API
鸿蒙开发:简单自定义一个绘制画板
画板,最重要的就是绘制,保证线条绘制的连续性,这一点很重要,还有就是beginPath方法一定要调用,否则更改颜色以及绘制就会出现不连续以及颜色设置错误问题。
72 14
|
2月前
|
索引 API
鸿蒙开发:自定义一个股票代码选择键盘
金融类的软件,特别是股票基金类的应用,在查找股票的时候,都会有一个区别于正常键盘的键盘,也就是股票代码键盘,和普通键盘的区别就是,除了常见的数字之外,也有一些常见的股票代码前缀按钮,方便在查找股票的时候,更加方便的进行检索。
鸿蒙开发:自定义一个股票代码选择键盘
|
2月前
|
API
鸿蒙开发:自定义一个英文键盘
实现方式呢,有很多种,目前采用了比较简单的一种,如果大家采用网格Grid组件实现方式,也是可以的,但是需要考虑每行的边距以及数据,还有最后两行的格子占位问题。
鸿蒙开发:自定义一个英文键盘
|
2月前
|
API
鸿蒙开发:了解显式动画animateTo
在实际的开发中,应该遵循规范,正确的使用属性动画animateTo,切莫在轮询中使用,否则就会造成本不属当前的动画进行执行,造成UI错误,还有一点需要注意,那就是直接使用animateTo可能导致实例不明确的问题,建议使用getUIContext获取UIContext实例,并使用animateTo调用绑定实例的animateTo。
124 3
|
2月前
|
API
鸿蒙开发:自定义一个车牌字母键盘
车牌字母键盘和一般的键盘还有很大区别的,大家可以发现,键盘上是少一个字母的,因为I字母具有混淆性,所以这个字母是不在车牌键盘内的。
鸿蒙开发:自定义一个车牌字母键盘
|
2月前
|
Dart 前端开发 IDE
鸿蒙Flutter实战:14-现有Flutter 项目支持鸿蒙 II
本文介绍了如何将现有 Flutter 项目适配鸿蒙系统,详细步骤包括安装 FVM、使用 FVM 安装 Flutter SDK、搭建开发环境、创建项目架构和壳工程等。
311 4
鸿蒙Flutter实战:14-现有Flutter 项目支持鸿蒙 II
|
2月前
|
JavaScript Java 容器
鸿蒙应用开发从入门到入行 - 篇4:层叠布局、自定义组件、ForEach
导读:在本篇文章里,您将掌握层叠布局、自定义组件的用法,特别是自定义组件将来的开发中必然会用,其中应该特别关注自定义组件的一些规范与装饰器。
68 7
鸿蒙应用开发从入门到入行 - 篇4:层叠布局、自定义组件、ForEach

热门文章

最新文章

  • 1
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 4
    【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 6
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
  • 7
    flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
  • 8
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 9
    【06】flutter完成注册页面-密码登录-手机短信验证-找回密码相关页面-并且实现静态跳转打包demo做演示-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 10
    flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡