음료 이미지는 CircleAvatar를 사용하며 48의 반지름크기를 갖는다.
음료 영문명의 font size는 14pt이며 회색으로 w200의 굵기를 가진다.
음료의 정보를 보여주는 위젯을 만들고, 이름은 DrinkTile로 한다.
골든 미모사 그린 티, Golden Mimosa Green Tea
블랙 햅쌀 고봉 라떼, Black Rice Latte
아이스 블랙 햅쌀 고봉 라떼, Iced Black Rice Latte
스타벅스 튜메릭 라떼, Starbucks Turmeric Latte
아이스 스타벅스 튜메릭 라떼, Iced Starbucks Turmeric Latte
일단 Appbar에 text가 없이, icon이 2개다.
머터리얼 디자인 아이콘
ListView로 스크롤 가능하도록 해야할 것 같다.
ListTile로 각 메뉴들을 나타내면 될 것 같고(커스텀)
주문할 매장 선택하는 부분은... floatBtn을 활용할 수 있는 방법이 있지 않을까?
BottomNavigationBarItem이 5개.
이미지를 leading에 CircleAvater로 줬는데, 이미지 크기가 조절이 안됐다.
이미지 크기는 커지는데, 동그라미가 안커짐...
ListTile 대신 Row로 만들어야 할 듯.
화면에 안보여서 뭔가 했더니 투명해짐.
type: BottomNavigationBarType.fixed
추가해 해결.
참고할만한 게 있을까 싶어서 머터리얼 디자인 컴포넌트를 살펴봤다.
그리고 Sheet: bottom을 발견.
플러터에서 후딱 sheet를 써보니 bottomSheet라는 게 있다.
처음엔 그냥 name, url 이런식으로 변수명을 짓는 실수를.. 했다.
나는 모 drinkTile이라는 객체 내에서 생성되는 변수니까 괜찮을 줄 알았지?
그런데 예약어라서 에러가 났다. 이름짓기 조심할것!
import 'package:flutter/material.dart';
class DrinkTile extends StatelessWidget {
const DrinkTile(
{super.key,
required this.enName,
required this.price,
required this.korName,
required this.drinkUrl});
final String korName;
final String enName;
final String price;
final String drinkUrl;
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8),
child: Row(
children: [
CircleAvatar(
backgroundImage: AssetImage(drinkUrl),
radius: 35,
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 8, 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
korName,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text(
enName,
style: const TextStyle(color: Colors.black26),
),
Text(
price,
style: const TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
),
],
),
),
],
),
);
}
}
DrinkTile(
korName: '골든 미모사 그린 티',
enName: 'Golden Mimosa Green Tea',
price: "6100원",
drinkUrl: 'assets/item_drink1.jpeg',
),
text + icon 조합이므로 ListTile 위젯을 사용했다.
bottomSheet: const ListTile(
tileColor: Colors.black87,
textColor: Colors.white,
title: Text(
"주문할 매장을 선택해 주세요.",
style: TextStyle(fontSize: 14),
),
trailing: Icon(
Icons.expand_more,
color: Colors.white,
),
),
Text(
'$price원',
style: ...
)
BottomNavigationBar(
currentIndex: 2,
)
symmetric
Padding(
padding: EdgeInsects.symmetric(horizontal: 16),
)
Quiz. BottomNavigationBar 위젯을 활용하여 다음과 같은 UI를 구성하려고 할 때 items가 3개를 넘으면 구현이 되지 않는 이유를 적고 어떻게 해결하였는지 제출하세요.
이 위젯의 타입을 따로 지정하지 않으면 항목이 4개 미만인 경우 자동으로 BottomNavigationBarType.fixed로 설정되고, 그렇지 않은 경우 BottomNavigationBarType.shifting으로 설정된다.
후자의 경우 selectedItemColor가 null이면 모든 항목이 흰색으로 렌더링된다.
이 위젯을 사용하려면 item을 2개이상 5개 이하로 사용하는 것을 권장한다.
selectedItemColor만 설정하고 fixed하지 않았을때는 선택된 아이템만 지정된 색으로 나오고, 나머지는 흰색으로 보인다.
플러터 문서
The bottom navigation bar's type changes how its items are displayed. If not specified, then it's automatically set to BottomNavigationBarType.fixed when there are less than four items, and BottomNavigationBarType.shifting otherwise.
너비가 고정된 네비게이션 바.
너비가 고정되지 않고 탭 하면 위치 및 크기가 변화되는 네비게이션 바.
bakcgroundColor와 unSelectedItemColor를 설정해주지 않으면 흰색으로 나온다.
shifting일때는 선택되지 않은 상태일 때 label이 안나오다가, 선택하면 label이 슝 하고 나오면서 아이템이 움직인다.
BottomNavigationBar(
type: BottomNavigationBarType.shifting,
selectedItemColor: Colors.green,
unselectedItemColor: Colors.blue,
currentIndex: 3,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.credit_card),
label: 'Pay',
),
BottomNavigationBarItem(
icon: Icon(Icons.coffee),
label: 'Order',
),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_basket),
label: 'Shop',
),
..생략
],
),
Come with me - Surfaces 및 salem ilese
Good day - Surfaces
Honesty - Pink Sweat$
I Wish I Missed My Ex - 마할리아 버크마
Plastic Plants - 마할리아 버크마
Sucker for you - 맷 테리
Summer is for falling in love - Sarah Kang & Eye Love Brandon
These days(feat. Jess Glynne, Macklemore & Dan Caplen) - Rudimental
You Make Me - DAY6
Zombie Pop - DRP IAN
Icon, Text, Icon, Icon
ListTile 쓰고,
leading: Image(songTitle),
subtitle: Icon + Text(time)
[ Col < Row < Image,
Col < Text(songTitle), Text(singer),
Col < Icon(Icons.play_arrow), Icon(Icons.skip_next),
< 여기에 라인을 넣을 예정.
]
BottomNavigationBarItem * 3개!
거의 시작과 동시에 theme먼저 찾아봤다.
매 위젯에 컬러와 백그라운드를 줄 수는 없지
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.black,
textTheme: const TextTheme(
bodyMedium: TextStyle(
color: Colors.white,
),
),
),
구글링해서 위와같이 적었는데, 과제풀이 강의를 들으니...^^ 저거 한줄로 끝나더라. 그런데 이상하게도 body에는 색이 black이 되지 않아서 MusicTile에 따로 컬러를 주었다.
colorScheme: const ColorScheme.dark(),
앱바를 잘 보면 border bottom이 있다.
방법이 두가지 있는데, bottom 속성을 사용하는것과 shape 속성을 사용하는 것이다.
AppBar(
// 방법1
bottom: PreferredSize(
preferredSize: const Size.fromHeight(1),
child: Container(
color: Colors.white,
height: 1,
),
),
...생략
AppBar(
// 방법2
shape: const Border(
bottom: BorderSide(
color: Colors.white24,
width: 1,
),
),
가수명이 제일 중요한 요소기 때문에 길면 긴대로 공간을 최대한 차지해야 한다.
필자는 Text에 overflow를 줬지만... 기대한대로 작동하지 않았다.
Flexible을 감싸서 이 위젯이 유동적으로 작동해야 함을 명시해야 한다.
기본적으로 위젯들은 최대한의 공간을 차지하려고 하기 때문.
이 위젯은 부모위젯이 Row라 가로로 계쏙 확장하려고 한다.
mainAxisSize도 그처럼 최소한의 공간, 즉 컨텐츠만큼의 공간을 차지하도록 하는 요소이다.
class MusicTile extends StatelessWidget {
const MusicTile({
super.key,
required this.albumCover,
required this.songTitle,
required this.artist,
required this.duration,
});
final String albumCover;
final String songTitle;
final String artist;
final String duration;
Widget build(BuildContext context) {
return ListTile(
tileColor: Colors.black54,
leading: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.asset(
albumCover,
),
),
title: Text(
songTitle,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 18,
),
),
subtitle: Row(
children: [
const Icon(
Icons.check_circle,
size: 16,
),
const SizedBox(width: 4),
Flexible(
child: Text(
artist,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 4),
const Icon(
Icons.fiber_manual_record,
size: 5,
),
const SizedBox(width: 4),
Text(duration),
],
),
trailing: const Icon(Icons.more_vert),
);
}
}
* 컨텐츠만큼의 크기만큼 공간 차지하도록 하기:
mainAxisSize: MainAxisSize.min
Column(
mainAxisSize: MainAxisSize.min,
children: [
// 재생중인 노래
ListTile(
tileColor: const Color(0xff2a2a2a),
leading: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.asset("assets/music_you_make_me.png"),
),
title: const Text(
"You Make Me",
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 18,
),
),
subtitle: const Row(
children: [
Flexible(
child: Text(
"Day6",
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
SizedBox(width: 4),
],
),
trailing: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.play_arrow,
),
Icon(
Icons.skip_next,
),
],
),
),
// 재생바
Container(
height: 1,
color: Colors.white24,
alignment: Alignment.centerLeft,
child: Container(
width: 14,
color: Colors.white,
),
),
],
),
아 강의 다듣고 과제 다 하는데 정규 시간보다 한시간이 더 걸렸다.
오늘 공부하기 싫다고 다른 팀원분이랑 멘토님들이랑 놀긴 했는데... 휴
낼은 더 어렵다는데 농땡이피지 말아야겠다....
본 후기는 유데미-스나이퍼팩토리 9주 완성 프로젝트캠프 학습 일지 후기로 작성 되었습니다.