
-
去年失业闲的无聊开发了一个简单的音乐播放器,过去一年,个人水平也有长进,近期花时间使用最新版Flutter SDK 重构。
-
其实是有设计图的进行参考的,具体的作者已经找不到了,不过贴一下展示一下。

- Flutter 在不同设备上的UI兼容性非常好。

项目中一些技术分享
半透明的高斯模糊AppBar 和 BottomNavigationBar
# Flutter 透明模糊化AppBar 和 BottomNavigationBar 优化方案
参考代码
dart
appBar: AppBar(
title: const Text("DM's Blur Gallery"),
flexibleSpace: BlurWidget(child: SizedBox.expand()),
),
extendBody: true,
bottomNavigationBar: BlurWidget(
child: _buildMenus(themeData),
),
滚动列表中的高斯模糊锯齿和效果丢失问题
每个音乐卡片都存在高斯模糊区域。如果裁剪设置不合理,就会存在问题

dart
ClipRRect(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.antiAliasWithSaveLayer,
Flutter 的ClipRRect组件有四种模式,默认是hardEdge,性能较好,但是在physics: ClampingScrollPhysics() 时,滚动列表会丢失模糊效果。 Flutter 在安卓上,listview 类型 默认都是 ClampingScrollPhysics。 将Clip模式设置为Clip.antiAliasWithSaveLayer ,即可取得最佳效果。
下面是裁剪模式的粗略翻译。
dart
none 不裁减
hardEdge 粗略裁剪
antiAlias 高精度裁剪
antiAliasWithSaveLayer 超高精度裁剪,并隔离区域
主题色切换
在main.dart的App配置中,设置
dart
return GetMaterialApp(
title: 'DMusic',
theme: _getLightTheme(),
darkTheme: _getDarkTheme(),
themeMode: ThemeMode.dark,
debugShowCheckedModeBanner: false,
home: SplashPage(),
);
dart
colorScheme: const ColorScheme.dark(
brightness: Brightness.dark,
// 主色调
primary: Colors.black,
//主色调 - 反转
inversePrimary: Colors.black,
// 文字颜色
onSurface: Colors.white,
// 文字颜色 - 反转
onInverseSurface: Colors.black,
// 表面颜色
surface: Colors.black,
// 表面颜色 - 反转
inverseSurface: Colors.white,
),
弧形进度条(支持点击和拖拽)

主要是通过修改Flutter 默认Slider的渲染逻辑,加入了路径渲染 和 路径裁剪。
- 自行实现难度较高,所以修改官方组件相对简单。
底部卡片动画

animate_do: ^4.2.0 # 动画组件
底部卡片的动画使用的是
dart
SlideInUp(
from: curveHeight,
animate: controller.slideController?.isCompleted ?? false,
controller: (slideController) {
controller.slideController = slideController;
},
child: _buildCard(theme),
),
底部弧形卡片
dart
/// 底部画刷
class BottomCurvePainter extends CustomPainter {
BottomCurvePainter(this.backgroundColor);
/// 背景色
final Color backgroundColor;
@override
void paint(Canvas canvas, Size size) {
debugPrint("重绘:底部背景-画刷");
// 贝塞尔曲率
double bezier = 25;
Path background = Path()
..moveTo(0, bezier)
..quadraticBezierTo(size.width / 2, -bezier, size.width, bezier)
..lineTo(size.width, size.height)
..lineTo(0, size.height)
..lineTo(0, bezier)
..close();
//canvas.drawShadow(background, Colors.black, 10, true);
canvas.clipPath(background);
canvas.drawColor(backgroundColor, BlendMode.srcIn);
}
@override
bool shouldRepaint(covariant BottomCurvePainter oldDelegate) {
return backgroundColor != oldDelegate.backgroundColor;
}
}
音频播放
just_audio: ^0.10.5 # 音频播放
这个组件其实有一些问题,比如
- 不兼容Windows
- 没有切换音乐的回调
有可能是文档没查好,如果有不同理解,请在评论区提出。
播放按钮动画

dart
AnimatedIcon(
size: iconSize,
color: theme.colorScheme.primary,
icon: AnimatedIcons.play_pause,
progress: controller ?? AlwaysStoppedAnimation(0),
),
SafeArea安全区域
按钮下方弧形屏幕区域,既是非安全区域

dart
/// 底部安全区域
double bottomSafe = MediaQuery.of(context).padding.bottom;
/// 使用SafeAre的minimum就可以设置安全区域。
/// minimum 是最低安全距离的意思,当设备没有安全距离或安全距离小于最小值都会使用设定的最小值。
SliverSafeArea(
minimum: EdgeInsets.only(
// left: 15,
// right: 15,
bottom: bottomHeight + 20,
),
最后源码也放出来,当然这个项目也会持续更新,如果有喜欢设计的朋友可以联系我,一起参与到后续的开发设计中。 源码地址