flutter主題設置

App主題色控制

  • Theme有兩種:全局Theme和局部Theme。全局Theme是由應用程序根MaterialApp建立的Theme 。web

  • Theme做用:能夠設置Widget的主題,提升開發效率和速度,保持App主題統一性或某種一致性。canvas

Theme

Theme組件能夠爲material APP定義主題數據(ThemeData)。Material組件庫裏不少組件都使用了主題數據, 如導航欄顏色、標題字體、Icon樣式等。Theme內會使用InheritedWidget來爲其子樹共享樣式數據。數組

設置主題栗子

全局:
/// 全局主題在MaterialApp的theme屬性
/// 全局生效
new MaterialApp(
  title: 'demo',
  theme: new ThemeData( // 這裏就是參數
    brightness: Brightness.dark,
    primaryColor: Colors.lightBlue[800],
    accentColor: Colors.cyan[600],
  ),
);
局部:
/// 假如咱們要給FloatingActionButton設置主題樣式
/// 直接寫個Theme包裹FloatingActionButton組件
/// 而後設置data,接收類型依然是ThemeData,裏面填寫咱們的參數
/// (若是沒有設置局部主題則默認使用全局主題)
new Theme(
  data: new ThemeData(
    accentColor: Colors.yellow,
  ),
  child: new FloatingActionButton(
    onPressed: () {},
    child: new Icon(Icons.add),
  ),
);
擴展父主題:
/// 擴展父主題時無需覆蓋全部的主題屬性,能夠經過使用copyWith方法來實現
new Theme(
  data: Theme.of(context).copyWith(accentColor: Colors.yellow),
  child: new FloatingActionButton(
    onPressed: null,
    child: new Icon(Icons.add),
  ),
);

Theme.of(context)將查找Widget樹並返回樹中最近的Theme。若是Widget之上有一個單獨的Theme定義, 則返回該值。若是不是,則返回App主題。微信

判斷平臺顯示指定主題:
/// defaultTargetPlatform在foundation包裏。
/// 
/// 咱們也可使用io包裏的Platform來進行判斷。

/// 那麼判斷就是
/// theme: Platform.isIOS ? iOSTheme : AndroidTheme,
new MaterialApp(
  theme: defaultTargetPlatform == TargetPlatform.iOS
      ? iOSTheme
      : AndroidTheme,
  title: 'Flutter Theme',
  home: new MyHomePage(),
);
Tips:

Flutter的Color中大多數顏色從100到900,增量爲100,加上顏色50,數字越小顏色越淺, 數字越大顏色越深。強調色調只有100、200、400和700。markdown

栗子:

推薦站點(Material design):

https://material.io/resources/color,app

爲你的UI建立共享調色板,並衡量任何顏色組合的可觀性【很是實用的工具】。less

ThemeData(Color類型屬性):

  • accentColor - 前景色(文本、按鈕等)
  • backgroundColor - 與 primaryColor對比的顏色(例如 用做進度條的剩餘部分)。
  • bottomAppBarColor - BottomAppBar的默認顏色。
  • buttonColor - MaterialRaisedButtons使用的默認填充色。
  • canvasColor - MaterialType.canvas Material的默認顏色。
  • cardColor - Material被用做 Card時的顏色。
  • dialogBackgroundColor - Dialog元素的背景色。
  • disabledColor - 用於 Widget無效的顏色,不管任何狀態。例如禁用複選框。
  • dividerColor - Dividers和PopupMenuDividers的顏色,也用於 ListTiles中間,和DataTables的每行中間.
  • errorColor - 用於輸入驗證錯誤的顏色,例如在 TextField中。
  • highlightColor - 用於相似墨水噴濺動畫或指示菜單被選中的高亮顏色。
  • hintColor - 用於提示文本或佔位符文本的顏色,例如在 TextField中。
  • indicatorColor - TabBar中選項選中的指示器顏色。
  • primaryColor - App主要部分的背景色( ToolBar, TabBar等)。
  • primaryColorDark - primaryColor的較暗版本。
  • primaryColorLight - primaryColor的較亮版本。
  • scaffoldBackgroundColor - 做爲 Scaffold基礎的 Material默認顏色,典型 Material應用或應用內頁面的背景顏色。
  • secondaryHeaderColor - 有選定行時 PaginatedDataTable標題的顏色。
  • selectedRowColor - 選中行時的高亮顏色。
  • splashColor - 墨水噴濺的顏色。
  • textSelectionColor - 文本字段中選中文本的顏色,例如 TextField
  • textSelectionHandleColor - 用於調整當前文本的哪一個部分的句柄顏色。
  • toggleableActiveColor - 用於突出顯示切換 Widget(如 SwitchRadioCheckbox)的活動狀態的顏色。
  • unselectedWidgetColor - 用於 Widget處於非活動(但已啓用)狀態的顏色。例如,未選中的複選框。一般與 accentColor造成對比。
  • focusColor - 焦點獲取時的顏色,例如,一些按鈕焦點、輸入框焦點。
  • hoverColor - 點擊以後徘徊中的顏色,例如,按鈕長按,按住以後的顏色。
  • cursorColor - 輸入框光標顏色。

ThemeData(Theme相關類型屬性):

  • accentIconTheme - IconThemeData類型,與突出顏色對照的圖片主題。
  • accentTextTheme - TextTheme類型,與突出顏色對照的文本主題。
  • chipTheme - ChipThemeData類型,用於渲染 Chip的顏色和樣式。
  • buttonTheme - ButtonThemeData類型,定義了按鈕等控件的默認配置,像 RaisedButtonFlatButton
  • primaryIconTheme - IconThemeData類型,一個與主色對比的圖片主題。
  • primaryTextTheme - TextThemeData類型,一個與主色對比的文本主題。
  • iconTheme - IconThemeData類型,與卡片和畫布顏色造成對比的圖標主題。
  • inputDecorationTheme - InputDecorationTheme類型, InputDecoratorTextFieldTextFormField的默認 InputDecoration值基於此主題。
  • sliderTheme - SliderThemeData類型,用於渲染 Slider的顏色和形狀。
  • textTheme - TextTheme類型,與卡片和畫布對比的文本顏色。
  • toggleButtonsTheme - ToggleButtonsThemeData類型,Flutter 1.9 全新組件 ToggleButtons 的主題。
  • tabBarTheme - TabBarTheme類型, TabBar的主題樣式。
  • tooltipTheme - TooltipThemeData類型, tooltip提示的主題樣式。
  • cardTheme - CardTheme類型,卡片的主題樣式。
  • pageTransitionsTheme - PageTransitionsTheme類型,頁面轉場主題樣式。
  • appBarTheme - AppBarTheme類型, AppBar主題樣式。
  • bottomAppBarTheme - BottomAppBarTheme類型,底部導航主題樣式。
  • dialogTheme - DialogTheme類型,對話框主題樣式。
  • floatingActionButtonTheme - FloatingActionButtonThemeData類型, FloatingActionButton的主題樣式,也就是 Scaffold屬性的那個。
  • cupertinoOverrideTheme - CupertinoThemeData類型, cupertino覆蓋的主題樣式。
  • snackBarTheme - SnackBarThemeData類型,彈出的 snackBar的主題樣式。
  • bottomSheetTheme - BottomSheetThemeData類型,底部滑出對話框的主題樣式。
  • popupMenuTheme - PopupMenuThemeData類型,彈出菜單對話框的主題樣式。
  • bannerTheme - MaterialBannerThemeData類型, Material材質的 Banner主題樣式。
  • dividerTheme - DividerThemeData類型, Divider組件的主題樣式,也就是那個橫向線條組件。

ThemeData(其餘類型屬性):

  • accentColorBrightness - Brightness類型, accentColor的亮度。用於肯定放置在突出顏色頂部的文本和圖標的顏色(例如 FloatingButton上的圖標)。
  • brightness - Brightness類型,應用程序總體主題的亮度。由按鈕等 Widget使用,以肯定在不使用主色或強調色時要選擇的顏色。
  • platform - TargetPlatform類型, Widget須要適配的目標類型。
  • splashFactory - InteractiveInkFeatureFactory類型,定義 InkWallInkResponse生成的墨水噴濺的外觀。
  • primaryColorBrightness - Brightness類型, primaryColor的亮度。
  • fontFamily - String類型,字體樣式。
  • applyElevationOverlayColor bool類型,是否應用 elevation覆蓋顏色。
  • materialTapTargetSize - MaterialTapTargetSize類型, Chip等組件的尺寸主題設置,如:設置爲 MaterialTapTargetSize.shrinkWrap時, clip距頂部距離爲0;設置爲 MaterialTapTargetSize.padded時距頂部有一個距離
  • colorScheme - ColorScheme類型,scheme組顏色,一組13種顏色,可用於配置大多數組件的顏色屬性。
  • typography - Typography類型,用於配置 TextThemeprimaryTextThemeaccentTextTheme的顏色和幾何文本主題值。

適配夜間模式

實現效果:

分析:

此次是使用局部的實現,哪一個頁面須要同步就加個Theme就好了,全局也是相似的實現方式,主體代碼不到100行。編輯器

代碼:

首先寫個配置類,主要配置主題的是否爲黑夜模式和主題樣式:ide

class Config {
  static bool dark = true// 是否爲黑夜模式
  static ThemeData themeData = new ThemeData.dark(); // 主題爲暗色
}

而後咱們正常的執行代碼:工具

import 'package:flutter/material.dart';
import 'global_config.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(title: "Flutter高級進階", home: new MyScaffold());
  }
}

class MyScaffold extends StatefulWidget {
  @override
  _MyScaffoldState createState() => _MyScaffoldState();
}

class _MyScaffoldState extends State<MyScaffold{
  /*
  * 主題改變
  * */

  changeTheme() {
    if (Config.dark) {
      Config.themeData = new ThemeData(
        primaryColor: Colors.white,
        scaffoldBackgroundColor: new Color(0xFFEBEBEB),
      );
      Config.dark = false;
    } else {
      Config.themeData = new ThemeData.dark();
      Config.dark = true;
    }
    setState(() {});
  }

  Widget body(context) {
    return new ListView(
      children: <Widget>[
        new Container(
          width: MediaQuery.of(context).size.width / 4// 整寬除4
          child: new GestureDetector(
            onTap: () => changeTheme(), // 觸發更換主題的事件
            child: new Column(
              children: <Widget>[
                new FlutterLogo(
                  size: 150.0,
                  style: FlutterLogoStyle.horizontal,
                  duration: Duration(milliseconds: 100),
                  textColor: Theme.of(context).colorScheme.background, // 從上下文拿到背景
                ),
                new Text( // 若是爲黑夜模式則按鈕文字爲白天模式,不然文字顯示爲黑夜模式
                  '點擊Logo更換${Config.dark ? "白天模式" : "黑夜模式"}',
                  style: new TextStyle(fontSize: 25.0),
                ),
              ],
            ),
          ),
        ),
        new MaterialButton( // 跳轉按鈕
          onPressed: () {
            Navigator.of(context).push(new MaterialPageRoute(
                builder: (context) => new NewPage('Flutter高級進階頁面二')));
          },
          child: new Text('跳轉到新頁面'),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Theme( // 主題組件,可設置局部的主題樣式
      data: Config.themeData, // 設置爲配置的主題數據
      child: new Scaffold(
        appBar: new AppBar(elevation: 0),
        body: body(context), // 身體頁面body
      ),
    );
  }
}

再把NewPage測試頁面寫上:

class NewPage extends StatefulWidget {
  final String title; // 接收的標題

  NewPage(this.title);

  @override
  _NewPageState createState() => new _NewPageState(); // 建立有狀態頁面
}

class _NewPageState extends State<NewPage{
  @override
  Widget build(BuildContext context) {
    return new Theme(
      child: new Scaffold( // title就是咱們的標題
        appBar: new AppBar(title: new Text('頁面:${widget.title}'), elevation: 0),
        body: new Center(
          child: new Text(
            '這是${widget.title}',
            style: TextStyle(fontSize: 30.0),
          ),
        ),
      ),
      data: Config.themeData, // 設置爲配置的主題數據
    );
  }
}

直接複製到本身的項目內便可運行。


本文分享自微信公衆號 - flutter開發精選(Study_Knowledge)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索