static List contentOptions = [
new IndexPage(),
Text(
'Index 1 场馆预定',
style: optionsStyle,
),
PersonCenterPage(),
];
// contentOptions 是widget List
方式一
body: Center(
child: contentOptions.elementAt(_selectedIndex)
),
这种方式切换后会状态丢失
方式二
body:IndexedStack(
index:_selectedIndex,
children:contentOptions
)
这种方式切换后不会丢失状态
assets:
- images/type1.png
- images/type2.png
- images/type3.png
- images/banner.png
import 'package:json_annotation/json_annotation.dart';
// user.g.dart 将在我们运行生成命令后自动生成
part 'user.g.dart';
///这个标注是告诉生成器,这个类是需要生成Model类的
@JsonSerializable()
class User{
User(this.name, this.email);
String name;
String email;
//不同的类使用不同的mixin即可
factory User.fromJson(Map json) => _$UserFromJson(json);
Map toJson() => _$UserToJson(this);
}
// 一次性生成
flutter packages pub run build_runner build
// 使用watcher可以使我们的源代码生成的过程更加方便。它会监视我们项目中文件的变化,并在需要时自动构建必要的文件。
// 只需启动一次观察器,然后它就会在后台运行,这是安全的。
flutter packages pub run build_runner watch
import 'package:hello/models/user.dart';
// 接口请求返回数据
Response response = await dio.get('https://api.apiopen.top/musicRankings');
// Json转Dart Model类
User user=User.fromJson(response.data);
import 'package:json_annotation/json_annotation.dart';
part 'musicRank.g.dart';
@JsonSerializable()
class MusicRank {
List- result;
MusicRank(this.result);
factory MusicRank.fromJson(Map
json) => _$MusicRankFromJson(json);
Map toJson()=>_$MusicRankToJson(this);
}
@JsonSerializable()
class Item {
//@JsonKey 显式关联JSON字段名与Model属性的对应关系
@JsonKey(name:'bg_pic')
String bgPic;
String color;
int count;
int type;
@JsonKey(name:'content')
List content;
Item(this.bgPic,this.color,this.count,this.type,this.content);
factory Item.fromJson(Map json)=>_$ItemFromJson(json);
Map toJson()=>_$ItemToJson(this);
}
@JsonSerializable()
class Content {
@JsonKey(name:'song_id')
String songId;
@JsonKey(name:'rank_change')
String rankChange;
String author;
String title;
@JsonKey(name:'pic_big')
String picBig;
Content(this.songId,this.rankChange,this.author,this.title,this.picBig);
factory Content.fromJson(Map json)=>_$ContentFromJson(json);
Map toJson()=>_$ContentToJson(this);
}
问题原因
安卓上从9.0(API level28)开始,明文通信支持默认是被禁用的,官方说法是不安全。因为我们播放的视频源是http协议,所以无法播放。
解决方法
修改AndroidManifest.xml
...
// 在application上 加 android:usesCleartextTraffic="true"
// 加一个权限
// 报错信息
════════ Exception caught by gesture ═════════
The following assertion was thrown while handling a gesture:
invalid text selection: TextSelection(baseOffset: 4, extentOffset: 4, affinity: TextAffinity.upstream, isDirectional: false)
When the exception was thrown, this was the stack
#0 TextEditingController.selection=
package:flutter/…/widgets/editable_text.dart:193
#1 EditableTextState._handleSelectionChanged
package:flutter/…/widgets/editable_text.dart:1507
#2 RenderEditable._handleSelectionChange
package:flutter/…/rendering/editable.dart:417
#3 RenderEditable.selectPositionAt
package:flutter/…/rendering/editable.dart:1568
#4 RenderEditable.selectPosition
package:flutter/…/rendering/editable.dart:1539
...
Handler: "onTapUp"
Recognizer: _TransparentTapGestureRecognizer#49c3a
debugOwner: _TextSelectionGestureDetectorState#0a503
state: ready
won arena
finalPosition: Offset(313.6, 322.3)
finalLocalPosition: Offset(293.6, 24.3)
button: 1
sent tap down
════════════════════════════════════════════════════════════════════════════════
关于此情况并大概就是在没有正常的取消输入框焦点的时候,就先清空输入框组件,整体渲染顺序是不正确的。
错误的做法:
我是直接调用controller取消输入框内容的方法,但是光标会聚集在此输入框,所以处理渲染生命周期是不可控制
TextEditingController _passwordController = new TextEditingController();
_passwordController.clear();
既然知道报错的大概方向,那么我们就控制build的生命周期插入指定时机才去运行方法即可
解决方法:
// 保证在组件build的第一帧时才去触发取消清空内容
WidgetsBinding.instance.addPostFrameCallback((_) => _passwordController.clear());
在runApp()之前
// 强制横屏
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight
]);
// 强制竖屏
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]);
在android上使用插件flutter_filereader: ^2.1.0
由于flutter_filereader这个插件基于腾讯的x5浏览器内核,所以ios是无法使用。
ios上需要使用原生插件WKWebview就行了。
bool isNumber(value) {
/// 不允许带+或者-的数字
RegExp number = new RegExp(r"^\d+(\.\d+)?$|^$|^(\d+|\-){7,}$");
/// 允许带+或者-的数字
// RegExp number = new RegExp(r"^[+-]?\d+(\.\d+)?$|^$|^(\d+|\-){7,}$");
return number.hasMatch(value);
}