本项目包含启动页,引导页,主题色,国际化,Bloc,RxDart。拥有较好的项目结构,比较规范的代码。 App拥有精致的UI界面,统一的交互,侧滑退出,列表和Web界面均提供快速滚动至顶部功能。
有关项目最新动态,可以关注App内第一条Hot Item信息。
Support [√] Flutter (Channel stable, v1.17.0).
由于在国内访问Flutter有时可能会受到限制,clone项目后,请勿直接packages get,建议运行如下目录行:
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
flutter packages get
flutter run --release
v0.2.6 (2020年05月08日)
Support [√] Flutter (Channel stable, v1.17.0).
版本升级功能(仅供参考)
- base_library Flutter基础组件库,方便多个项目共用。
- login_demo 关于App启动时,未登录跳登录页,已登录进主页。
- flutter_gallery 也许是Google官方最后一个版本的gallery(旧版)。
- |--lib
- |-- blocs (bloc相关)
- |-- common (常用类,例如常量Constant)
- |-- data (网络数据层)
- |-- db (数据库)
- |-- demos (flutter demos)
- |-- event (事件类)
- |-- models (实体类)
- |-- res (资源文件,string,colors,dimens,styles)
- |-- ui (界面相关page,dialog,widgets)
- |-- utils (工具类)
- |--data
- |-- api (url字段)
- |-- net (单例DioUtil)
- |-- protocol (请求与返回实体类)
- |-- repository (接口请求&解析)
class WanAndroidApi { /// 首页banner http://www.wanandroid.com/banner/json static const String BANNER = "banner"; static const String USER_REGISTER = "user/register"; //注册 static const String USER_LOGIN = "user/login"; //登录 static const String USER_LOGOUT = "user/logout"; //退出 // 拼接url static String getPath({String path: '', int page, String resType: 'json'}) { StringBuffer sb = new StringBuffer(path); if (page != null) { sb.write('/$page'); } if (resType != null && resType.isNotEmpty) { sb.write('/$resType'); } return sb.toString(); } }
// 打开debug模式. DioUtil.openDebug(); // 配置网络参数. Options options = DioUtil.getDefOptions(); options.baseUrl = "http://www.wanandroid.com/"; HttpConfig config = new HttpConfig(options: options); DioUtil().setConfig(config); // 两种单例请求方式. DioUtil().request<List>(Method.get, "banner/json"); DioUtil.getInstance().request(Method.get, "banner/json"); //示例 LoginReq req = new LoginReq('username', 'password'); DioUtil().request(Method.post, "user/login",data: req.toJson()); //示例 FormData formData = new FormData.from({ "username": "username", "password": "password", }); DioUtil().requestR(Method.post, "user/login",data: rformData);
class LoginReq { String username; String password; LoginReq(this.username, this.password); LoginReq.fromJson(Map<String, dynamic> json) : username = json['username'], password = json['password']; Map<String, dynamic> toJson() => { 'username': username, 'password': password, }; @override String toString() { StringBuffer sb = new StringBuffer('{'); sb.write("\"username\":\"$username\""); sb.write(",\"password\":$password"); sb.write('}'); return sb.toString(); } }
class WanRepository { Future<List<BannerModel>> getBanner() async { BaseResp<List> baseResp = await DioUtil().request<List>( Method.get, WanAndroidApi.getPath(path: WanAndroidApi.BANNER)); List<BannerModel> bannerList; if (baseResp.code != Constant.STATUS_SUCCESS) { return new Future.error(baseResp.msg); } if (baseResp.data != null) { bannerList = baseResp.data.map((value) { return BannerModel.fromJson(value); }).toList(); } return bannerList; } }
- |--res
- |-- colors.dart
- |-- dimens.dart
- |-- strings.dart
- |-- styles.dart
class Colours { static const Color app_main = Color(0xFF666666); static const Color text_dark = Color(0xFF333333); static const Color text_normal = Color(0xFF666666); static const Color text_gray = Color(0xFF999999); }
class Dimens { static const double font_sp12 = 12; static const double font_sp14 = 14; static const double font_sp16 = 16; static const double gap_dp5 = 5; static const double gap_dp10 = 10; }
class Ids { static const String titleHome = 'title_home'; } Map<String, Map<String, Map<String, String>>> localizedValues = { 'en': { 'US': { Ids.titleHome: 'Home', } }, 'zh': { 'CN': { Ids.titleHome: '主页', }, 'HK': { Ids.titleHome: '主頁', }, 'TW': { Ids.titleHome: '主頁', } } };
class TextStyles { static TextStyle listTitle = TextStyle( fontSize: Dimens.font_sp16, color: Colours.text_dark, fontWeight: FontWeight.bold, ); static TextStyle listContent = TextStyle( fontSize: Dimens.font_sp14, color: Colours.text_normal, ); static TextStyle listExtra = TextStyle( fontSize: Dimens.font_sp12, color: Colours.text_gray, ); } // 间隔 class Gaps { // 水平间隔 static Widget hGap5 = new SizedBox(width: Dimens.gap_dp5); static Widget hGap10 = new SizedBox(width: Dimens.gap_dp10); // 垂直间隔 static Widget vGap5 = new SizedBox(height: Dimens.gap_dp5); static Widget vGap10 = new SizedBox(height: Dimens.gap_dp10); }
Flutter 国际化相关 fluintl
fluintl是一个为应用提供国际化的库,可快速集成实现应用多语言。该库封装了一个国际化支持类,通过提供统一方法getString(id)获取字符串。
// 在MyApp initState配置多语言资源 setLocalizedValues(localizedValues); //配置多语言资源 // 在MaterialApp指定localizationsDelegates和supportedLocales MaterialApp( home: MyHomePage(), localizationsDelegates: [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, CustomLocalizations.delegate //设置本地化代理 ], supportedLocales: CustomLocalizations.supportedLocales,//设置支持本地化语言集合 ); // 字符串获取 IntlUtil.getString(context, Ids.titleHome); CustomLocalizations.of(context).getString(StringIds.titleHome); // 支持复用。替换字符串格式要求:'%\${index}\$s' ,{index} 第几个参数,从0开始。 Ids.click_times: '%\$0\$s点击了%\$1\$s次', IntlUtil.getString(context, Ids.click_times, params: ['Tom', '$_counter']) // print: Tom点击了0次
Flutter 屏幕适配 ScreenUtil
方案一、不依赖context
// 步骤1 // 如果设计稿尺寸默认配置一致,无需该设置。 配置设计稿尺寸 默认 360.0 / 640.0 / 3.0 setDesignWHD(_designW,_designH,_designD); // 步骤2 // 在MainPageState build 调用MediaQuery.of(context) class MainPageState extends State<MainPage> { @override Widget build(BuildContext context) { // 在 MainPageState build 调用 MediaQuery.of(context) MediaQuery.of(context); return new Scaffold( appBar: new AppBar(), ); } } // 步骤3 ScreenUtil.getInstance().screenWidth ScreenUtil.getInstance().screenHeight //屏幕适配相关 ScreenUtil.getInstance().getWidth(size); //返回根据屏幕宽适配后尺寸(单位 dp or pt) ScreenUtil.getInstance().getHeight(size); //返回根据屏幕高适配后尺寸 (单位 dp or pt) ScreenUtil.getInstance().getWidthPx(sizePx); //sizePx 单位px ScreenUtil.getInstance().getHeightPx(sizePx); //sizePx 单位px ScreenUtil.getInstance().getSp(fontSize); //返回根据屏幕宽适配后字体尺寸 double adapterSize = ScreenUtil.getInstance().getAdapterSize(100);
方案二、依赖context
//如果设计稿尺寸默认配置一致,无需该设置。 配置设计稿尺寸 默认 360.0 / 640.0 / 3.0 setDesignWHD(_designW,_designH,_designD); ScreenUtil.getScreenW(context); //屏幕 宽 ScreenUtil.getScreenH(context); //屏幕 高 //屏幕适配相关 ScreenUtil.getScaleW(context, size); //返回根据屏幕宽适配后尺寸(单位 dp or pt) ScreenUtil.getScaleH(context, size); //返回根据屏幕高适配后尺寸 (单位 dp or pt) ScreenUtil.getScaleSp(context, size) ;//返回根据屏幕宽适配后字体尺寸 double adapterSize = ScreenUtil.getAdapterSizeCtx(context, 100)
Flutter 数据存储 SpUtil
单例"同步" SharedPreferences 工具类。
支持get获取默认参数、支持存储实体对象、支持存储实体对象数组。
// 等待Sp初始化完成。 await SpUtil.getInstance(); SpUtil.getString('key', defValue: ''); SpUtil.getInt('key', defValue: 0); /// save object example. /// 存储实体对象示例。 City city = new City(); city.name = "成都市"; SpUtil.putObject("loc_city", city); City hisCity = SpUtil.getObj("loc_city", (v) => City.fromJson(v)); print("thll Str: " + (hisCity == null ? "null" : hisCity.toString())); /// save object list example. /// 存储实体对象List示例。 List<City> list = new List(); list.add(new City(name: "成都市")); list.add(new City(name: "北京市")); SpUtil.putObjectList("loc_city_list", list); List<City> _cityList = SpUtil.getObjList("loc_city_list", (v) => City.fromJson(v)); print("thll List: " + (_cityList == null ? "null" : _cityList.toString()));
- |--demos
- |-- city_select_page.dart 城市列表(索引&悬停)示例
- |-- date_page.dart 日期格式化示例
- |-- image_size_page.dart 获取图片尺寸示例
- |-- money_page.dart 金额(元转分/分转元)示例
- |-- pinyin_page.dart 汉字转拼音示例
- |-- regex_page.dart 正则工具类示例
- |-- round_portrait_page.dart 圆形圆角头像示例
- |-- timeline_page.dart 时间轴示例
- |-- timer_page.dart 倒计时/定时任务示例
- |-- widget_page.dart 获取Widget尺寸/屏幕坐标示例
截图无法查看?
| 主界面 | 启动页 | 侧滑Back |
|---|---|---|
| 快速滚动到顶部 | 分类页面 | 国际化 |
| 主题色 | 闪屏广告页 | 引导页 |
1 感谢鸿洋大佬提供的开源api
2 界面参考gitme
3 Github Trending Api
4 Streams-Block-Reactive-Programming-in-Flutter
Q1:Flutter国际化系统切换iOS不生效问题?
A1:在Xcode项目Localizations下添加支持语言即可,原文。
Apk:flutter_wanandroid.apk
iOS:请自行clone项目代码运行。
GitHub : Sky24n
简书 : Sky24n
掘金 : Sky24n
Email : 863764940@qq.com
⭐⭐⭐ 如果您觉得本项目不错的话,来个star支持下作者吧! ⭐⭐⭐
关于项目任何问题请提交issues,私发QQ邮件将不再回复〜
⭐⭐⭐ 最新开源 ⭐⭐⭐
nine_grid_view
Flutter仿微信/微博九宫格、拖拽排序,钉钉群组,微信群组头像。
⭐⭐⭐ 个人作品 ⭐⭐⭐
Fitness
Flutter开发的微博客户端,同时支持Android和iOS。与官方微博x9.99%相似度体验,离线模式,多语言支持,主题随心换,超乎想象的流畅度,各种惊喜的细节等待你一一发现。
Flutter仿微博客户端 Flutter Weibo
Flutter仿微信/微博九宫格 NineGridView
Flutter版玩安卓 flutter_wanandroid
Flutter仿滴滴出行 GreenTravel
Flutter常用工具类库 flustars
Dart常用工具类库 common_utils
Flutter城市列表 azlistview
Flutter汉字转拼音库 lpinyin
Flutter国际化库 fluintl