Flutter新手开发问题和记录
说明: $ROOT_PATH: 代表flutter项目的根目录
一、访问加速
1、gradle会在安卓编译的时候下载一些依赖,默认的仓库是google的,在国内访问速度会很慢,所以替换阿里云的仓库,修改 $ROOT_PATH/android/build.gradle 文件,修改内容如下
buildscript {
ext.kotlin_version = '1.6.21'
repositories {
- google()
- mavenCentral()
+ 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镜像,执行下面的命令设置,或者写入到.zshrc文件中后,重启终端再运行 flutter pub get 就会快很多。
官方说明:Using Flutter in China | Flutter
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
二、常见实现
1、取消点击的水波效果(在iOS上一般不需要),修改主题就可以了
theme: ThemeData(
highlightColor: Colors.transparent,
splashColor: Colors.transparent
),
2、修改Tabbar指示器的宽度为固定宽度,默认仅支持(和tab文本一样长、和tab一样长,两种方式)
- 修改原生的UnderlineTabIndicator组件
- 修改渲染长度的函数
- 使用自定义的UnderlineTabIndicator来渲染指示器
目标效果,指示器是固定宽度的:
实现如下:
/// 可以固定宽度的tab指示器
/// 基于UnderlineTabIndicator修改
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;
// 添加成员变量width
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);
}
}
3、修改状态栏为白色,需要在runApp后执行下面的代码
void main() {
runApp(const MyApp());
// 修改状态栏为白色
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(statusBarColor: Colors.white));
}
4、取消右上角的debug标识,需要配置MaterialApp
debugShowCheckedModeBanner: false
5、退出app
exit(0)
6、配置appBar的高度,我们查看AppBar的定义并不能修改高度,需要使用PreferredSize包裹一下才可以设置高度,如下:
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size(double.infinity, 80),
child: AppBar(
title: Text(_tabs[_tabIndex]["name"]),
backgroundColor: Colors.red,
actions: [
IconButton(
onPressed: () {
context.push("/scan");
},
icon: const Icon(Icons.qr_code_scanner))
]),
)
)
}
展示效果:
7、隐藏和展示状态栏,例如跳转到拍照页面时候,需要隐藏,但是隐藏和展示的时候没有动画效果,比较卡顿,还是不建议使用的,目前还在寻找其他的解决方案。
// 隐藏
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
// 展示
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
8、Positioned宽度占满父容器的方案,只需要左右都设置为0即可,使用宽度设置为double.infinity无效;同理,要是想高度占满父容器,只需要上下都设置为0即可
Positioned(
left: 0,
right: 0,
child: Container(
color: Colors.red,
child: Text("测试定位"),
))
三、常见问题
1、如果组件定义方法的时候有参数,在使用组件的时候传入的方法必须写上参数,例如下面的value是不能省略的,即使你不用
Switch(value: true, onChanged: (value) {}),
2、安卓模拟器一个有用的快捷键
- 摇一摇:CMD+M(windows应该是ctrl+M)
四、常用插件
- 请求数据 dio
- 轻量强大的状态管理库 getx
- 轻量的路由管理工具 go_router
- 页面loading组件 flutter_easyloading
- webview webview_flutter
- 调用照相机 camera
- 二维码扫描识别 qr_code_scanner
转载自:https://juejin.cn/post/7195363812378640440