💡 학습목표
1. Flutter의 레이아웃 매커니즘의 작동 방식
2. 위젯의 수직, 수평 배치
3. Flutter 레이아웃 구축 방법
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Layout demo',
home: Scaffold(
appBar: AppBar(
title: Text('layout demo'),
),
body: Center(
child: Text('Hello World'),
),
),
);
}
}
Context의 사용 사례
테마 데이터 가져오기
Theme.of(context)를 사용하여 현재 테마 데이터에 액세스할 수 있습니다.
Navigator 사용하기
페이지 전환을 위해 Navigator.of(context)를 사용할 수 있습니다.
상위 위젯에서 제공된 데이터에 액세스
Provider 패키지나 InheritedWidget을 사용하여 context를 통해 데이터에 액세스할 수 있습니다.
💡 BuildContext란
위젯 트리를 건물의 층과 같이 생각해보세요.
여러분이 건물 안에서 어디에 있는지 알려면 현재의 위치나 방향을 알아야 합니다.
context는 Flutter 앱의 건물에서 현재 위치와 방향을 알려주는 나침반과 같습니다.
여러분이 어떤 층에 있는지, 어떤 방에 있는지를 알게 해주며,
그 위치에 따라 어떤 서비스나 정보에 액세스할 수 있는지를 알려줍니다.
결론
context는 위젯의 현재 위치와 관련된 정보를 포함하는 객체입니다.
이를 사용하여 위젯 트리의 다른 부분과 상호 작용하거나, 특정 메타데이터를 얻거나,
상위 위젯에서 제공된 데이터에 액세스할 수 있습니다.
main
import 'package:flutter/material.dart';
import 'package:flutter_layout_01/component/favorited_widget.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
Widget textSection = Container(
padding: const EdgeInsets.all(32),
child: const Text(
'Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese '
'Alps. Situated 1,578 meters above sea level, it is one of the '
'larger Alpine Lakes. A gondola ride from Kandersteg, followed by a '
'half-hour walk through pastures and pine forest, leads you to the '
'lake, which warms to 20 degrees Celsius in the summer. Activities '
'enjoyed here include rowing, and riding the summer toboggan run.',
softWrap: true,
),
);
// theme 속성을 가져 오기
// 위젯 트리 내의 현재 위치에 대한 참조 및 핸들링 처리
// 위젯 트리에 다양한 메타 데이터나 부모 위젯에 접근하게 하여
// 상호 작용할 수 있또록 하는 BuildContext 객체
Color color = Theme.of(context).primaryColor;
Widget buttonSection = Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(color, Icons.call, "CALL"),
_buildButtonColumn(color, Icons.near_me, "ROUTE"),
_buildButtonColumn(color, Icons.share, "SHARE"),
],
);
// 지역 변수 + 연산
Widget titleSection = Container(
padding: EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Text(
"Oeschinen Lake Campground",
style: TextStyle(fontWeight: FontWeight.bold),
),
padding: EdgeInsets.only(bottom: 8),
),
Text(
"Kandersteg, Switzerland",
style: TextStyle(color: Colors.grey[500]),
)
],
),
),
FavoritedWidget(),
],
),
); // end of titleSection
return MaterialApp(
title: 'Flutter Layout demo',
home: Scaffold(
appBar: AppBar(
title: Text('layout demo'),
),
body: ListView(
children: [
Image.asset(
'assets/lake.jpeg',
width: 580,
height: 240,
fit: BoxFit.cover,
),
titleSection,
buttonSection,
textSection
],
),
),
);
} // end of build
Column _buildButtonColumn(Color color, IconData icon, String label) {
return Column(
children: [
Icon(icon, color: color),
Container(
margin: const EdgeInsets.only(top: 8),
child: Text(
label,
style: TextStyle(
fontSize: 12, fontWeight: FontWeight.w400, color: color),
),
),
],
);
}
}
favorited_widget
import 'package:flutter/material.dart';
class FavoritedWidget extends StatefulWidget {
const FavoritedWidget({super.key});
State<FavoritedWidget> createState() => _FavoritedWidgetState();
}
class _FavoritedWidgetState extends State<FavoritedWidget> {
// 1. 변수 선언 해보기
bool _isFavorited = true;
int _favoritedCount = 41;
Widget build(BuildContext context) {
return Row(
children: [
Container(
padding: EdgeInsets.all(4.0),
child: IconButton(
onPressed: () {
setState(() {
if(_isFavorited) {
_isFavorited = false;
_favoritedCount -= 1;
} else {
_isFavorited = true;
_favoritedCount += 1;
}
});
},
icon: _isFavorited
? const Icon(Icons.star)
: const Icon(Icons.star_border)),
),
SizedBox(
width: 18,
child: Text('$_favoritedCount'),
)
],
);
}
}