リバース・エンジニアリング

Flultterとテックブログと時々iOS

6. Column と Row ウィジェットで複数のウィジェットを配置する

今日はColumn とRow について学習しました。

Flutter のColumn とRow の概念はiOSのUIKitにはないようなUIです。 一つのレイアウトに複数のウィジェットを配置したい場合に使います。

Androidに近い概念があります。 そのためAndroidのレイアウトと比較してみます。

Flutter Android
Column LinearLayout(Vertical)
Row LinearLayout(Horizontal)

AndroidのLinearLayoutは縦か横にUI を並べますがまさにそんな感じのウィジェットというイメージです。 LinearLayoutで思い出したのですが、そういえばiOSにも似た概念にStackViewがあったことを忘れていました。

つまり、Flutter・AndroidiOSのそれぞれで比較すると

Flutter Android Android
Column LinearLayout(Vertical) StackView(Vertical)
Row LinearLayout(Horizontal) StackView(Horizontal)

こういうことになりますね。 ただColumnとRowはそれぞれ逆にもウィジェットを並べることができるので一概に縦・横に一列に並べるという表現は違いました。 それはおいおい説明すると思います。

Columnのプロパティについて

Column にはいくつかのプロパティが用意されています。

プロパティ 役割
Main Axis Alignment Columnウィジェット「自体」の配置場所を指定する
Cross Axis Alignment Columnに「入れた」ウィジェットの配置場所を指定する
Main Axis Size ウィジェット自体のサイズを指定する

それでは試しにサンプルのソースコードを書いていきます。

stackview.dart

import 'package:flutter/material.dart';

class StackView extends StatefulWidget {
  @override
  _StackViewState createState() => _StackViewState();
}

class _StackViewState extends State<StackView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Column Sample'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              '1st View',
              style: TextStyle(
                  backgroundColor: Colors.blue,
                  fontSize: 30.0,
                  color: Colors.white,
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
            ),
            Text(
              '2nd View',
              style: TextStyle(
                  backgroundColor: Colors.green,
                  fontSize: 30.0,
                  color: Colors.white,
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
            ),
            Text(
              '3rd View',
              style: TextStyle(
                  backgroundColor: Colors.red,
                  fontSize: 30.0,
                  color: Colors.white,
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
            ),
          ],
        ));
  }
}

main.dart

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

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

class MyApp extends StatelessWidget {
  final title = 'FloatingActionButtonのサンプルコード';
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: true,
      title: 'Sample App',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: const Color(0xff2196f3),
        accentColor: const Color(0xff2196f3),
        canvasColor: const Color(0xfffafafa),
      ),
      home: new StackView(),
    );
  }
}

これをビルドします。今回はAndroidエミュレータを使います。

f:id:qed805:20200119234116p:plain
Column を使ったサンプル

このように見えます。

試しにここからMain Axis Alignmentを操作していきます。

start center end
f:id:qed805:20200119234248p:plain
Main Axis Alignment が start
f:id:qed805:20200119234313p:plain
Main Axis Alignment が center
f:id:qed805:20200119234357p:plain
Main Axis Alignment が end

このように見えることがわかりました。 次にCross Axis Alignmentを操作していきます。

start center end
f:id:qed805:20200119234248p:plain
Cross Axis Alignment が start
f:id:qed805:20200119234629p:plain
Cross Axis Alignment が center
f:id:qed805:20200119234707p:plain
Cross Axis Alignment が end

わかりにくいのでTextの文字を変更してwidth の調整をしてみます。

center end
f:id:qed805:20200119235723p:plain
Cross Axis Alignment が center
f:id:qed805:20200119235751p:plain
Cross Axis Alignment が end

これでだいぶ見やすくなりました。

このように Column はウィジェットを複数個を配置して縦に見せるレイアウトでした。

Rowのプロパティについて

Colum は縦にウィジェットを並べるものでした。それに対してRow はウィジェットを横に並べるレイアウトになります。 では、試しに先程のサンプルコードをColumnからRow に変更してみましょう。

stackview.dart

import 'package:flutter/material.dart';

class StackView extends StatefulWidget {
  @override
  _StackViewState createState() => _StackViewState();
}

class _StackViewState extends State<StackView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Column Sample'),
        ),
        body: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              '1st View',
              style: TextStyle(
                  backgroundColor: Colors.blue,
                  fontSize: 30.0,
                  color: Colors.white,
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
            ),
            Text(
              '2nd View',
              style: TextStyle(
                  backgroundColor: Colors.green,
                  fontSize: 30.0,
                  color: Colors.white,
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
            ),
            Text(
              '3rd View',
              style: TextStyle(
                  backgroundColor: Colors.red,
                  fontSize: 30.0,
                  color: Colors.white,
                  fontWeight: FontWeight.w400,
                  fontFamily: "Roboto"),
            ),
          ],
        ));
  }
}

ColumnをRow に変更しただけです。 これでウィジェットを横に並べることができます。

f:id:qed805:20200120000154p:plain
Row で並べたウィジェットの見え方

そして、ColumnとRow の使い分けと覚え方についてです。 iOSエンジニアをやっていると UITableView を使うことが多いと思います。 UITableView に indexPath.row というのがあってこのrowが列を表していて縦にUIが並んでいました。 なのでiOSエンジニアだとRow が縦向きのイメージを持ちますが、「Flutterでは逆にRowは横に並べる」と覚えてしまえばいいかと思います。 結構雑な覚え方になりますが私はこれで「Row=横」のイメージに切り替えられました。

以上で Column と Row の具体的な使い方がわかりました。