【Flutter】初学者が意外と陥りやすいTextウィジェットの黄色い下線問題

## はじめに
通常、Flutter開発においてTextウィジェットは`Scaffold`内で使用されることが多いです。

https://docs.flutter.dev/ui/widgets/text

以下の場合、テキストは正常に表示され、特に問題はありません。
```main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('text'),
        ),
      ),
    );
  }
}

```
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658262/c3007f4d-a374-9e1c-4f2b-f042368bbf05.png">


次に、Scaffoldがない場合のコード例を見てみましょう。

```main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Center(
        child: Text('text'),
      ),
    );
  }
}
```

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658262/7aa75a4a-b7df-8eea-115f-dcc72384f7ab.png">

するとテキストが異常に大きく、赤文字で黄色い下線が表示されるという、エラーを連想させるような表示になります。

## 解決方法
### ① Materialを使用（シンプル）
```dart
child: Material(
  child: Text('text'),
),
```

### ② DefaultTextStyleを使用
```dart
child: DefaultTextStyle(
  style: TextStyle(decoration: TextDecoration.none),
  child: Text('text'),
),
```
### ③ Scaffoldを使用
割愛します。

## 原因
この問題は、TextウィジェットがScaffoldのWidgetツリー内にないために発生します。

ではなぜ、`Scaffold`の有無でスタイルが変わるのでしょうか？

[公式](https://api.flutter.dev/flutter/widgets/Text-class.html#:~:text=The%20style%20argument%20is%20optional.%20When%20omitted%2C%20the%20text%20will%20use%20the%20style%20from%20the%20closest%20enclosing%20DefaultTextStyle.)にも書かれていますがTextウィジェットは何もスタイルを指定しない場合、一番近いDefaultTextStyleを利用します。
>The style argument is optional. When omitted, the text will use the style from the closest enclosing DefaultTextStyle.

これは、Scaffoldで囲われていない場合、Textウィジェットは`MaterialApp`のDefaultTextStyleを利用することを意味します。

以下[MaterialApp](https://github.com/flutter/flutter/blob/52e2ca38fcacedf59ef519f15d05d20623473dab/packages/flutter/lib/src/material/app.dart#L22)のコードの抜粋です。
`_errorTextStyle`がDefaultTextStyleとして使用されていることがわかります。

```app.dart
/// [MaterialApp] uses this [TextStyle] as its [DefaultTextStyle] to encourage
/// developers to be intentional about their [DefaultTextStyle].
///
/// In Material Design, most [Text] widgets are contained in [Material] widgets,
/// which sets a specific [DefaultTextStyle]. If you're seeing text that uses
/// this text style, consider putting your text in a [Material] widget (or
/// another widget that sets a [DefaultTextStyle]).
const TextStyle _errorTextStyle = TextStyle(
  color: Color(0xD0FF0000),
  fontFamily: 'monospace',
  fontSize: 48.0,
  fontWeight: FontWeight.w900,
  decoration: TextDecoration.underline,
  decorationColor: Color(0xFFFFFF00),
  decorationStyle: TextDecorationStyle.double,
  debugLabel: 'fallback style; consider putting your text in a Material',
);
```

このコードから、Scaffoldで作られるDefaultTextStyleではなく、MaterialAppで作られるDefaultTextStyleがTextウィジェットに適用されることがわかりました。

## 事例
しかし、特定のシナリオではTextウィジェットをScaffoldの外で使用する必要がある場合があるかもしれません。これには以下のような状況が含まれます。

- 非同期処理後のダイアログ表示
データ取得などの非同期処理が完了した後に表示されるダイアログ内でTextウィジェットを使用する場合。

- ローディング画面の表示
データの読み込みを開始する際にローディング画面を表示し、その中で「読み込み中...」などのメッセージをTextウィジェットで表示する場合。

他のシナリオも考えられますが、このような例では、ScaffoldのWidgetツリー外に配置される場合がありますので、注意して実装していきたいです。

## 参考

https://stackoverflow.com/questions/47114639/yellow-lines-under-text-widgets-in-flutter