🤠

CrossAxisAlignment

2023/08/14に公開

普段使わないので調べてみた

https://api.flutter.dev/flutter/rendering/CrossAxisAlignment.html

公式を翻訳すると
フレックスレイアウトにおいて、クロス軸に沿って子供たちをどのように配置するか。

文字の解説しかなかったので、海外の記事を参考に学習してみた。
https://medium.com/flutter-community/flutter-layout-cheat-sheet-5363348d037e

サイズの異なる文字を揃えて並べるパターン

異なるテキストのベースラインを揃える必要がある場合は、CrossAxisAlignment.baselineを使用する必要があります。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TabBar with Riverpod',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WidgetExample(),
    );
  }
}

class WidgetExample extends StatelessWidget {
  const WidgetExample({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("CrossAxisAlignment")),
      body: Row(
        crossAxisAlignment: CrossAxisAlignment
            .baseline, // CrossAxisAlignment.baselineは、子要素のテキストベースラインを揃える
        textBaseline: TextBaseline.alphabetic,
        children: <Widget>[
          Text(
            'Baseline',
            style: TextStyle(fontSize: 30, color: Colors.red),
          ),
          Text(
            'Baseline',
            style: TextStyle(fontSize: 15, color: Colors.blue),
          ),
        ],
      ),
    );
  }
}

startの場合

横と縦で、星が均一に並ぶレイアウトだとこんな風になります。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TabBar with Riverpod',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WidgetExample(),
    );
  }
}

class WidgetExample extends StatelessWidget {
  const WidgetExample({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("CrossAxisAlignment")),
      body: Column(
        children: [
          // 横向き
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Icon(Icons.star, size: 50),
              Icon(Icons.star, size: 200),
              Icon(Icons.star, size: 50),
            ],
          ),
          // 縦向き
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Icon(Icons.star, size: 50),
              Icon(Icons.star, size: 200),
              Icon(Icons.star, size: 50),
            ],
          ),
        ],
      ),
    );
  }
}

centerの場合

星を使って、横と縦が均一に並ぶようにしたパターン。サイズは違うが星が中央に並んで、均一になっている。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TabBar with Riverpod',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WidgetExample(),
    );
  }
}

class WidgetExample extends StatelessWidget {
  const WidgetExample({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("CrossAxisAlignment")),
      body: Column(
        children: [
          // 横向き
          Row(
            crossAxisAlignment: CrossAxisAlignment.center,// CrossAxisAlignment.centerは、子要素を中央に配置する
            children: [
              Icon(Icons.star, size: 50),
              Icon(Icons.star, size: 200),
              Icon(Icons.star, size: 50),
            ],
          ),
          // 縦向き
          Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Icon(Icons.star, size: 50),
              Icon(Icons.star, size: 200),
              Icon(Icons.star, size: 50),
            ],
          ),
        ],
      ),
    );
  }
}

endの場合

横向きだと、下の端の方に均一に並び、縦だと右横に均一に並ぶ。ColumnをmainAxisAlignment: MainAxisAlignment.end,に変更すると、右横から、中央寄せになる。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TabBar with Riverpod',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WidgetExample(),
    );
  }
}

class WidgetExample extends StatelessWidget {
  const WidgetExample({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("CrossAxisAlignment")),
      body: Column(
        children: [
          // 横向き
          Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Icon(Icons.star, size: 50),
              Icon(Icons.star, size: 200),
              Icon(Icons.star, size: 50),
            ],
          ),
          // 縦向き
          Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Icon(Icons.star, size: 50),
              Icon(Icons.star, size: 200),
              Icon(Icons.star, size: 50),
            ],
          ),
        ],
      ),
    );
  }
}

stretchの場合

公式による
子どもたちに横軸を埋めることを要求する。
これにより、子要素に渡される制約は、横軸でタイトになります。

Columnで横と縦向きのWidgetを並べて表示しょうと思いましたがで、エラーが出てきてできなかったので、RowとColumn別々に表示します。

Columnでラップして、縦向きと横向きを表示しようとすると、こんなエラーが出てくる!

例外が発生しました
FlutterError (BoxConstraints forces an infinite height.
These invalid constraints were provided to RenderSemanticsAnnotations's layout() function by the following function, which probably computed the invalid constraints in question:
  RenderBox.layout (package:flutter/src/rendering/box.dart:2386:11)
The offending constraints were:
  BoxConstraints(0.0<=w<=Infinity, h=Infinity))

これを翻訳すると

例外が発生しました
FlutterError(BoxConstraintsは無限の高さを強制します。
これらの無効な制約は、おそらく問題の無効な制約を計算した以下の関数によって、RenderSemanticsAnnotationsのlayout()関数に提供されました:
  RenderBox.layout (package:flutter/src/rendering/box.dart:2386:11)
問題の制約は次のとおりです:
  BoxConstraints(0.0<=w<=Infinity,h=Infinity))です。

Flexibleで、RowとColumnをラップしてあげると、無限に広がるのを防止して、Widgetのエラーを防止できます。
このように書きます

body: Column(
        children: [
          Flexible(
            child: Row /*or Column*/ (
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Icon(Icons.star, size: 50),
                Icon(Icons.star, size: 200),
                Icon(Icons.star, size: 50),
              ],
            ),
          ),
          Flexible(
            child: Column /*or Column*/ (
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Icon(Icons.star, size: 50),
                Icon(Icons.star, size: 200),
                Icon(Icons.star, size: 50),
              ],
            ),
          ),
        ],
      ),

Row
こちらが横向きだけのパターン

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TabBar with Riverpod',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WidgetExample(),
    );
  }
}

class WidgetExample extends StatelessWidget {
  const WidgetExample({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("CrossAxisAlignment")),
      body: Row /*or Column*/(
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: <Widget>[
    Icon(Icons.star, size: 50),
    Icon(Icons.star, size: 200),
    Icon(Icons.star, size: 50),
  ],
),
    );
  }
}

Column
こちらが縦向きだけのパターン

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TabBar with Riverpod',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WidgetExample(),
    );
  }
}

class WidgetExample extends StatelessWidget {
  const WidgetExample({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("CrossAxisAlignment")),
      body: Column /*or Column*/ (
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Icon(Icons.star, size: 50),
          Icon(Icons.star, size: 200),
          Icon(Icons.star, size: 50),
        ],
      ),
    );
  }
}

まとめ

「crossAxisAlignment(クロスアラインメント)」は、主にUI(ユーザーインターフェース)デザインやレイアウトの文脈で使用される用語です。UI要素を配置する際に、主軸(通常は縦軸)と横軸(クロス軸)の2つの方向が存在します。主軸は通常要素を配置する基本的な方向を示し、横軸はその主軸に対して直交する方向です。

「crossAxisAlignment」は、横軸(クロス軸)に対してUI要素をどのように配置するかを指定するプロパティやコンセプトです。要素が主軸上に揃っている場合、クロス軸の配置方法が重要になります。

例えば、縦に一列に要素を配置する場合を考えてみましょう。主軸は縦方向であり、クロス軸は横方向です。このとき、「crossAxisAlignment」の値によって、各要素がクロス軸上でどのように配置されるかが変わります。

主な「crossAxisAlignment」の値とその効果は次の通りです:

  1. start(開始揃え): クロス軸の始点に要素を揃えます。
  2. center(中央揃え): クロス軸の中央に要素を揃えます。
  3. end(末尾揃え): クロス軸の末尾に要素を揃えます。
  4. stretch(伸縮揃え): クロス軸方向に要素を伸縮させて埋めます。
  5. baseline(ベースライン揃え): テキストなどの要素において、基準線(ベースライン)に要素を揃えます。

要するに、「crossAxisAlignment」はUI要素の横方向での配置方法を決定するもので、どのようにクロス軸上で要素を整列させるかを指定します。これによって、UIのデザインやレイアウトが意図通りに表示されるようになります。

Jboy王国メディア

Discussion