前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【喵咪专场】还不来领取你的小可爱吗?😍

【喵咪专场】还不来领取你的小可爱吗?😍

作者头像
玖柒的小窝
修改2021-11-04 09:26:44
5870
修改2021-11-04 09:26:44
举报
文章被收录于专栏:各类技术文章~

话不多说,先上效果图:是不是很炫酷~

tt0.top-591909.gif
tt0.top-591909.gif

源码地址:github.com/taxze6/flut…(希望给点点star⭐)

本文分析重点:

  • 基于GetX封装,MVP架构
  • 检测是否是第一次登录,是否展示引导页
  • 引导页的登录动画处理(封装处理)
  • 首页底部特效导航栏(暂无分析,原因有兴趣大家可以看文章的最后)
  • 其他的动画效果(暂无分析,原因有兴趣大家可以看文章的最后)

使用插件:

代码语言:javascript
复制
#状态管理 + 路由管理
get: 4.2.0
​
# 本地存储 + 图片缓存
shared_preferences: ^2.0.6
cached_network_image: ^3.0.0
复制代码

1.实现基于Getx封装,MVP架构

mvp的全称为Model-View-Presenter,Model提供数据,View负责显示,Controller/Presenter负责逻辑的处理。

举个例子:

屏幕截图 2021-11-03 125837.jpg
屏幕截图 2021-11-03 125837.jpg

使用Getx进行封装:

数据存放:

代码语言:javascript
复制
class SplashModel {
  late String Background;
  late String SplashText;
  late String SplashButtonText;
  BuildContext? context = Get.context;
​
    ///初始化数据
  SplashModel() {
    Background = "images/splash/Splash.png";
    SplashText = "Rehoming and adoption. You find each other.";
    SplashButtonText = "Let's Start";
  }
}
复制代码

在controller中定义SplashModel,使用数据:

代码语言:javascript
复制
class SplashController extends GetxController {
  final SplashModel splashModelState = SplashModel();
 }
复制代码

在view中使用控制器:

代码语言:javascript
复制
final controller = Get.put(SplashController());
final state = Get.find<SplashController>().splashModelState;
​
//使用:
Text(state.SplashText)
复制代码

2.检测是否是第一次登录,是否展示引导页

这里就需要使用全局信息配置了,然后使用shared_preferences本地持久化

简单的定义用户信息:

代码语言:javascript
复制
UserLoginResponseModel userLoginResponseModelFromJson(String str) => UserLoginResponseModel.fromJson(json.decode(str));
​
String userLoginResponseModelToJson(UserLoginResponseModel data) => json.encode(data.toJson());
​
class UserLoginResponseModel {
  UserLoginResponseModel({
    this.token,
    this.name,
    this.id,
  });
​
  String? token;
  String? name;
  int? id;
​
  factory UserLoginResponseModel.fromJson(Map<String, dynamic> json) => UserLoginResponseModel(
    token: json["token"],
    name: json["name"],
    id: json["id"],
  );
​
  Map<String, dynamic> toJson() => {
    "token": token,
    "name": name,
    "id": id,
  };
}
复制代码

全局配置怎么去做呢?

定义一个Global文件

代码语言:javascript
复制
class Global{}
复制代码

在这个文件中我们可以进行app的全局配置

例如:

代码语言:javascript
复制
/// 用户配置
static UserLoginResponseModel? profile = UserLoginResponseModel(token: null);
​
///是否是第一次打开
static bool isFirstOpen = false;
​
///是否登录
static bool isOfflineLogin = false;
复制代码

重点来啦!定义一个init方法用于初始化:

代码语言:javascript
复制
static Future init() async{
    // 运行初始
    WidgetsFlutterBinding.ensureInitialized();
    //本地存储初始化
    await LoacalStorage.init();
    // 读取离线用户信息
    var _profileJSON = LoacalStorage().getJSON(STORAGE_USER_PROFILE_KEY);
    if (_profileJSON != null) {
      profile = UserLoginResponseModel.fromJson(_profileJSON);
      isOfflineLogin = true;
    }
​
    // android 状态栏为透明的沉浸
    if (Platform.isAndroid) {
      SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
      SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
    }
    isFirstOpen = !LoacalStorage().getBool(STORAGE_DEVICE_ALREADY_OPEN_KEY);
    if (isFirstOpen) {
      LoacalStorage().setBool(STORAGE_DEVICE_ALREADY_OPEN_KEY, true);
    }
}
复制代码

之后我们就可以在main文件中初始化这配置文件

代码语言:javascript
复制
void main() => Global.init().then((value) => runApp(MyApp()));
复制代码

然后我们就可以进行判断啦:

代码语言:javascript
复制
Obx(() => Scaffold(
  body: controller.isloadWelcomePage.isTrue
      ? SplashPage() //引导页
      : Global.isOfflineLogin
      ? HomePage() //首页
      : LoginPage(), //登录页
)
复制代码

3.引导页的登录动画处理(封装处理)

在上方我们已经进行了SplashModel的数据定义

那么让我们来看看动画吧,因为时MVP架构,所以我们关于AnimationController的处理要放到controller中,我们使controller继承于SingleGetTickerProviderMixin。

代码语言:javascript
复制
class SplashController extends GetxController
    with SingleGetTickerProviderMixin {
   AnimationController? animationController;
}
复制代码

然后再初始化动画(记得销毁哦):

代码语言:javascript
复制
@override
void onInit() {
  super.onInit();
  animationController = AnimationController(
      duration: const Duration(milliseconds: 1500), vsync: this);
  animationController!.forward();
}
​
@override
  void onClose() {
    // TODO: implement onClose
    super.onClose();
    animationController!.dispose();
 }
复制代码

按钮动画(view):

代码语言:javascript
复制
Widget Splash_Button(BuildContext context) => ScaleTransition(
//动画处理
      scale: Tween<double>(begin: 0, end: 1).animate(CurvedAnimation(
        parent: controller.animationController!,
        curve: const Interval(0.3, 0.6, curve: Curves.fastOutSlowIn),
      )),
      child: GestureDetector(
        onTap: () {
          controller.getTo();
        },
        child: Container(
         //按钮
        ),
      ),
    );
复制代码

就是这么的简单,如果觉得不够详细可以自己下拉源码查看~

关于引导页的背景,我们这里有个优化的点,提前缓存图片: 在controller中onInit中缓存:

代码语言:javascript
复制
@override
  void onInit() {
    super.onInit();
    _precacheImage(splashModelState.Background, splashModelState.context!);
  }
void _precacheImage(String imageUrl, BuildContext context) {
  precacheImage(AssetImage(imageUrl), context);
}
复制代码

4.最后:

上文说到没有分析的原因是因为本人遇到一件很重要的事,一件在绝望中寻找希望的事,也许没有了周末,没有了假期,不能在编写Flutter系列的文章,不能和小伙伴们谈论技术,但是,人生嘛总要有舍有得~

最后送所有正在努力的大家一句话:你不一定逆风翻盘,但一定要向阳而生。

我是阿T,山水有相逢,我们江湖见。(我们很快再见~)

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.实现基于Getx封装,MVP架构
  • 2.检测是否是第一次登录,是否展示引导页
  • 3.引导页的登录动画处理(封装处理)
  • 4.最后:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档