Flutter에서 반응형 UI를 구현할 때 가장 중요한 도구 중 하나가 미디어 쿼리(MediaQuery)입니다. MediaQuery
를 사용하면 현재 화면의 크기, 방향(가로 또는 세로), 디스플레이 밀도 등 다양한 정보를 가져올 수 있습니다. 이를 활용하면 다양한 디바이스에서 최적화된 UI를 제공할 수 있습니다.
1. MediaQuery란?
MediaQuery
는 Flutter에서 제공하는 내장 클래스 중 하나로, 현재 디바이스의 화면 정보를 가져오는 역할을 합니다. 이를 통해 화면 크기에 따라 동적으로 UI 요소를 조정하는 반응형 디자인을 구현할 수 있습니다.
예를 들어, 스마트폰과 태블릿에서 동일한 앱을 실행할 때, MediaQuery
를 사용하면 각 디바이스에 맞게 UI를 변경할 수 있습니다.
2. MediaQuery로 화면 크기 가져오기
MediaQuery.of(context)
를 사용하면 현재 화면의 크기를 가져올 수 있습니다. 아래 예제에서는 화면의 너비와 높이를 출력하는 방법을 보여줍니다.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(title: Text('MediaQuery 예제')),
body: Center(
child: Text(
'화면 크기: ${screenWidth.toStringAsFixed(2)} x ${screenHeight.toStringAsFixed(2)}',
style: TextStyle(fontSize: 20),
),
),
);
}
}
위 코드에서는 MediaQuery.of(context).size.width
와 MediaQuery.of(context).size.height
를 사용하여 현재 화면의 너비와 높이를 가져왔습니다.
3. MediaQuery를 활용한 반응형 UI
(1) 화면 크기에 따른 위젯 조정
아래 예제에서는 화면 크기에 따라 텍스트 크기를 다르게 설정하는 방법을 보여줍니다.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(title: Text('반응형 UI 예제')),
body: Center(
child: Text(
'반응형 텍스트',
style: TextStyle(fontSize: screenWidth * 0.05), // 화면 너비의 5% 크기
),
),
);
}
}
위 코드에서는 screenWidth * 0.05
를 사용하여 화면 크기에 따라 텍스트 크기를 조정했습니다.
(2) 화면 크기에 따라 다른 레이아웃 적용
아래 예제에서는 화면이 600px 이상일 때는 가로로 배치하고, 그보다 작을 때는 세로로 배치하는 UI를 구현합니다.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ResponsiveLayout(),
);
}
}
class ResponsiveLayout extends StatelessWidget {
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(title: Text('반응형 레이아웃')),
body: screenWidth > 600
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(width: 100, height: 100, color: Colors.blue),
SizedBox(width: 20),
Container(width: 100, height: 100, color: Colors.red),
],
)
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(width: 100, height: 100, color: Colors.blue),
SizedBox(height: 20),
Container(width: 100, height: 100, color: Colors.red),
],
),
);
}
}
위 코드에서는 screenWidth
값을 기준으로 Row
와 Column
을 동적으로 변경하는 방식으로 반응형 UI를 구현했습니다.
4. MediaQuery를 활용한 SafeArea 적용
MediaQuery
를 사용하면 상태바(Status Bar), 네비게이션 바(Navigation Bar), 노치(Notch) 영역을 고려한 UI를 만들 수도 있습니다. Flutter에서는 이러한 영역을 피할 수 있도록 SafeArea
위젯을 제공합니다.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeAreaScreen(),
);
}
}
class SafeAreaScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Text('이 텍스트는 노치 영역을 피합니다.', style: TextStyle(fontSize: 20)),
),
),
);
}
}
위 코드에서 SafeArea
를 사용하면 디바이스의 상태바나 노치 영역과 겹치지 않도록 자동으로 패딩이 추가됩니다.
결론
MediaQuery
는 Flutter에서 반응형 UI를 구현할 때 필수적인 도구입니다. 화면 크기, 방향, 디스플레이 밀도 등의 정보를 쉽게 가져올 수 있어, 다양한 디바이스에서 최적화된 UI를 제공할 수 있습니다. 또한, SafeArea
와 결합하면 노치나 상태바 영역을 고려한 디자인도 쉽게 적용할 수 있습니다.
이제 MediaQuery
를 활용하여 다양한 디바이스에서도 최적화된 UI를 만들어 보세요!