一、访问加速
1. 编译时加速
在安卓编译时,Gradle会下载依赖,默认的Google仓库在国内访问较慢。可以通过修改$ROOT_PATH/android/build.gradle文件,将仓库替换为阿里云镜像以提升速度。
buildscript {
ext.kotlin_version = '1.6.21'
repositories {
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.0-rc03'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
2. Flutter的Dart仓库访问加速
设置国内Flutter镜像可以显著加快flutter pub get的速度。可以通过以下命令设置环境变量,或将其写入.zshrc(或.bashrc)文件后重启终端。
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
二、常见实现
1. 取消点击的水波效果
在iOS平台或某些场景下,可能需要取消Material组件默认的水波纹效果。可以通过修改主题实现。
theme: ThemeData(
highlightColor: Colors.transparent,
splashColor: Colors.transparent
),
2. 修改TabBar指示器的宽度为固定值
Flutter自带的TabBar指示器宽度通常与标签文本或标签本身等宽。若需要固定宽度的指示器(例如宽度为20的逻辑像素),可以自定义一个Decoration。
import 'package:flutter/material.dart';
class FixedUnderlineTabIndicator extends Decoration {
const FixedUnderlineTabIndicator({
this.width = 20,
this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
this.insets = EdgeInsets.zero,
});
final BorderSide borderSide;
final EdgeInsetsGeometry insets;
final double width;
@override
Decoration? lerpFrom(Decoration? a, double t) {
if (a is FixedUnderlineTabIndicator) {
return FixedUnderlineTabIndicator(
borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
insets: EdgeInsetsGeometry.lerp(a.insets, insets, t)!,
);
}
return super.lerpFrom(a, t);
}
@override
Decoration? lerpTo(Decoration? b, double t) {
if (b is FixedUnderlineTabIndicator) {
return FixedUnderlineTabIndicator(
borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!,
);
}
return super.lerpTo(b, t);
}
@override
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
return _FixedUnderlinePainter(this, onChanged);
}
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
return Rect.fromLTWH(
indicator.left + (indicator.width - width) / 2,
indicator.bottom - borderSide.width,
width,
borderSide.width,
);
}
@override
Path getClipPath(Rect rect, TextDirection textDirection) {
return Path()..addRect(_indicatorRectFor(rect, textDirection));
}
}
class _FixedUnderlinePainter extends BoxPainter {
_FixedUnderlinePainter(this.decoration, VoidCallback? onChanged) : super(onChanged);
final FixedUnderlineTabIndicator decoration;
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration.size != null);
final Rect rect = offset & configuration.size!;
final TextDirection textDirection = configuration.textDirection!;
final Rect indicator = decoration._indicatorRectFor(rect, textDirection).deflate(decoration.borderSide.width / 2.0);
final Paint paint = decoration.borderSide.toPaint()..strokeCap = StrokeCap.square;
canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
}
}
使用时,在TabBar的indicator属性中传入自定义的FixedUnderlineTabIndicator即可。
3. 修改状态栏样式
若需将状态栏背景色设置为白色,可以在runApp之后调用系统方法。
void main() {
runApp(const MyApp());
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(statusBarColor: Colors.white));
}
另一种方式是通过全局主题设置AppBar的样式,这可以统一管理所有页面的状态栏。
appBarTheme: const AppBarTheme(
elevation: 0,
color: Colors.white,
foregroundColor: Colors.black,
titleTextStyle: TextStyle(color: Colors.black, fontSize: 20),
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.white,
statusBarIconBrightness: Brightness.dark // 浅色背景用深色图标
)
);
4. 隐藏Debug标识
在开发模式下,Flutter App右上角会有一个“Debug”横幅。要在MaterialApp中隐藏它,设置如下属性:
debugShowCheckedModeBanner: false
5. 设置AppBar高度
AppBar组件本身不直接提供高度属性。如果需要自定义高度,可以使用PreferredSize组件进行包裹。
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size(double.infinity, 80), // 设置高度为80
child: AppBar(
title: Text(_tabs[_tabIndex]["name"]),
backgroundColor: Colors.red,
actions: [
IconButton(
onPressed: () { context.push("/scan"); },
icon: const Icon(Icons.qr_code_scanner))
]),
)
);
}
6. 隐藏和显示状态栏
在某些全屏页面(如拍照页)可能需要隐藏状态栏。但需注意,Flutter提供的该方法在隐藏和显示时可能没有平滑的动画过渡,体验上可能有些卡顿,请谨慎使用。
// 隐藏状态栏
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
// 显示状态栏(例如采用edgeToEdge模式)
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
7. Positioned组件占满父容器宽度或高度
Positioned组件想水平撑满父容器(Stack),将left和right都设为0即可,设置width: double.infinity是无效的。同理,垂直撑满则需要设置top和bottom为0。
Positioned(
left: 0,
right: 0,
child: Container(
color: Colors.red,
child: Text("测试定位"),
))
8. 实现文本部分点击
使用RichText和TextSpan组合,可以实现在一段文本中让特定部分可点击。
RichText(
text: TextSpan(
style: TextStyle(
color: const Color(0xff252525),
height: 20 / 14,
fontSize: 14), // 基础样式
text: '上述是常见问题,如果您有新的疑问,请',
children: [
TextSpan(
text: “点此反馈”,
style: const TextStyle(color: Color(0xff2F92FF)),
recognizer: TapGestureRecognizer()..onTap = () {
Get.toNamed(‘/feedback’); // 点击跳转
}
),
const TextSpan(text: “,我们会尽快联系您”)
]
)
)
9. 防止圆角Container的子元素溢出
当为Container设置borderRadius圆角后,如果其子元素(如图片)超出边界,默认不会被裁剪。需要设置clipBehavior属性。
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
clipBehavior: Clip.hardEdge, // 关键属性,裁剪超出部分
child: Image.network(...),
)
10. 自定义AppBar需实现PreferredSizeWidget
自定义的AppBar组件如果直接用在Scaffold的appBar属性中,可能会遇到类型错误。需要让自定义组件混入PreferredSizeWidget并实现preferredSize的getter。
class CustomAppBar extends StatelessWidget with PreferredSizeWidget {
const CustomAppBar({super.key, this.title});
final Widget? title;
// ... 其他属性和build方法
@override
Widget build(BuildContext context) {
return AppBar(title: title, ...);
}
@override // 必须实现此getter
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
11. 清除应用缓存
Flutter应用的缓存文件通常存储在应用的临时目录中。可以使用path_provider插件获取该目录并清除。
import 'package:path_provider/path_provider.dart';
_clearCache() async {
final dir = await getTemporaryDirectory(); // 获取缓存目录
dir.deleteSync(recursive: true); // 递归删除
}
注意:如果在该缓存目录中存储了应用运行所需的重要数据,则不应直接删除整个文件夹,而应遍历后选择性删除。
12. 在Flutter页面中展示Markdown
使用flutter_markdown插件可以方便地渲染Markdown内容。注意,该插件可能不支持内联HTML标签。
MarkdownBody(
data: markdownContent,
selectable: true, // 允许文本选择
softLineBreak: true,
styleSheet: MarkdownStyleSheet(
p: TextStyle(fontSize: 15, color: Colors.grey[700])
),
onTapLink: (text, href, title) {
// 处理链接点击
Get.toNamed(‘/webview?url=$href’);
}
)
13. 生成带透明度的实际颜色
有两种方式为颜色添加透明度:
Colors.red.withOpacity(0.16): 这种方式生成的颜色是真正半透明的,如果作为背景,会透出底部的内容。Color.alphaBlend(Colors.red.withOpacity(0.16), Colors.white): 这种方式是将半透明颜色与一个背景色(如白色)进行混合,生成一个不透明的新颜色,不会透出底部内容。
14. 为操作添加震动反馈
适当的触觉反馈可以提升用户体验。Flutter提供了HapticFeedback类来调用设备震动。
import ‘package:flutter/services.dart’;
// 中度震动反馈
HapticFeedback.mediumImpact();
// 也可使用 .lightImpact() 或 .heavyImpact()
15. 实现毛玻璃效果
使用BackdropFilter组件可以实现背景模糊的毛玻璃效果,常见于导航栏等元素。
ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), // 模糊度
child: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.4), // 半透明底色
),
child: Text(“毛玻璃后的文字”),
),
),
)
三、常见问题
1. 组件回调参数不可省略
例如Switch组件的onChanged回调,即使你不使用value参数,也必须在声明时写上。
Switch(value: true, onChanged: (value) {}), // 正确
// Switch(value: true, onChanged: () {}), // 错误,会报类型不匹配
2. Android模拟器实用快捷键
- 摇一摇(打开DevMenu):在模拟器窗口激活时,按
Ctrl + M(Windows/Linux) 或Cmd + M(Mac)。
3. 折叠IDE控制台中冗长的调试输出
在Android Studio或IntelliJ IDEA中,可以折叠以特定模式开头的日志行,让自定义的print信息更清晰。
- 在Run/Debug控制台选中一条你想折叠的日志行中的特征字符串(如
E/FrameEvents)。 - 右键点击,选择 “Fold lines like this” (或中文“像这样折叠行”)。
4. iOS真机调试LLDB警告
在iOS真机调试时,可能会遇到关于libobjc的LLDB警告,这可能会影响调试性能。通常可以通过删除Xcode的设备支持缓存来解决。
rm -rf ~/Library/Developer/Xcode/iOS\ DeviceSupport
删除后,重新使用Xcode运行一次应用,之后再用Flutter命令或Android Studio运行即可。
四、常用插件推荐
1. 功能型插件
- 网络请求:dio
- 状态管理:getx (功能强大且轻量)
- WebView:webview_flutter
- 相机:camera
- 二维码扫描:qr_code_scanner
- 下拉刷新/上拉加载:pull_to_refresh
- 日历:device_calendar (访问系统日历或展示组件)
- Lottie动画:lottie
- 图片缓存:cached_network_image
- 应用信息:package_info_plus
- 设备信息:device_info_plus
- 网络状态:connectivity_plus
- 屏幕唤醒:wakelock
- 数据埋点:sensors_analytics_flutter_plugin
- 路径获取:path_provider
- 本地存储:shared_preferences
- 列表侧滑:flutter_slidable
- 打开应用设置:app_settings
2. UI型插件
- SVG渲染:flutter_svg
- 全局Loading:flutter_easyloading
- 加载动画:flutter_spinkit
- 透明占位图:transparent_image
- Toast:fluttertoast