LoginSignup
11

More than 5 years have passed since last update.

FlutterでWidgetTree全体にTextStyleを適用する(DefaultTextStyle)

Posted at

チュートリアルの'Nesting rows and columns'で以下のように書かれているように、DefaultTextStyle.mergeを使うことで、その下のWidgetTree全体に共通textStyleを適用することができます。

DefaultTextStyle.merge allows you to create a default text style that is inherited by its child and all subsequent children.

この記事では、画面内のWidgetTree全体にTextStyleを適用させるパターンと、その中の一部のWidgetTreeのみにTextStyleを適用させるパターンを紹介します。

画面内のWidgetTree全体にTextStyleを適用させるパターン

例として、下のスクショでは、大まかに言えば3つのRow widgetが1つのColumn widgetの中に入っていて、各Row widgetの中には3つのText widgetがあり、それぞれ引数にa b c という文字リテラルが指定してあります。

さらに、この全てのText widgetのstyleプロパティで、太字など以下のTextStyleも指定されています。

Screenshot_1528550502.png

    var descTextStyle = TextStyle(
      color: Colors.black,
      fontWeight: FontWeight.w800,
      fontFamily: 'Roboto',
      letterSpacing: 0.5,
      fontSize: 50.0,
    );
  var row = Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Text('a', style : descTextStyle),
        Text('b', style : descTextStyle),
        Text('c', style : descTextStyle),
      ],
    );

ただ、今回のように計9個のText widget全てに対し、個別にstyleを指定するのは面倒くさいですよね。

そんな時に便利なのが、DefaultTextStyle widgetのファクトリメソッドmergeです。

mergeメソッドの引数styleにTextStyleを指定し、childにwidgetを指定してあげると、このwidgetから始まるViewTreeの全ての階層に、このTextStyleが指定されます。

そのため、この画面内の全てのWidgetTreeの全てにdescTextStyleを設定したいという時には、以下のようにScaffoldbody プロパティにDefaultTextStylewidgetを指定してあげれば良いと思います。
(いまだに忘れますが、このDefaultTextStyleもwidgetなんですよね。)

    return new MaterialApp(
      theme: ThemeData(),
      title: 'Snapshot Title',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('DefaultTextStyleTest'),
        ),
        body: DefaultTextStyle.merge(
            style: descTextStyle,
            child: Center(
              child: column,
            )),
      ),
    );

一部のWidgetTreeのみにTextStyleを適用させるパターン

また、一部の階層だけにTextStyleを指定したい時も、簡単です。

   var column = Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        _buildRowContainer(Colors.red),

        //2番目のRow階層にだけdescTextStyleを指定
        DefaultTextStyle.merge(
            style: descTextStyle,
            child: _buildRowContainer(Colors.green),),

        _buildRowContainer(Colors.blue),
      ],
    );

Screenshot_1528552240.png


一応、main.dart全体は以下です(bodyにDefaultTextStyleを指定したバージョン)。

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

void main() {
  //debugPaintSizeEnabled = true;
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    var descTextStyle = TextStyle(
      color: Colors.black,
      fontWeight: FontWeight.w800,
      fontFamily: 'Roboto',
      letterSpacing: 0.5,
      fontSize: 50.0,
    );

    var row = Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Text('a'),
        Text('b'),
        Text('c'),
      ],
    );

    Container _buildRowContainer(Color color) {
      return Container(
        color: color,
        child: row,
      );
    }

    var column = Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        _buildRowContainer(Colors.red),
        _buildRowContainer(Colors.green),
        _buildRowContainer(Colors.blue),
      ],
    );

    return new MaterialApp(
      title: 'Snapshot Title',
      home: Scaffold(
        appBar: AppBar(
          title: Text('DefaultTextStyleTest'),
        ),
        body: DefaultTextStyle.merge(
            style: descTextStyle,
            child: Center(
              child: column,
            )),
      ),
    );
  }
}

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11