원하는 화면

1. 화면 상단
return Scaffold(
endDrawer: Container(
// side bar 내용을 레이어로 하나 더 올리는 것
width: 200,
color: Colors.yellow,
),
appBar: AppBar(
leading: Icon(Icons.arrow_back_ios),
title: Text("Profile"),
centerTitle: true,
),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 100,
height: 100,
child: CircleAvatar(
backgroundImage: AssetImage("assets/avatar.png"),
),
),
Column(
children: [
Text("HelloWorld"),
Text("Programer"),
],
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(onPressed: () {}, child: Text("버튼1")),
OutlinedButton(onPressed: () {}, child: Text("버튼2")),
TextButton(
onPressed: () {},
child: Text("버튼3"),
style: TextButton.styleFrom(
backgroundColor: Colors.blueAccent,
foregroundColor: Colors.white,
minimumSize: Size(200, 40),
),
),
],
),
- endDrawer
- 우측에 나오는 사이드 드로어 메뉴입니다.
- 위치는 appbar 우측 action 부분에 있지만 앱 바 위에 얹지는 형식이라 appBar 밖에 써야 합니다.
- SizedBox
- width, height 속성이 없는 위젯의 크기를 설정하려면 SizedBox 위젯으로 감싸서 크기를 지정할 수 이씁니다.
- CircleAvatar
- 원형 아바타 위젯입니다.
- backgroundImage는 AssetImage를 받을 수 있습니다.
- Button 위젯 3가지
- ElevatedButton
- onPressed: 클릭 시 동작 설정
- child: 버튼 텍스트 설정
- OutlinedButton
- 외곽선이 있는 버튼
- TextButton
- 일반 버튼입니다.
style: TextButton.styleFrom
→ styleFrom으로 style 설정을 해줘야 버튼 내용이 바뀌어도 style이 유지됩니다.
2. TabBar
Expanded(
child: DefaultTabController(
initialIndex: 0, // 시작 인덱스 0
length: 2,
child: Column(
children: [
TabBar(
tabs: <Widget>[
Tab(
icon: Icon(Icons.beach_access_sharp),
),
Tab(
icon: Icon(Icons.brightness_5_sharp),
),
], // Widget
), // TabBar
Expanded(
child: TabBarView(
children: <Widget>[
GridView.builder(
physics: NeverScrollableScrollPhysics(),
itemCount: 30,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 1, // x축 간격
mainAxisSpacing: 1, // y축 간격
),
itemBuilder: (context, index) {
// index 0 부터 for 반복 실행, 빌더 써야 하는 이유 -> 통신에서 이미지 몇개 올지 모름
return Image.network(
// 더미 사진 제공해주는 사이트
"https://picsum.photos/id/${200 + index}/200/300",
fit: BoxFit.cover,
);
},
), // GridView.builder
Center(
child: Text("It's next tab here"),
),
],
), // TabBarView
),
],
),
), // DefaultTabController
)
DefaultTabController
- initialIndex
- 최초로 켜져 있는 탭을 설정합니다.
- length
- 탭의 개수를 설정합니다.
- TabBar와 TabBarView는 쌍으로 꼭 있어야 합니다.
- TabBarView
- children으로 위젯 리스트를 받습니다.
- 높이 설정을 안 해줄 경우 “Horizontal viewport was given unbounded height.” 에러가 발생합니다.
GridView.builder
- itemCount
- 표시할 아이템 개수입니다.
- gridDelegate
- 그리드 레이아웃을 정의합니다.
- SliverGridDelegateWithFixedCrossAxisCount → 그리드 레이아웃 설정
- crossAxisCount: 1행에 배치할 아이템 개수
- crossAxisSpacing: horizontal gap 설정
- mainAxisSpacing: vertical gap 설정
- itemBuilder
- for 반복을 시행하면서 아이템을 동적으로 생성합니다.
- physics: NeverScrollableScrollPhysics()
- 이 속성은 그리드 내부의 스크롤을 비활성화합니다.
- 즉, 그리드 뷰가 자체적으로 스크롤하지 않게 합니다.
- 다른 스크롤 가능한 부모 위젯에 포함될 때 유용합니다.
3. 전체 코드
import 'package:flutter/material.dart';
void main() => runApp(const TabBarApp());
class TabBarApp extends StatelessWidget {
const TabBarApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(useMaterial3: true),
home: const TabBarExample(),
);
}
}
class TabBarExample extends StatelessWidget {
const TabBarExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
endDrawer: Container(
// side bar 내용을 레이어 하나 더 올리는 것
width: 200,
color: Colors.yellow,
),
appBar: AppBar(
leading: Icon(Icons.arrow_back_ios),
title: Text("Profile"),
centerTitle: true,
),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 100,
height: 100,
child: CircleAvatar(
backgroundImage: AssetImage("assets/avatar.png"),
),
),
Column(
children: [
Text("HelloWorld"),
Text("Programer"),
],
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(onPressed: () {}, child: Text("버튼1")),
OutlinedButton(onPressed: () {}, child: Text("버튼2")),
TextButton(
onPressed: () {},
child: Text("버튼3"),
style: TextButton.styleFrom(
backgroundColor: Colors.blueAccent,
foregroundColor: Colors.white,
minimumSize: Size(200, 40),
),
),
],
),
Expanded(
child: DefaultTabController(
initialIndex: 0, // 시작 인덱스 0
length: 2,
child: Column(
children: [
const TabBar(
tabs: <Widget>[
Tab(
icon: Icon(Icons.beach_access_sharp),
), // Tab
Tab(
icon: Icon(Icons.brightness_5_sharp),
), // Tab
], // Widget
), // TabBar
Expanded(
child: TabBarView(
children: <Widget>[
GridView.builder(
itemCount: 30,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 5, // x, y 축 간격
mainAxisSpacing: 1,
),
itemBuilder: (context, index) {
// index 0 부터 for 반복 실행, 빌더 써야 하는 이유 -> 통신에서 이미지 몇개 올지 모름
return Image.network(
// 더미 사진 제공해주는 사이트
"https://picsum.photos/id/${200 + index}/200/300",
fit: BoxFit.cover,
);
},
), // GridView.builder
Center(
child: Text("It's sunny here"),
),
],
), // TabBarView
),
],
),
), // DefaultTabController
),
],
),
);
}
}
Share article