Responsive Design

āļāļēāļĢāļ›āļĢāļąāļš UI āđƒāļŦāđ‰āđ€āļŦāļĄāļēāļ°āļāļąāļšāļ‚āļ™āļēāļ”āļŦāļ™āđ‰āļēāļˆāļ­āđāļĨāļ° platform āļ•āđˆāļēāļ‡āđ† āđƒāļ™ Flutter

Responsive vs Adaptive

ResponsiveAdaptive
āļ›āļĢāļąāļšāļ•āļēāļĄāļ‚āļ™āļēāļ”āļˆāļ­ (width, height)Platform (iOS, Android)
āļ•āļąāļ§āļ­āļĒāđˆāļēāļ‡āļĄāļ·āļ­āļ–āļ·āļ­ = Column, tablet = RowiOS āđƒāļŠāđ‰ Cupertino, Android āđƒāļŠāđ‰ Material
āđ€āļ„āļĢāļ·āđˆāļ­āļ‡āļĄāļ·āļ­MediaQuery, LayoutBuilderPlatform.isIOS, Platform.isAndroid

MediaQuery — āļĢāļđāđ‰āļ‚āļ™āļēāļ”āļˆāļ­

final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
 
// āđ€āļ›āļĨāļĩāđˆāļĒāļ™ layout āļ•āļēāļĄāļ‚āļ™āļēāļ”āļˆāļ­
if (width < 600) {
  return Column(children: [chart, expensesList]);     // āļĄāļ·āļ­āļ–āļ·āļ­āđāļ™āļ§āļ•āļąāđ‰āļ‡
} else {
  return Row(children: [
    Expanded(child: chart),
    Expanded(child: expensesList),
  ]);  // āđāļ™āļ§āļ™āļ­āļ™/tablet
}

āļ‚āđ‰āļ­āļ„āļ§āļĢāļĢāļ°āļ§āļąāļ‡: MediaQuery.of(context) āļ§āļąāļ”āļˆāļēāļāļ‚āļ™āļēāļ”āļˆāļ­āļ—āļąāđ‰āļ‡āļŦāļĄāļ” āđ„āļĄāđˆāđƒāļŠāđˆāļžāļ·āđ‰āļ™āļ—āļĩāđˆāļ—āļĩāđˆ widget āđƒāļŠāđ‰āđ„āļ”āđ‰āļˆāļĢāļīāļ‡

LayoutBuilder — āļĢāļđāđ‰ constraints āļ‚āļ­āļ‡ parent

LayoutBuilder(builder: (ctx, constraints) {
  if (constraints.maxWidth >= 600) {
    return wideLayout;    // tablet/landscape
  }
  return narrowLayout;    // phone/portrait
});

āđƒāļŠāđ‰ LayoutBuilder āđāļ—āļ™ MediaQuery āđ€āļĄāļ·āđˆāļ­: widget āļ­āļĒāļđāđˆāđƒāļ™ container āļ—āļĩāđˆāļĄāļĩāļ‚āļ™āļēāļ”āļˆāļģāļāļąāļ” (āđ€āļŠāđˆāļ™āļ­āļĒāļđāđˆāđƒāļ™ Column āļ—āļĩāđˆāđāļšāđˆāļ‡āļ„āļĢāļķāđˆāļ‡) — LayoutBuilder āļšāļ­āļāļžāļ·āđ‰āļ™āļ—āļĩāđˆāļˆāļĢāļīāļ‡āļ—āļĩāđˆāđ„āļ”āđ‰

Adaptive — āļ›āļĢāļąāļšāļ•āļēāļĄ Platform

import 'dart:io';
 
if (Platform.isIOS) {
  return CupertinoAlertDialog(...);   // iOS style
}
return AlertDialog(...);              // Material (Android) style

SafeArea — āļŦāļĨāļĩāļ notch/status bar

SafeArea(
  child: myWidget,  // āđ„āļĄāđˆāļ–āļđāļ notch/status bar/home bar āļšāļąāļ‡
)

Breakpoints āļ—āļĩāđˆāđāļ™āļ°āļ™āļģ

āļ‚āļ™āļēāļ”Device
< 600pxPhone (portrait)
600-900pxPhone (landscape) / Small tablet
> 900pxTablet / Desktop

Key Points

  • MediaQuery = āļ‚āļ™āļēāļ”āļˆāļ­āļ—āļąāđ‰āļ‡āļŦāļĄāļ” / LayoutBuilder = āļžāļ·āđ‰āļ™āļ—āļĩāđˆāļ—āļĩāđˆ widget āđ„āļ”āđ‰āļˆāļĢāļīāļ‡
  • Responsive (āļ‚āļ™āļēāļ”āļˆāļ­) āļāļąāļš Adaptive (platform) āđ€āļ›āđ‡āļ™āļ„āļ™āļĨāļ°āđ€āļĢāļ·āđˆāļ­āļ‡
  • SafeArea āļ„āļ§āļĢāđƒāļŠāđ‰āđ€āļŠāļĄāļ­āđ€āļžāļ·āđˆāļ­āļŦāļĨāļĩāļ notch āđāļĨāļ° system UI
  • āđƒāļŠāđ‰ Expanded āđƒāļ™ Row/Column āđ€āļžāļ·āđˆāļ­āđāļšāđˆāļ‡āļžāļ·āđ‰āļ™āļ—āļĩāđˆāđāļšāļšāļĒāļ·āļ”āļŦāļĒāļļāđˆāļ™
  • Flutter — framework āļ—āļĩāđˆāļĢāļ­āļ‡āļĢāļąāļš responsive/adaptive
  • Widgets — LayoutBuilder, MediaQuery, SafeArea, Expanded