티스토리 뷰
지금까지 Flutter의 기본 구성 요소들에 대하여 살펴보았으니, 간단하게 아주 기초적인 UI 프로젝트를 하나 만들어 보면서 화면 이동이나 화면 간에 데이터를 주고받는 연습을 좀 해보려고 한다.
아주 기본적인 list - detail 형태의 ui 프로젝트를 만들 것이기 때문에 따로 DB연결이나 기능에 대하여는 신경 쓰지 않는다.
바로 시작해보도록 하자.
우선, list와 detail에 모두 사용할 model을 하나 생성해보자.
◎lib > models > book.dart
class Book {
final String title;
final String subtitle;
final String description;
final String image;
Book({
required this.title,
required this.subtitle,
required this.description,
required this.image
});
}
다음으로 이 model 객체를 초기화하고 더미 데이터 생성 및 get 메서드를 제공할 repository 또한 생성한다.
◎lib > repositories > book_repository.dart
import '../models/book.dart';
class BookRepository {
final List<Book> _dummyBooks = [
Book(
title: 'MS 팀즈로 소통하고 오피스 365로 만드는 미래수업',
subtitle: '대충 부제',
description: '영화에서 자주 등장하는 히어로들은 위기 상황에서 기가 막힌 순발력을 발휘하여 위기를 극복한다. 교사들이 수업을 할 때도 생각치도 못한 위기 상황이 등장하기 마련이다. 다양한 수업 방법과 도구들로 무장한다면 누구나 영화 속 히어로들처럼 멋지게 수업을 이어갈 수 있는 교육의 히어로가 될 수 있다.',
image: 'https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIXFaT%2Fbtq3c9f4ZeP%2F02ZkK5m3omPEBt6FPgSBH1%2Fimg.png',
),
Book(
title: '아파치 카프카 애플리케이션 프로그래밍 with 자바',
subtitle: '대충 부제',
description: '영화에서 자주 등장하는 히어로들은 위기 상황에서 기가 막힌 순발력을 발휘하여 위기를 극복한다. 교사들이 수업을 할 때도 생각치도 못한 위기 상황이 등장하기 마련이다. 다양한 수업 방법과 도구들로 무장한다면 누구나 영화 속 히어로들처럼 멋지게 수업을 이어갈 수 있는 교육의 히어로가 될 수 있다.',
image: 'https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdI6o0h%2Fbtq2bILTJXb%2FUFqmeh0l8LqWfIdZPxk9uk%2Fimg.png',
),
Book(
title: '웹 디자인 & 웹 퍼블리싱을 위한 피그마 완벽 활용서',
subtitle: '대충 부제',
description: '영화에서 자주 등장하는 히어로들은 위기 상황에서 기가 막힌 순발력을 발휘하여 위기를 극복한다. 교사들이 수업을 할 때도 생각치도 못한 위기 상황이 등장하기 마련이다. 다양한 수업 방법과 도구들로 무장한다면 누구나 영화 속 히어로들처럼 멋지게 수업을 이어갈 수 있는 교육의 히어로가 될 수 있다.',
image: 'https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyvsr9%2Fbtq9t7p8rFt%2Fx98J2ZBgA6wuQZWUffvDUK%2Fimg.png', ),
Book(
title: 'Vue.js 프로젝트 투입 일주일 전',
subtitle: '대충 부제',
description: '영화에서 자주 등장하는 히어로들은 위기 상황에서 기가 막힌 순발력을 발휘하여 위기를 극복한다. 교사들이 수업을 할 때도 생각치도 못한 위기 상황이 등장하기 마련이다. 다양한 수업 방법과 도구들로 무장한다면 누구나 영화 속 히어로들처럼 멋지게 수업을 이어갈 수 있는 교육의 히어로가 될 수 있다.',
image: 'https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGOxQ8%2Fbtq6imQpvmA%2FEY3gKphHOPQbk8KT5FOm8K%2Fimg.jpg', ),
];
List<Book> getBooks() {
return _dummyBooks;
}
}
book 객체는 위와 같이 제목, 부제, 설명, 이미지 URL로 4개의 string data를 가지고 있으며, 간단하게 더미 데이터까지 생성을 했다.
이제 ListView를 사용한 리스트 형태의 첫번째 화면을 구성한 뒤 main.dart가 해당 화면을 띄우도록 설정해야 한다.
◎lib > screens > list_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_book_list/repositories/book_repository.dart';
import 'package:flutter_book_list/screens/detail_screen.dart';
import '../models/book.dart';
class BookTile extends StatelessWidget {
final Book book;
BookTile({
required this.book
});
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(book.title),
leading: Image.network(book.image),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DetailScreen(
book: book
)
),
);
}
);
}
}
class ListScreen extends StatelessWidget {
final List<Book> books = BookRepository().getBooks();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('도서 목록 앱'),
),
body:
ListView.builder(
itemCount: books.length,
itemBuilder: (context, index) {
return BookTile(book: books[index]);
},
)
);
}
}
ListView에서 사용하는 ListTile 부분을 BookTile이라는 클래스를 하나 생성하여 해당 객체가 Book을 받아서 ListItem을 하나하나 구성하도록 작성하였다.
ListTile의 onTap 함수안에 화면 이동을 위한 코드를 작성하여 각 리스트 아이템을 터치하면 상세 보기 페이지로 Book 데이터와 함께 넘어간다.
◎lib > screens > detail_screen.dart
import 'package:flutter/material.dart';
import '../models/book.dart';
class DetailScreen extends StatelessWidget{
final Book book;
DetailScreen({
required this.book,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(book.title),
),
body: Column(
children: [
Image.network(
book.image
),
Padding(padding: EdgeInsets.all(3)),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: MediaQuery.of(context).size.width * 0.8,
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Text(
book.title,
style: TextStyle(
fontSize: 23,
fontWeight: FontWeight.bold,
),
),
),
Text(
book.subtitle,
style: TextStyle(fontSize: 18, color: Colors.grey),
)
],
),
),
Container(
width: MediaQuery.of(context).size.width * 0.15,
padding: EdgeInsets.all(10),
child: Icon(
Icons.star,
color: Colors.red,
),
)
],
),
Padding(padding: EdgeInsets.all(3)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Icon(
Icons.call,
color: Colors.blue,
),
Text(
'Contact',
style: TextStyle(color: Colors.blue),
)
],
),
Column(
children: [
Icon(
Icons.near_me,
color: Colors.blue,
),
Text(
'Contact',
style: TextStyle(color: Colors.blue),
)
],
),
Column(
children: [
Icon(
Icons.save,
color: Colors.blue,
),
Text(
'Contact',
style: TextStyle(color: Colors.blue),
)
],
),
],
),
Container(
padding: EdgeInsets.all(15),
child: Text(
book.description
),
)
],
)
);
}
}
detail 부분이 아이콘이나 설명이 들어가 조금 코드가 복잡해 보일 수는 있으나, 한번 쭉 확인해보면 row와 column을 사용하여 레이아웃을 적절하게 구성한 내용이 전부이다.
Container의 너비는
MediaQuery.of(context).size.width
를 사용하여 단말에 맞는 너비를 동적으로 조절할 수 있게끔 작성이 되어 있다.
그 외에는 따로 어려운 내용은 없으니, 이제 아래와 같이 list_screen을 main.dart에 띄워주고 실행해보자.
◎main.dart
import 'package:flutter/material.dart';
import 'package:flutter_book_list/screens/list_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Book List App',
home: ListScreen(),
);
}
}
디자인은 조금 투박하지만, 이 간단한 프로젝트를 구성하면서 Flutter가 얼마나 편리한지 확실하게 체감했다.
위 실행 화면에서 볼 수 있듯, 뒤로가기 기능은 따로 레이아웃을 작성하지도, 그 기능을 넣지도 않았는데 push로 넘어온 화면에서 다시 돌아가는 기능을 자동으로 지원한다.
UI 워낙 이미 만들어져있는 형태가 많아서 그리 복잡하지 않은 형태의 어플이라면 개발 시간을 획기적으로 줄일 수 있을 거 같다.
다음 포스팅에서는 State를 활용한 간단한 프로젝트를 만들어 보려고 한다.
끝!!
'Projects' 카테고리의 다른 글
[Flutter] Data Project: Todo List with Firebase (0) | 2022.07.22 |
---|---|
[Flutter] Data Project: Todo List with SQLite (0) | 2022.07.21 |
[Flutter] Simple State 프로젝트: Poromodo Timer (0) | 2022.07.14 |
[Spring Boot] 심부름 중계 플랫폼: Hermes (0) | 2022.04.17 |
[Web-MVC] Web Service: My pet diary (0) | 2021.06.04 |
- Promise
- 맛집
- redux
- AsyncStorage
- Async
- redux-thunk
- react
- 이탈리안 레스토랑
- javascript
- 정보보안기사 #실기 #정리
- await
- 인천 구월동 이탈리안 맛집
- 인천 구월동 맛집
- react-native
- 파니노구스토
- Total
- Today
- Yesterday