整理Flutter App开发过程中遇到的问题及解决方法
最近使用flutter开发一款app,因为是第一次接触flutter,在开发过程中遇到一些问题或常用的功能点,在此记录一下(持续更新…)
(1)禁止横屏
-
在开发过程中,如果手机设置了自动旋转,手机横屏会使你当前开发的app也横向展示。有时候app横向展示的时候页面会出现布局错乱。此时我们可以禁止横屏展示。代码截图如下:
-
在main.dart中添加如下代码:
// An highlighted block //import services.dart import 'package:flutter/services.dart'; SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, //只能纵向 DeviceOrientation.portraitDown, //只能纵向 ]);
(2)粘贴复制中文化
-
flutter 中复制粘贴显示出来默认的是英文(paste),修改为中文需要引入flutter_localizations,代码截图如下:
-
在main.dart中添加如下代码
// An highlighted block //import flutter_localizations.dart import 'package:flutter_localizations/flutter_localizations.dart'; localizationsDelegates: [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: [ const Locale('zh', 'CN'), const Locale('en', 'US'), ],
(3)修改状态栏的颜色
flutter app修改状态栏的颜色分为带有appbar和不带appbar2种情况。
-
不带appbar的情况代码如下
// An highlighted block return AnnotatedRegion <SystemUiOverlayStyle>( child: Scaffold( backgroundColor: Colors.white, body:Container() ), value: SystemUiOverlayStyle( //值可以根据需要修改 statusBarColor: Colors.transparent ), )
-
带有appbar的情况,需在appBar中添加 brightness: Brightness.light(值可以根据需要修改),代码如下:
// An highlighted block return AnnotatedRegion <SystemUiOverlayStyle>( child: Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, brightness: Brightness.light, elevation: 0, //去掉阴影 centerTitle: true, ), body:Container() ), value: SystemUiOverlayStyle( //值可以根据需要修改 statusBarColor: Colors.transparent ), )
(4)下拉刷新
下拉刷新的情况我们可以使用RefreshIndicator来实现,实现代码如下:
// An highlighted block
return Scaffold(
backgroundColor: Colors.black,
body:RefreshIndicator(
//圆圈进度颜色
color: Colors.blue,
//下拉停止的距离
displacement: 44.0,
//背景颜色
backgroundColor: Colors.grey[200],
onRefresh: () async{
//模拟网络请求
await Future.delayed(Duration(milliseconds: 2000), () {
//TODO:具体的实现方法
});
//结束刷新
return Future.value(true);
}
)
);
(5)setState更新数据,子控件数据不更新
- 关于这个问题,我们拿上面的问题来举例,我的父组件中是遍历pageview的(仿抖音刷视频),当我下拉刷新时,我将数据倒序排列,发现,数据改变了,但是第一个页面的视频没有刷新,这时我们需要在子组件中添加didUpdateWidget来刷新当前页面,代码如下:
在父组件中,我们在onRefresh方法中更新了_videoList 数组。我们的子组件是VideoPlayerMaskWidget
// An highlighted block
return Scaffold(
backgroundColor: Colors.black,
body: RefreshIndicator(
//圆圈进度颜色
color: Colors.blue,
//下拉停止的距离
displacement: 44.0,
//背景颜色
backgroundColor: Colors.grey[200],
onRefresh: () async {
//模拟网络请求
await Future.delayed(Duration(milliseconds: 2000), () {
//TODO:具体的实现方法
//_videoList[0]['player'].pause();
List _list = [];
_list.addAll(_videoList.reversed);
if (_list.isNotEmpty) {
//我们更新了_videoList
setState(() {
_videoList = _list;
});
}
});
//结束刷新
return Future.value(true);
},
child: _videoList.isNotEmpty
? PageView.builder(
scrollDirection: Axis.vertical,
controller: _pageController,
itemBuilder: (context, index) {
Widget _player = Container(
child: FijkView(
width: ScreenAdapter.setWidth(750),
height: ScreenAdapter.setHeight(1200),
player: _videoList[index]['player'],
fit: FijkFit(
sizeFactor: -0.1,
aspectRatio: 0.55,
alignment: Alignment.center,
),
color: Colors.black,
),
);
return VideoPlayerMaskWidget(
player: _player, //播放器
videoModel: _videoList[index],
);
},
itemCount: _videoList.length,
onPageChanged: (index) {
//TODO:pageview 翻页
},
)
: Container(),
),
);
此时在我们的子组件中视频的地址虽然更新了,但是界面播放的还是原来的视频,这时,在我们的子组件(VideoPlayerMaskWidget)中需要添加didUpdateWidget来进行刷新子组件的值。代码如下:
// An highlighted block
@override
didUpdateWidget(VideoPlayerMaskWidget oldWidget){
//给 _videoModel 重新赋值
_videoModel = widget.videoModel;
}
(6)瀑布流布局的实现
现在很多的app都趋向于瀑布流式的布局,下面我们介绍利用flutter_staggered_grid_view组件来实现瀑布流布局。组件详细的api可以在https://pub.flutter-io.cn/packages/flutter_staggered_grid_view中查看。
- 首先在pubspec.yaml文件中引入组件
// An highlighted block
flutter_staggered_grid_view: ^0.6.1
在需要使用的页面import 组件,代码如下:
// An highlighted block
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
@override
Widget build(BuildContext context) {
var cardWidth = (screenwidth - ScreenAdapter.setWidth(30)) / 2;
return StaggeredGrid.count(
crossAxisCount: 2, //总共多少列
mainAxisSpacing: 10,//主轴间距
crossAxisSpacing: 10,//纵轴间距
//_list是你需要展示的数据
children: _list.map((item) {
return InkWell(
onTap: () {
//TODO:点击事件
},
child: Container(),
);
}).toList(),
);
}
}
(7)倒计时
flutter中实现倒计时代码如下:
int _countDown = 5;
Timer? _countDownTimer = null;
int _seconds = 5;
// 页面销毁
dispose() {
super.dispose();
_countDownTimer?.cancel();
_countDownTimer = null;
}
//倒计时
void _setCountDown() {
setState(() {
if (_countDownTimer != null) {
return;
}
_seconds = _countDown;
_countDownTimer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
if (_countDown > 0) {
_seconds = _countDown--;
} else {
//TODO:业务代码
_countDownTimer!.cancel();
_countDownTimer = null;
}
});
});
});
}