【Flutter】Rowで片方だけを真ん中にする


# はじめに
FlutterのRowを使って、左側のWidgetだけとか、右側のWidgetだけを真ん中に配置するという方法に意外に苦戦したので、実装方法を記事にしたいと思います。
デザインとしては下記のように、Centerというテキストが真ん中に配置されて、その右にlableというテキストが配置されるというデザインです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/517bdf88-3572-0199-d2c0-6509f7adda04.png)

# 配置方法
下記のような形で、両側に同じ幅の領域を取り、真ん中の部分に真ん中へ配置したいWidgetを並べます。
![スクリーンショット 2023-12-23 12.35.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/29a1a2f5-598e-9185-e1b2-ed678d2ac30a.png)

コードにすると下記のようになります。

```dart
Row(
  children: [
    Expanded(
      child: SizedBox()
    ),
    Center(
      child: Text(
        "Center",
      ),
    ),
    Expanded(
      child: Padding(
        padding: EdgeInsets.only(left: 8.0),
        child: Text("Right"),
      ),
    ),
  ],
),
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/9441383b-631b-1d9a-6604-89bad217a2f8.png)


# 注意点
冒頭で見せたデザインを実装したい場合は、`Expanded`ではなく`Flexible`を使いましょう。
下記のようにExpandedを使うと、横幅いっぱいに広がってしまいます。

```dart
Row(
  children: [
    Expanded(
      child: SizedBox()
    ),
    Center(
      child: Text(
        "Center",
      ),
    ),
    Expanded(
      child: Padding(
        padding: const EdgeInsets.only(left: 8.0),
        child: Container(
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadius.circular(16),
          ),
          // heightとwidthはExpanded内だと効かない
          height: 32,
          width: 80,
          child: const Center(child: Text("Right")),
        ),
      ),
    ),
  ],
),

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/95fada62-6351-e77c-79cb-f98158555001.png)

下記のようにFlexibleを使えば解決します。

```dart
Row(
  children: [
    Expanded(
      child: SizedBox()
    ),
    Center(
      child: Text(
        "Center",
      ),
    ),
    Flexible(
      child: Padding(
        padding: const EdgeInsets.only(left: 8.0),
        child: Container(
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadius.circular(16),
          ),
          // heightとwidthはExpanded内だと効かない
          height: 32,
          width: 80,
          child: const Center(child: Text("Right")),
        ),
      ),
    ),
  ],
),

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/27b8db15-d847-a21e-6d49-43268b993909.png)


<!--
横幅が大きいとオーバフローする

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:janbariapp/gen/colors.gen.dart';
import 'package:janbariapp/presentation/common/widgets/dashed_line.dart';
import 'package:janbariapp/presentation/core/constants/formats.dart';
import 'package:janbariapp/presentation/core/constants/strings.dart';
import 'package:janbariapp/presentation/core/constants/text_styles.dart';

class TotalEarningsRateRow extends StatelessWidget {
  const TotalEarningsRateRow({
    super.key,
    required this.title,
    required this.userWinningRate,
    required this.userLosingRate,
  });
  final String title;
  final double? userLosingRate;
  final double? userWinningRate;

  @override
  Widget build(BuildContext context) {
    final textHeight = 23.h;
    const subTitleFontSize = 12.0;
    const displayFontSize = 28.0;
    final subTitleHeight =
        textHeight / TextStyles.Roboto.w700.size(subTitleFontSize).fontSize!;
    final displayTextHeight =
        textHeight / TextStyles.Roboto.w700.size(displayFontSize).fontSize!;
    return Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
      Text(
        title,
        textAlign: TextAlign.start,
        style: TextStyles.AOTFGothic.w500
            .size(13)
            .colorName(ColorName.grayA6)
            .copyWith(height: 1.77), // 23px
      ),
      SizedBox(
        height: 5.h,
      ),
      Row(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          Text(
            AppStrings.subTitleWinningPeople,
            style: TextStyles.Roboto.w700
                .size(subTitleFontSize)
                .colorName(ColorName.gray65)
                .copyWith(
                  height: subTitleHeight,
                ),
          ),
          SizedBox(
            width: 10.w,
          ),
          Text(
            userWinningRate.formatRate(),
            style: TextStyles.Roboto.w700
                .size(displayFontSize)
                .colorName(userWinningRate == null
                    ? ColorName.gray65
                    : ColorName.calenderSeisekiPlus)
                .copyWith(
                  height: displayTextHeight,
                ),
          ),
          SizedBox(
            width: 21.w,
          ),
          Text(
            AppStrings.subTitleLosingPeople,
            style: TextStyles.Roboto.w700
                .size(subTitleFontSize)
                .colorName(ColorName.gray65)
                .copyWith(
                  height: subTitleHeight,
                ),
          ),
          SizedBox(
            width: 10.w,
          ),
          Text(
            userLosingRate.formatRate(),
            style: TextStyles.Roboto.w700
                .size(displayFontSize)
                .colorName(userLosingRate == null
                    ? ColorName.gray65
                    : ColorName.calenderSeisekiAka)
                .copyWith(
                  height: displayTextHeight,
                ),
          ),
        ],
      ),
      SizedBox(height: 6.h),
      const DashedLine(),
    ]);
  }
}
-->