0.파일 구성

1. ProfileButtons.dart
class ProfileButtons extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildFollowButton(),
_buildMessageButton(),
],
);
}
Widget _buildFollowButton() {
return InkWell(
onTap: () {
print("Follow 버튼 클릭됨");
},
child: Container(
alignment: Alignment.center,
//컨테이너 내부 Text 위젯 정렬시 사용
width: 150,
height: 45,
child: Text(
"Follow",
style: TextStyle(color: Colors.white),
),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
),
),
);
}
Widget _buildMessageButton() {
return InkWell(
onTap: () {
print("Message 버튼 클릭됨");
},
child: Container(
alignment: Alignment.center,
width: 150,
height: 45,
child: Text(
"Message",
style: TextStyle(color: Colors.black),
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(), //컨테이너에 테두리 선을 준다.
),
),
);
}
}

코드설명
팔로우 버튼:
_buildFollowButton()
메서드는 팔로우 버튼을 정의하며,InkWell
을 사용하여 터치 인터랙션을 추가합니다.
- 터치 시
"Follow 버튼 클릭됨"
이라는 메시지를 출력하며, 버튼은 파란색 배경과 하얀색 텍스트로 디자인되어 있습니다.
메시지 버튼:
_buildMessageButton()
메서드는 메시지 버튼을 정의하며, 이 또한InkWell
로 터치 인터랙션을 추가합니다.
- 터치 시
"Message 버튼 클릭됨"
이라는 메시지를 출력하며, 버튼은 하얀색 배경과 검은색 텍스트로 디자인되어 있습니다.
InkWell: 터치 시 시각적 피드백을 제공하며, 버튼 클릭 이벤트를 처리하는 역할을 합니다.
2. Profile_count-info.dart
import 'package:flutter/material.dart';
class ProfileCountInfo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildInfo("50", "Posts"),
_buildLine(),
_buildInfo("10", "Likes"),
_buildLine(),
_buildInfo("3", "share"),
],
);
}
Widget _buildInfo(String count, String title) {
return Column(
children: [
Text(
count, //변수 바인딩
style: TextStyle(fontSize: 15),
),
SizedBox(height: 2),
Text(
title, //변수 바인딩
style: TextStyle(fontSize: 15),
),
],
);
}
Widget _buildLine() {
return Container(
width: 2,
height: 60,
color: Colors.blue,
);
}
}

코드설명
ProfileCountInfo
클래스는 게시물 수, 좋아요 수, 공유 수 등의 정보를 한 줄(Row)로 정렬하는 Flutter 위젯입니다.buildInfo 메서드:
_buildInfo
는 두 개의 문자열, 숫자(count)와 제목(title)을 받아 해당 정보를 표시합니다.
- 두 줄로 구성된 수직 레이아웃을 구현하기 위해
Column
을 사용하며, 숫자와 제목은 각각 텍스트 위젯으로 표현됩니다.
buildLine 메서드:
_buildLine
메서드는 두 정보 항목 사이에 파란색 구분선을 표시하기 위한 메서드입니다.
- 구분선은
Container
로 정의되며, 2dp의 너비와 60dp의 높이를 가집니다. 이 선은 각 정보 항목을 구분하는 역할을 합니다.
이 위젯은 게시물 수, 좋아요 수, 공유 수와 같은 프로필 통계 정보를 깔끔하게 한 줄로 배치하는 데 사용됩니다.
3. Profile_drawer.dart
import 'package:flutter/material.dart';
class ProfileDrawer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 200,
height: double.infinity,
color: Colors.blue,
);
}
}


4. Profile_header.dart
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
children: [
SizedBox(width: 20),
_buildHeaderAvatar(),
SizedBox(width: 20),
_buildHeaderProfile(),
],
);
}
Widget _buildHeaderAvatar() {
return SizedBox(
width: 100,
height: 100,
child: CircleAvatar(
backgroundImage: AssetImage("assets/avatar.png"),
));
}
Widget _buildHeaderProfile() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"GetinThere",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w700,
),
),
Text(
"프로그래머/작가/강사",
style: TextStyle(
fontSize: 20,
),
),
Text(
"데어 프로그래밍",
style: TextStyle(
fontSize: 15,
),
),
],
);
}
}

코드설명
ProfileHeader
클래스는 프로필 헤더를 구성하는 Flutter 위젯입니다.- buildHeaderAvatar 메서드:
- 이 메서드는 원형 아바타를 생성하는 역할을 합니다.
SizedBox
로 아바타의 크기를 100x100dp로 설정하고,CircleAvatar
위젯을 사용해 이미지를 원형으로 표시합니다.AssetImage("assets/avatar.png")
는 로컬에 저장된 이미지 파일을 불러옵니다.
- _buildHeaderProfile 메서드:
- 프로필 정보를 표시하는 부분으로, Column 위젯을 사용하여 정보를 수직으로 나열합니다.
- 프로필 정보에는 세 가지 텍스트가 포함되며, 각각 이름("GetinThere"), 직업("프로그래머/작가/강사"), 소속("데어 프로그래밍")이 표시됩니다.
- 텍스트 스타일은 각 텍스트의 크기와 굵기를 달리하여 중요한 정보일수록 크고 굵게 표시합니다:
5. Profile_tab.dart
import 'package:flutter/material.dart';
class ProfileTab extends StatefulWidget {
@override
_ProfileTabState createState() => _ProfileTabState();
}
class _ProfileTabState extends State<ProfileTab>
with SingleTickerProviderStateMixin {
TabController? _tabController;
@override
void initState() {
super.initState();
_tabController = new TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
_buildTabBar(),
Expanded(child: _buildTabBarView()),
],
);
}
Widget _buildTabBar() {
return TabBar(
controller: _tabController,
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
],
); // end of TabBar
}
Widget _buildTabBarView() {
return TabBarView(
controller: _tabController,
children: [
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 10,
crossAxisCount: 3,
mainAxisSpacing: 10,
),
itemCount: 42,
itemBuilder: (context, index) {
return Image.network(
"https://picsum.photos/id/${index + 1}/200/200");
},
),
Container(color: Colors.red),
],
);
}
}

코드설명
ProfileTab
클래스는 탭(Tab)을 통해 두 개의 화면을 전환할 수 있는 구조로 구성된 Flutter 위젯입니다.- StatefulWidget 및 TabController:
ProfileTab
은 StatefulWidget으로, 탭 간의 전환을 관리하기 위해TabController
를 사용합니다.SingleTickerProviderStateMixin
을 사용하여 애니메이션 효과를 위한vsync
를 제공합니다.TabController
는 두 개의 탭을 관리하며,initState()
에서 초기화됩니다.
- TabBar:
_buildTabBar()
메서드는 탭을 표시하는 TabBar를 반환합니다. 두 개의 **아이콘(Tab)**이 탭바에 추가되며, 각각 차 아이콘과 대중교통 아이콘을 표시합니다.controller
로 TabController를 연결하여 탭 전환을 제어합니다.
- TabBarView:
- TabBarView는 각 탭에서 표시할 내용을 정의합니다.
controller
를 통해 탭 전환을 연결합니다. - 첫 번째 탭은 **그리드 뷰(GridView)**를 사용하여 이미지를 3개의 열로 배치합니다. 총 42개의 아이템을 표시하며,
picsum.photos
에서 이미지를 동적으로 불러옵니다. - 두 번째 탭은 빨간색 배경의 빈 컨테이너로 구성되어 있습니다.
- GridView.builder:
GridView.builder
는 그리드 형태로 아이템을 동적으로 생성합니다.SliverGridDelegateWithFixedCrossAxisCount
을 사용하여 3개의 열로 이미지를 나열하며, 가로 및 세로 간격을 10dp로 설정합니다.itemCount
는 42로, 총 42개의 이미지가 그리드로 표시됩니다.itemBuilder
는 각각의 이미지 항목을Image.network()
을 통해 URL로 이미지를 불러옵니다.
코드 흐름: 이 코드는 탭을 통한 화면 전환과 그리드 레이아웃을 조합하여 UI를 구성하는 좋은 예시입니다.
6. main.dart
import 'package:flutter/material.dart';
import 'package:profileapp1/components/profile_buttons.dart';
import 'package:profileapp1/components/profile_count_info.dart';
import 'package:profileapp1/components/profile_header.dart';
import 'package:profileapp1/components/profile_tab.dart';
import 'package:profileapp1/theme.dart';
import 'components/profile_drawer.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: theme(),
home: ProfilePage(),
);
}
}
class ProfilePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
endDrawer: ProfileDrawer(),
appBar: _buildProfileAppBar(),
body: Column(
children: [
SizedBox(height: 20),
ProfileHeader(),
SizedBox(height: 20),
ProfileCountInfo(),
SizedBox(height: 20),
ProfileButtons(),
// 남아 있는 세로 공간을 모두 차지하기 위해 Expanded를 준다.
Expanded(child: ProfileTab()),
],
),
);
}
AppBar _buildProfileAppBar() {
return AppBar(
leading: Icon(Icons.arrow_back_ios),
title: Text("Profile"),
centerTitle: true,
);
}
}

코드설명
Flutter 프로젝트의
ProfilePage
는 프로필 화면을 구성하는 레이아웃으로, 다양한 컴포넌트를 사용해 하나의 깔끔한 프로필 UI를 제공합니다.주요 컴포넌트:
ProfileHeader
:- 프로필 사진과 사용자 정보를 표시하는 프로필 헤더입니다.
ProfileHeader
는 이미 작성된 클래스(예: 아바타와 텍스트)를 통해 유저 이름과 직업 정보 등을 보여줍니다.
ProfileCountInfo
:- 게시물 수, 좋아요 수, 공유 수 등 프로필 통계를 나타내는 컴포넌트입니다. 수직으로 배치된 통계 정보와 이를 구분하는 라인이 함께 표시됩니다.
ProfileButtons
:- 팔로우 및 메시지 버튼을 표시하는 영역입니다.
Row
위젯을 사용하여 두 개의 버튼이 나란히 표시됩니다.
ProfileTab
:- 탭으로 구성된 프로필 상세 정보를 보여주는 컴포넌트입니다. 이 컴포넌트는 그리드 형태로 이미지를 표시하는 첫 번째 탭과, 간단한 컨테이너를 보여주는 두 번째 탭을 포함합니다.
ProfileDrawer
:- 화면의 오른쪽에서 슬라이드하여 나타나는 사이드바(drawer)입니다.
Scaffold
의endDrawer
속성으로 적용되며, 사용자가 메뉴를 열 수 있도록 구성되어 있습니다.
ProfilePage
레이아웃:
AppBar
:- 상단 앱바에는 뒤로 가기 버튼과
Profile
이라는 타이틀이 표시됩니다. 타이틀은 중앙에 위치하며, 아이콘과 텍스트는 기본적인 앱바 스타일을 따릅니다.
Column
레이아웃:Column
위젯을 사용하여 프로필 헤더, 통계, 버튼, 탭을 세로 방향으로 배치합니다.SizedBox
를 사용해 각 컴포넌트 사이에 일정한 간격을 추가합니다.- 마지막에
ProfileTab
을 Expanded 위젯으로 감싸서 남아 있는 공간을 모두 차지하도록 설정합니다.
최종 구조 설명:
- 이 레이아웃은 Flutter 앱에서 프로필 화면을 구성하는 매우 효율적인 구조로, 다양한 컴포넌트를 모듈화하여 재사용성을 높였습니다.
- 다양한 위젯을 조합해 프로필 관련 정보를 한 화면에 표시하면서도, 깔끔하게 각 요소 간의 간격과 정렬을 관리하고 있습니다.
이 전체 레이아웃은 유저 프로필 UI를 구성하는 데 필요한 여러 요소를 포함하며, 확장성을 고려해 컴포넌트가 각각 독립적으로 정의되어 유지보수와 기능 추가가 용이합니다.
Share article