Flutter核心技术与实战
陈航
美团点评高级技术专家
立即订阅
6150 人已学习
课程目录
已完结 47 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (3讲)
开篇词 | 为什么每一位大前端从业者都应该学习Flutter?
免费
01 | 预习篇 · 从0开始搭建Flutter工程环境
02 | 预习篇 · Dart语言概览
Flutter开发起步 (3讲)
03 | 深入理解跨平台方案的历史发展逻辑
04 | Flutter区别于其他方案的关键技术是什么?
05 | 从标准模板入手,体会Flutter代码是如何运行在原生系统上的
Dart语言基础 (3讲)
06 | 基础语法与类型变量:Dart是如何表示信息的?
07 | 函数、类与运算符:Dart是如何处理信息的?
08 | 综合案例:掌握Dart核心特性
Flutter基础 (13讲)
09 | Widget,构建Flutter界面的基石
10 | Widget中的State到底是什么?
11 | 提到生命周期,我们是在说什么?
12 | 经典控件(一):文本、图片和按钮在Flutter中怎么用?
13 | 经典控件(二):UITableView/ListView在Flutter中是什么?
14 | 经典布局:如何定义子控件在父容器中排版的位置?
15 | 组合与自绘,我该选用何种方式自定义Widget?
16 | 从夜间模式说起,如何定制不同风格的App主题?
17 | 依赖管理(一):图片、配置和字体在Flutter中怎么用?
18 | 依赖管理(二):第三方组件库在Flutter中要如何管理?
19 | 用户交互事件该如何响应?
20 | 关于跨组件传递数据,你只需要记住这三招
21 | 路由与导航,Flutter是这样实现页面切换的
Flutter进阶 (17讲)
22 | 如何构造炫酷的动画效果?
23 | 单线程模型怎么保证UI运行流畅?
24 | HTTP网络编程与JSON解析
25 | 本地存储与数据库的使用和优化
26 | 如何在Dart层兼容Android/iOS平台特定实现?(一)
27 | 如何在Dart层兼容Android/iOS平台特定实现?(二)
28 | 如何在原生应用中混编Flutter工程?
29 | 混合开发,该用何种方案管理导航栈?
30 | 为什么需要做状态管理,怎么做?
31 | 如何实现原生推送能力?
32 | 适配国际化,除了多语言我们还需要注意什么?
33 | 如何适配不同分辨率的手机屏幕?
34 | 如何理解Flutter的编译模式?
35 | Hot Reload是怎么做到的?
36 | 如何通过工具链优化开发调试效率?
37 | 如何检测并优化Flutter App的整体性能表现?
38 | 如何通过自动化测试提高交付质量?
Flutter综合应用 (6讲)
39 | 线上出现问题,该如何做好异常捕获与信息采集?
40 | 衡量Flutter App线上质量,我们需要关注这三个指标
41 | 组件化和平台化,该如何组织合理稳定的Flutter工程结构?
42 | 如何构建高效的Flutter App打包发布环境?
43 | 如何构建自己的Flutter混合开发框架(一)?
44 | 如何构建自己的Flutter混合开发框架(二)?
结束语 (1讲)
结束语 | 勿畏难,勿轻略
特别放送 (1讲)
特别放送 | 温故而知新,与你说说专栏的那些思考题
Flutter核心技术与实战
登录|注册

16 | 从夜间模式说起,如何定制不同风格的App主题?

陈航 2019-08-03
你好,我是陈航。今天,我和你分享的主题是,从夜间模式说起,如何定制不同风格的 App 主题。
在上一篇文章中,我与你介绍了组装与自绘这两种自定义 Widget 的方式。对于组装,我们按照从上到下、从左到右的布局顺序去分解目标视图,将基本的 Widget 封装到 Column、Row 中,从而合成更高级别的 Widget;而对于自绘,我们则通过承载绘制逻辑的载体 CustomPainter,在其 paint 方法中使用画笔 Paint 与画布 Canvas,绘制不同风格、不同类型的图形,从而实现基于自绘的自定义组件。
对于一个产品来说,在业务早期其实更多的是处理基本功能有和无的问题:工程师来负责实现功能,PM 负责功能好用不好用。在产品的基本功能已经完善,做到了六七十分的时候,再往上的如何做增长就需要运营来介入了。
在这其中,如何通过用户分层去实现 App 的个性化是常见的增长运营手段,而主题样式更换则是实现个性化中的一项重要技术手段。
比如,微博、UC 浏览器和电子书客户端都提供了对夜间模式的支持,而淘宝、京东这样的电商类应用,还会在特定的电商活动日自动更新主题样式,就连现在的手机操作系统也提供了系统级切换展示样式的能力。
那么,这些在应用内切换样式的功能是如何实现的呢?在 Flutter 中,在普通的应用上增加切换主题的功能又要做哪些事情呢?这些问题,我都会在今天的这篇文章中与你详细分享。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Flutter核心技术与实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(11)

  • dao
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';

    void main() => runApp(MyThemePage());

    class MyThemePage extends StatelessWidget {
      // iOS 浅色主题
      final ThemeData kIOSTheme = ThemeData(
          brightness: Brightness.light,
          accentColor: Colors.white,
          primaryColor: Colors.blue,
          iconTheme: IconThemeData(color: Colors.grey),
          textTheme: TextTheme(body1: TextStyle(color: Colors.black)));

      // Android 深色主题
      final ThemeData kAndroidTheme = ThemeData(
          brightness: Brightness.dark, // 深色主题
          accentColor: Colors.black, //(按钮)Widget 前景色为黑色
          primaryColor: Colors.cyan, // 主题色为青色
          iconTheme: IconThemeData(color: Colors.blue), //icon 主题色为蓝色
          textTheme: TextTheme(body1: TextStyle(color: Colors.red)) // 文本主题色为红色
          );

      Widget build(BuildContext context) {
        var theme = MyTheme(
          title: 'Flutter Demo Home Page',
          themes: [kIOSTheme, kAndroidTheme],
        );
        return MaterialApp(
          title: 'My Theme',
          theme: kAndroidTheme,
          home: theme,
        );
      }
    }

    class MyTheme extends StatefulWidget {
      MyTheme({Key key, this.title, this.themes}) : super(key: key);

      final String title;
      final List<ThemeData> themes;

      _MyThemeState createState() => _MyThemeState();
    }

    class _MyThemeState extends State<MyTheme> {
      bool isLight;

      @override
      void initState() {
        isLight = true;
        super.initState();
      }

      @override
      Widget build(BuildContext context) {
        return Theme(
            child: Scaffold(
              appBar: AppBar(
                title: Text('Theme switch'),
              ),
              floatingActionButton: FloatingActionButton(
                child: Text(isLight ? 'Night' : 'Light'),
                onPressed: () {
                  setState(() {
                    isLight = !isLight;
                  });
                },
              ),
            ),
            data: isLight ? widget.themes[0] : widget.themes[1]);
      }
    }

    作者回复: 赞

    2019-08-10
    1
    3
  • 菜头
    Theme.of(context) 方法将向上查找 Widget 树,并返回 Widget 树中最近的主题 Theme。如果 Widget
    的父 Widget 们有一个单独的主题定义,则使用该 Theme
    如果不是,就使用 App 全局 Theme。

    这个表示没太懂。
    最近?是表示其第一个 superWidget 吗?
    父 Widget 们?一个 widget 有多个父 widget?


    作者回复: 父Widget们=祖先

    2019-11-15
  • zzz
    请问下,目前主流的App内UI的样式应该不会局限于ThemeData中的定义的情况。比如有一个自定义的Button,是在代码中设置的特殊Color,不是Themedata里的,这种情况下的button(或类似实现的全部widget),对于日夜间切换这种动态处理的时候,有统一的换颜色的方法么?还是需要在每个widget中都要实现对应的颜色处理?同样的对于TextTheme,ThemeData只提供了textTheme,primaryTextTheme,accentTextTheme三种,如果App内有更多的通用TextTheme,如何动态的统一切换呢?

    作者回复: 你可以自己抽象出一套属性配置,控制的粒度更细一些,通过开关统一切换,本质上和系统主题类似

    2019-10-23
  • 🌝
    如果全局更改主题的话,那岂不是要把MaterialApp这个Widget设置成有状态的widget?这样子是不是更耗性能

    作者回复: 是啊,换主题本身就相当于重建整个App的UI了,自然需要重走一遍根视图的生命周期

    2019-09-20
  • 和小胖
    老师,这个全局主题的设置只是针对于布局中的对应 widget 没有设置样式才会生效吧?例如我在 ThemeData 里面设置了文字颜色为黑色?但是我在子 widget 里面设置了一个文字会红色,那么此时黑色是不生效的吧?

    作者回复: 对,会覆盖

    2019-09-04
  • 灰灰
    class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
      TabController _controller;
      bool isNight = false;
      @override
      void initState() {
        super.initState();
        _controller = TabController(length: 2, vsync: this);
      }

      @override
      Widget build(BuildContext context) {
        return
          Theme(
            data: ThemeData(
              brightness: isNight ? Brightness.dark : Brightness.light,
            ),
            child: Stack(
              children: <Widget>[
                Scaffold(
                  ...
                ),
                Positioned(
                  bottom: 20,
                  right: 20,
                  child: FloatingActionButton(
                    onPressed: () {setState(() {
                      isNight = !isNight;
                    });},
                    child: Text(isNight ? '日间' : '夜间'),
                  ),
                )
              ],
            ),
          );
      }

      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    }

    作者回复: 赞

    2019-08-06
  • 文心雕龙
    第三方插件 https://pub.dev/packages/dynamic_theme#-readme-tab-

    作者回复: 赞

    2019-08-06
  • 宋世通
    老师,在flutter1.8.2,1.8.3版本中增加了ThemeMode,是不是用这个来控制主题明暗会更好一点?

    作者回复: 可以的。ThemeMode是在主题之上,是用来设置是否跟随系统设置的属性,你可以通过它来强制设置App主题为明或暗,也可以跟随系统,这样就需要把两套主题都实现了

    2019-08-06
    1
  • Ω
    defaultTargetPlatform这个变量哪里来的,文章中没有说明清楚

    作者回复: import 'package:flutter/foundation.dart';

    2019-08-05
  • 小米
    思考题:
    1、增加一个布尔变量
          bool _isLight = false
    2、在ThemeData中,根据_isLight来显示是否为高亮或者暗色。
          brightness: _isLight ? Brightness.light : Brightness.dark
    3、增加一个切换按钮,点击改变_isLight值。
          FlatButton(onPressed: (){setState(() { _isLight = !_isLight; });},child: Text(_isLight?"白天":"夜间"))

    作者回复: 赞

    2019-08-05
  • 许童童
    老师你好,这个Theme应该是要定义为状态,在setState里面修改这个变量,但是代码不知道怎么写,老师能否给一下代码。

    作者回复: 可以参考小米同学的实现

    2019-08-03
    1
收起评论
11
返回
顶部