はじめに
Flutter for Webでは、通常のCSSやSassと比較した場合レスポンシブ対応が難しい印象を持ちます。
昨今はAndroid系列の端末をはじめ、様々な画面サイズが登場しているためFlutter WebのOverflowエラーが発生しやすい原因となっています。
この記事では、2パターンのレスポンシブ対応について解説したいと思います。
手法自体は通常のWebと同じですが、画面幅を取得し、画面ごとPC用、Tablet用、Mobile用を用意して切り替えるケースと、画面幅に応じてスタイルを切り替えるケースです。
ケース1:画面ごと切り替える
こちらの手法の場合、responsive_builderというパッケージがとても便利です
使い方
import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
class SamplePage extends StatelessWidget {
const SamplePage({super.key});
@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
mobile: const SampleMobilePage(),
tablet: const SampleTabletPage(),
desktop: const SampleDesktopPage(),
);
}
}
また、私の所感的にデフォルトのブレイクポイントでも問題ありませんが、ブレイクポイントもカスタム可能です。
しかし、watchのブレイクポイントもrequiredのため指定しないといけない上、mobileは指定できないので注意が必要です。
import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
class SamplePage extends StatelessWidget {
const SamplePage({super.key});
@override
Widget build(BuildContext context) {
return ScreenTypeLayout(
breakpoints: ScreenBreakpoints(
tablet: 600,
desktop: 950,
watch: 300,
),
mobile: const SampleMobilePage(),
tablet: const SampleTabletPage(),
desktop: const SampleDesktopPage(),
);
}
}
ケース2:スタイル側で切り替える
やることは同じです。
こちらでブレイクポイントを指定し、それぞれ切り替えるだけです。
以下のようなenumとメソッドを用意してみました。
なお、ブレイクポイントはこちらのサイトを参考に設定しました!
import 'package:flutter/material.dart';
/// デバイスの種類を判定する
enum DeviceType {
mobile,
tablet,
desktop,
}
DeviceType getDeviceType(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
if (screenWidth < 430) {
return DeviceType.mobile;
} else if (screenWidth < 1024) {
return DeviceType.tablet;
} else {
return DeviceType.desktop;
}
}
使い方
class SamplePage extends StatelessWidget {
const SamplePage({super.key});
/// デバイス種別に応じてwidthを変更する
double getDialogWidth(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final deviceType = getDeviceType(context);
switch (deviceType) {
case DeviceType.mobile:
return screenWidth * 0.75;
case DeviceType.tablet:
return screenWidth * 0.56;
case DeviceType.desktop:
return screenWidth * 0.36;
}
}
double getDialogHight(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
final deviceType = getDeviceType(context);
switch (deviceType) {
case DeviceType.mobile:
return screenWidth * 0.85;
case DeviceType.tablet:
return screenWidth * 0.68;
case DeviceType.desktop:
return screenHeight * 0.64;
}
}
@override
Widget build(BuildContext context) {
return Dialog(
child: SizedBox(
height: getDialogHight(context),
width: getDialogWidth(context),
),
);
}
}
しかし、上記の例だとViewファイルが肥大化してしまいます。
そのため、sample_page_style.dart
のようなファイルを別途設けることで
肥大化は避けられると思います。