〰️

【Flutter】RichText内のWidgetSpanで作ってずれた文字リンクの位置を修正

2025/01/19に公開

※自分用メモ:Notionで過去に書いたもの

こんにちは、laughtaoneです。
Flutter学習中に備忘録として書いていますので、正確な情報でない可能性もありますのでご了承ください。

状況

修正前

このように、修正前は「こちら」のテキストが前の「詳しくは」のテキストの位置とずれてしまっています。

修正後

これを全てのテキストで位置を同じにします。

変更箇所

修正前

変更前の該当箇所は次のとおりです:

RichText(
    text: TextSpan(
      style: TextStyle(color: Colors.black, height: 1),
      children: [
        TextSpan(text: '詳しくは', style: TextStyle(fontSize: 30)),
        WidgetSpan(
          child: GestureDetector(
            onTap: () {viewWebsite('https://www.google.com/');},
            child: Text(
              ' こちら',
              style: TextStyle(
                color: Colors.indigo[500],
                fontWeight: FontWeight.w500,
                fontSize: 30
              ),
            ),
          ),
        ),
      ],
    ),
  ),
),
変更前の全体コード
main.dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';


Future viewWebsite(String recvUrl) async {
  final url = Uri.parse(recvUrl);
  launchUrl(url);
}

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

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('リンク飛ぶ')),
        body: Center(
          child: RichText(
            text: TextSpan(
              style: TextStyle(color: Colors.black, height: 1),
              children: [
                TextSpan(text: '詳しくは', style: TextStyle(fontSize: 30)),
                WidgetSpan(
                  child: GestureDetector(
                    onTap: () {viewWebsite('https://www.google.com/');},
                    child: Text(
                      ' こちら',
                      style: TextStyle(
                        color: Colors.indigo[500],
                        fontWeight: FontWeight.w500,
                        fontSize: 30
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

修正後

該当箇所の修正後のコードは次のとおりです:

main.dart
RichText(
    text: TextSpan(
      style: TextStyle(color: Colors.black, height: 1),
      children: [
        TextSpan(text: '詳しくは', style: TextStyle(fontSize: 30)),
        WidgetSpan(
+          alignment: PlaceholderAlignment.baseline,
+          baseline: TextBaseline.alphabetic,
          child: GestureDetector(
            onTap: () {viewWebsite('https://www.google.com/');},
            child: Text(
              ' こちら',
              style: TextStyle(
                color: Colors.indigo[500],
                fontWeight: FontWeight.w500,
                fontSize: 30
              ),
            ),
          ),
        ),
      ],
    ),
  ),
),
変更後の全体コード
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';


Future viewWebsite(String recvUrl) async {
  final url = Uri.parse(recvUrl);
  launchUrl(url);
}

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

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('リンク飛ぶ')),
        body: Center(
          child: RichText(
            text: TextSpan(
              style: TextStyle(color: Colors.black, height: 1),
              children: [
                TextSpan(text: '詳しくは', style: TextStyle(fontSize: 30)),
                WidgetSpan(
+                 alignment: PlaceholderAlignment.baseline,
+                 baseline: TextBaseline.alphabetic,
                  child: GestureDetector(
                    onTap: () {viewWebsite('https://www.google.com/');},
                    child: Text(
                      ' こちら',
                      style: TextStyle(
                        color: Colors.indigo[500],
                        fontWeight: FontWeight.w500,
                        fontSize: 30
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

なぜこれだけで修正できるのか

WidgetSpan内に

alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic,

を書き足すだけで、なぜ修正できるのか紹介します。
まず alignment: PlaceholderAlignment.baseline は、ウィジェットの位置をベースラインに揃えるため、テキストとウィジェットが同じ縦の位置に配置されます。
次の baseline: TextBaseline.alphabetic は、ベースラインの基準をアルファベットのテキスト基準に設定し、英語テキストと同じ位置に揃えます。
これにより、修正を実現することができたのです。

まとめ

このようにして、RichText内のWidgetSpanで作ってずれた文字リンクの位置を修正することができました。

Discussion