🚀码云客户端Gitee Flutter Client
🚀Flutter中文网 https://book.flutterchina.club/
🚀Flutter中文网 随书源码 https://github.com/wendux/flutter_in_action_source_code
🚀gsy_github_app_flutter https://github.com/CarGuo/gsy_github_app_flutter
🚀FlutterGithub https://github.com/MrHGJ/FlutterGithub
├─common 常量,常用方法,网络及缓存,全局配置,oauth认证
├─event EventBus组件
├─l10n 国际化
├─models Json文件对应的实体类
├─route 所有路由页面
├─states 保存APP中需要跨组件共享的状态类
├─ui 自定义组件
└─util 工具类
index.dart
main.dart
首页 | 动态 | 我的 |
---|---|---|
搜索 | 消息 |
---|---|
dart -> arb
flutter pub pub run intl_translation:extract_to_arb --output-dir=target/directory
my_program.dart mor;e_of_my_program.dart
my:
flutter pub pub run intl_translation:extract_to_arb --output-dir=l10n-arb \ lib/l10n/localization_intl.dart
arb -> dart
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/l10n/localization_intl.dart l10n-arb/intl_*.arb
根目录下创建一个intl.sh的脚本,内容为:
flutter pub pub run intl_translation:extract_to_arb --output-dir=l10n-arb lib/l10n/localization_intl.dart
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/l10n/localization_intl.dart l10n-arb/intl_*.arb
Linux: 然后授予执行权限: chmod +x intl.sh
, 执行intl.sh: ./intl.sh
Windows: Android Studio 中直接运行 intl.sh
🍎仅需一条指令 👉 flutter packages pub run json_model
🍎网页版 👉 https://caijinglong.github.io/json2dart/index_ch.html
json
结构字段问题:
//repoV3.dart
@JsonKey(name: "fork?")
bool fork;
//payload.dart / payload.g.dart
@JsonKey(name: "_links")
Links links;
// number 字段 为动态类型
String number;
..number = (json['number'] as Object)?.toString()
//pullRequest.dart
@JsonKey(name: "_links")
Links links;
- 接口版本
V3
和V5
:api v5
头像avatar_url
;v3
头像portrait_url
User
-> models/user.dart
String avatar_url; //
@JsonKey(name: "avatar_url")
String portrait_url;
https://medium.com/flutter/enums-with-extensions-dart-460c42ea51f7
///方式一
const tab_title_home = <String>["推荐项目", "热门项目", "最近更新"];
///方式二(推荐)
enum TabTitleHome {
Recommend,
Popular,
Recent,
}
extension TabTitleHomeExtension on TabTitleHome {
//eg: Recommend
String get name => describeEnum(this);
List<String> get _titles => <String>["推荐项目", "热门项目", "最近更新"];
String get _titles => titles.elementAt(this.index);
}
应用:
List<String> _tabs = tab_title_home.toList();
List<String> _tabs = TabTitleHome.Recommend.titles;//_titles -> titles
List<String> _tabs = TabTitleHome.values.map((e) => e.title).toList();//推荐
///========================== flukit ==============================
///
/// after_layout.dart
/// animated_rotation_box.dart
/// gradient_button.dart
/// gradient_circular_progress_indicator.dart
/// infinite_listview.dart
/// pull_refresh.dart
/// quick_scrollbar.dart
/// scale_view.dart
/// swiper.dart
/// turn_box.dart
/// utils.dart
///
///========================== GradientButton ==============================
///
///flukit-1.0.2\lib\src\gradient_button.dart 👉 颜色渐变的按钮
///
///GradientButton是由DecoratedBox、Padding、Center、InkWell等组件组合而成。
/// 然而作为一个按钮它还并不完整,比如没有禁用状态,可以根据实际需要来完善。
///
///Usage:
/// GradientButton(
/// height: 50.0,
/// colors: [Colors.lightBlue[300], Colors.blueAccent],
/// child: Text("Submit"),
/// onPressed: onTap,
/// ),
///========================== TurnBox ==============================
///
///flukit-1.0.2\lib\src\turn_box.dart 👉 旋转控件
///
///TurnBox,它不仅可以以任意角度来旋转其子节点,而且可以在角度发生变化时执行一个动画以过渡到新状态,同时可以手动指定动画速度。
/// 1.通过组合RotationTransition和child来实现的旋转效果。
/// 2.在didUpdateWidget中,我们判断要旋转的角度是否发生了变化,如果变了,则执行一个过渡动画。
///
///RotatedBox,它可以旋转子组件,但是它有两个缺点:
///一是只能将其子节点以90度的倍数旋转;二是当旋转的角度发生变化时,旋转角度更新过程没有动画。
///
///Usage:
/// TurnBox(
/// turns: _turns, // `1/8` 旋转的“圈”数,一圈为360度,如0.25圈即90度
/// duration: 500, //过渡动画执行的总时长
/// child: Icon(Icons.refresh,size: 50),
/// ),
///========================== GradientCircularProgressIndicator ==============================
///
///flukit-1.0.2\lib\src\gradient_circular_progress_indicator.dart 👉 圆形背景渐变进度条
///
/*
1.支持多种背景渐变色。2.任意弧度;进度条可以不是整圆。3.可以自定义粗细、两端是否圆角等样式。
eg:
1.
GradientCircularProgressIndicator(
// No gradient
colors: [Colors.blue, Colors.blue],
radius: 50.0,
strokeWidth: 3.0,
value: _animationController.value,
),
2.
SizedBox(
height: 108.0,
width: 200.0,
child: Stack(
alignment: AlignmentDirectional.center,
children: [
TurnBox(
turns: -0.25,
child: GradientCircularProgressIndicator(
colors: [Colors.red,Colors.blue,Colors.red],
radius: 50.0,
strokeWidth: 5.0,
strokeCapRound: true,
totalAngle: math.pi,
value: CurvedAnimation(parent: _animationController, curve: Curves.linear).value),
),
Center(
child: Text(
///toInt 会出现达不到 100% 的问题
'${(_animationController.value * 100).ceil()}%',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
),
],
),
),
*/
- Fixed:
//首页底部导航测试时候,初始化了两个 RepoListRoute ,导致 tag 被注册了两次... ̄□ ̄||
_pageList = List();
_pageList.add(RepoListRoute());
_pageList.add(LanguageRoute());
_pageList.add(RepoListRoute());//改用其他页面路由即可
cached_network_image: ^2.3.2+1
-> CachedNetworkImage
- Fixed:
Widget getAvatarCircle(String url, {double radius = 30.0, BoxFit fit = BoxFit.cover,}) {
var placeholder = Image.asset(image_avatar_default,width: radius,height: radius);//默认头像
if (checkUrl(url)) {
return ClipOval(
child: CachedNetworkImage(
imageUrl: url,width: radius,height:radius,fit:fit,
placeholder: (context, url) => placeholder,
errorWidget: (context, url, error) => placeholder,
),
);
} else {
return ClipOval(child: placeholder);
}
}