2022/12/18/Flutter/Rowでオーバーフローする時の対処法

 

Rowの子の幅が大きかったりすると画面幅、window幅をはみ出してオーバーフローしてしまいます。

If the width of the child of Row is large, it will overflow the screen width and window width.

 

そういう時の対処法をいくつか考えてみましょう。

Let’s consider some ways to deal with this.


スタート地点

starting point

//Rowでオーバーフローする場合の対処法0。まずスタート地点。
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Animated Icons',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(
        child:Row(
          children:[
            ElevatedButton(
              child:Text('aaaaaaaaaaaaaaaaaa'),
              onPressed: (){},
            ),
            SizedBox(width:4.0,),
            ElevatedButton(
              child:Text('bbbbbbbbbbbbbbbb'),
              onPressed: (){},
            ),
            SizedBox(width:4.0,),
            ElevatedButton(
              child:Text('ccccccccccccccc'),
              onPressed: (){},
            ),
            SizedBox(width:4.0,),
          ],
        ),
      ),
    );
  }
}

 

 


対処法1 (Solution 1)

Wrapを使う。

Using Wrap widget

//Rowでオーバーフローする場合の対処法1。Row→Wrapにする。
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Animated Icons',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(
        child:Wrap(
          children:[
            ElevatedButton(
              child:Text('aaaaaaaaaaaaaaaaaa'),
              onPressed: (){},
            ),
            SizedBox(width:4.0,),
            ElevatedButton(
              child:Text('bbbbbbbbbbbbbbbb'),
              onPressed: (){},
            ),
            SizedBox(width:4.0,),
            ElevatedButton(
              child:Text('ccccccccccccccc'),
              onPressed: (){},
            ),
            SizedBox(width:4.0,),
          ],
        ),
      ),
    );
  }
}

オーバーフロー部分が折り返されて例外が解消されます。

The overflow part is wrapped and the exception is resolved.

Wrapについて詳しくはこちらをご覧ください。

Learn more about Wraps here.


対処法2 (Solution 2)

OverflowBarを使う。

Using OverflowBar widget

//Rowでオーバーフローする場合の対処法2。Row→OverflowBarにする。

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Animated Icons',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(
        child:OverflowBar(
          spacing: 8.0,
          overflowSpacing: 4.0,
          overflowAlignment: OverflowBarAlignment.center,
          children:[
            ElevatedButton(
              child:Text('aaaaaaaaaaaaaaaaaa'),
              onPressed: (){},
            ),
            //SizedBox(width:4.0,),
            ElevatedButton(
              child:Text('bbbbbbbbbbbbbbbb'),
              onPressed: (){},
            ),
            //SizedBox(width:4.0,),
            ElevatedButton(
              child:Text('ccccccccccccccc'),
              onPressed: (){},
            ),
            //SizedBox(width:4.0,),
          ],
        ),
      ),
    );
  }
}

 

OverflowBarは、オーバーフローが発生しない状況ではRowのレイアウト、画面幅が狭くなってオーバーフローが発生するとColumnのレイアウトにしてくれるウィジェットですね。

OverflowBar is a widget that uses Row layout when overflow does not occur, and Column layout when screen width narrows and overflow occurs.

OverflowBarについて詳しくはこちらをご覧ください。

Learn more about OverflowBar here.


対処法3 (Solution 3)

それぞれの子要素をFlexibleでラップする。

Wrap each child element with Flexible.

//Rowでオーバーフローする場合の対処法3。全てFlexibleでラップする。

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Animated Icons',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(
        child:Row(
          children:[
            Flexible(
              flex:1,
              child: ElevatedButton(
                child:Text('aaaaaaaaaaaaaaaaaa'),
                onPressed: (){},
              ),
            ),
            SizedBox(width:4.0,),
            Flexible(
              flex:1,
              child: ElevatedButton(
                child:Text('bbbbbbbbbbbbbbbb'),
                onPressed: (){},
              ),
            ),
            SizedBox(width:4.0,),
            Flexible(
              flex: 1,
              child: ElevatedButton(
                child:Text('ccccccccccccccc'),
                onPressed: (){},
              ),
            ),
            SizedBox(width:4.0,),
          ],
        ),
      ),
    );
  }
}

Row/Columnの中でFlexibleを使うと、それぞれの子要素の大きさの比を指定することができ、結果としてオーバーフローが解消されます。

Using Flexible in Row/Column allows you to specify the size ratio of each child element, thus eliminating overflow.

 

この例では三つのボタンの幅を1:1:1に指定しています。

This example specifies a width ratio of 1:1:1 for the three buttons.

 

Flexibleについて詳しくはこちらをご覧ください。

Learn more about Flexible here.


対処法4 (Solution 4)

水平方向のListViewを使う。

Use a horizontal ListView.

//Rowでオーバーフローする場合の対処法4。水平方向のListViewを使う。

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Animated Icons',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Center(
        child:Container(
          height:50.0,
          color:Colors.orange,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: ListView(
              scrollDirection: Axis.horizontal,
              children:[
                ElevatedButton(
                  child:Text('aaaaaaaaaaaaaaaaaa'),
                  onPressed: (){},
                ),
                SizedBox(width:4.0,),
                ElevatedButton(
                  child:Text('bbbbbbbbbbbbbbbb'),
                  onPressed: (){},
                ),
                SizedBox(width:4.0,),
                ElevatedButton(
                  child:Text('ccccccccccccccc'),
                  onPressed: (){},
                ),
                SizedBox(width:4.0,),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

ListViewのscrollDirectionフィールドをAxis.horizontalにすることで水平方向にスクロールできるようになり、オーバーフローが解消されます。

Setting the scrollDirection field of the ListView to Axis.horizontal will allow horizontal scrolling and eliminate the overflow.

 

ListViewについて詳しくはこちらをご覧ください。

Learn more about ListView here.


以上、Rowでオーバーフローが発生する場合の対処法をお届けしました。
最後まで読んでいただきありがとうございました。

So far, we have provided a workaround for when an overflow occurs in Row.
Thank you for reading.

コメントを残す

メールアドレスが公開されることはありません。