1. RecipeTitle 커스텀 위젯 만들기
- 모든 위젯에는 제약 조건이 있음
- 컬럼의 부모가 바디 → 바디는 기계마다 다름
- 바디의 크기는 앱바 바로 밑에서 끝까지 = html의 바디와 동일
- 바디 안에 컬럼이 있음
- 컬럼의 제약 조건
- 화면의 크기가 바껴도 재사용 가능함
끝까지 늘어나는데 감싸는 컨테이너를 만들면 크기를 조절할 수 있음
double.infinity // 부모의 크기까지 늘어남
2. 현재 뷰 확인하기
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import '../components/recipe_body.dart'; class RecipePage extends StatelessWidget { const RecipePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: _appbar(), body: RecipeBody(), ); } AppBar _appbar() { return AppBar( actions: [ Icon(CupertinoIcons.search), // 시그니처로 키 값 없음 SizedBox(width: 15), Icon( CupertinoIcons.heart, color: Colors.redAccent, ), SizedBox(width: 15), ], ); } }
3. Align으로 정렬하기
- ListView는 따로 정렬 키워드를 제공해주지 않음
import 'package:flutter/cupertino.dart'; import 'package:recipe_app2/components/recipe_menu.dart'; import 'package:recipe_app2/components/recipe_title.dart'; class RecipeBody extends StatelessWidget { const RecipeBody({ super.key, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 30), child: ListView( children: [ Align( alignment: Alignment.center, child: RecipeTitle()), RecipeMenu(), ], ), ); } }
- Align 사용하기 전 상황
@override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(top: 20), child: Row( //1. 메뉴 아이템들의 방향이 수평 방향이기 때문 mainAxisAlignment: MainAxisAlignment.end, children: [ _buildMenuItem(Icons.food_bank, "ALL"), // 2. 재사용 SizedBox(width: 25), _buildMenuItem(Icons.emoji_food_beverage, "Coffee"), // 3. 재사용 SizedBox(width: 25), _buildMenuItem(Icons.fastfood, "Burger"), // 4. 재사용 SizedBox(width: 25), _buildMenuItem(Icons.local_pizza, "Pizza"), // 5. 재사용 ], ), ); }
4. 이미지와 텍스트 넣기
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:recipe_app2/components/recipe_menu.dart'; import 'package:recipe_app2/components/recipe_title.dart'; class RecipeBody extends StatelessWidget { const RecipeBody({ super.key, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: ListView( children: [ RecipeTitle(), RecipeMenu(), SizedBox( width: double.infinity, child: Column( children: [ Image.asset("assets/images/coffee.jpeg", fit: BoxFit.cover), Text("Coffee", style: TextStyle(fontSize: 20)), Text( "Have you ever made your own Coffee? Once you've tried a homemade Coffee, you'll never go back.", style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), ) ], ), ); } }
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:recipe_app2/components/recipe_menu.dart'; import 'package:recipe_app2/components/recipe_title.dart'; Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: ListView( children: [ RecipeTitle(), RecipeMenu(), RecipeListItem(), ], ), ); } } class RecipeListItem extends StatelessWidget { const RecipeListItem({ super.key, }); @override Widget build(BuildContext context) { return SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset("assets/images/coffee.jpeg", fit: BoxFit.cover)), Text("Coffee", style: TextStyle(fontSize: 20)), Text( "Have you ever made your own Coffee? Once you've tried a homemade Coffee, you'll never go back.", style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), ); } }
- 사진 모서리 라운딩하기
- aspectRatio로 비율을 이용한 크기 조절하기!!
import 'package:flutter/material.dart'; import 'package:recipe_app2/components/recipe_menu.dart'; import 'package:recipe_app2/components/recipe_title.dart'; class RecipeBody extends StatelessWidget { const RecipeBody({ super.key, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: ListView( children: [RecipeTitle(), RecipeMenu(), RecipeListItem()], ), ); } SizedBox RecipeListItem() { return SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AspectRatio( aspectRatio: 1 / 2, // 비율로 조절하기 child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset("assets/images/coffee.jpeg", fit: BoxFit.cover)), ), Text("Coffee", style: TextStyle(fontSize: 20)), Text( "Have you ever made your own Coffee? Once you've tried a homemade Coffee, you'll never go back.", style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), ); } }
- 나머지 이미지도 넣어주기
- 사진이름과 사진 타이틀을 변수로 사용하기
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:recipe_app2/components/recipe_menu.dart'; import 'package:recipe_app2/components/recipe_title.dart'; class RecipeBody extends StatelessWidget { const RecipeBody({ super.key, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: ListView( children: [ RecipeTitle(), RecipeMenu(), RecipeListItem(imgName: "coffee.jpeg", title: "Coffee"), RecipeListItem(imgName: "pizza.jpeg", title: "Pizza"), RecipeListItem(imgName: "burger.jpeg", title: "Burger"), ], ), ); } } class RecipeListItem extends StatelessWidget { final imgName; final title; const RecipeListItem({required this.imgName, required this.title}); @override Widget build(BuildContext context) { return SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AspectRatio( aspectRatio: 2 / 1, child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset("assets/images/${imgName}", fit: BoxFit.cover), ), ), Text("Coffee", style: TextStyle(fontSize: 20)), Text( "Have you ever made your own ${title}? Once you've tried a homemade ${title}, you'll never go back.", style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), ); } }
- for문 돌리기
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:recipe_app2/components/recipe_menu.dart'; import 'package:recipe_app2/components/recipe_title.dart'; Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: ListView( children: [ RecipeTitle(), RecipeMenu(), RecipeListItem(title: "coffee",), RecipeListItem(title: "pizza",), RecipeListItem(title: "burger",), ], ), ); } class RecipeListItem extends StatelessWidget { final title; // 편하게 해보려고 한개만 받음 const RecipeListItem({required this.title}) @override Widget build(BuildContext context) { return SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset("assets/images/${title}.jpeg", fit: BoxFit.cover)), Text("Coffee", style: TextStyle(fontSize: 20)), Text( "Have you ever made your own ${title}? Once you've tried a homemade ${title}, you'll never go back.", style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), ); } }
list.map((e) =>RecipeListItem(title: e)).toList() // 하나만 할 때는 가능
import 'package:flutter/material.dart'; import 'package:recipe_app2/components/recipe_menu.dart'; import 'package:recipe_app2/components/recipe_title.dart'; class RecipeBody extends StatelessWidget { RecipeBody({ super.key, }); final list = ["coffee", "pizza", "burger"]; // List<String> 타입 @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: ListView( children: [ RecipeTitle(), RecipeMenu(), // list.map((e) =>RecipeListItem(title: e)).toList() // 하나만 할 때는 가능 for(String text in list) RecipeListItem(title: text), ], ), ); } } class RecipeListItem extends StatelessWidget { final title; const RecipeListItem({required this.title}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(top: 25), child: SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AspectRatio( aspectRatio: 2 / 1, child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Image.asset("assets/images/${title}.jpeg", fit: BoxFit.cover), ), ), Text("${title}", style: TextStyle(fontSize: 20)), Text( "Have you ever made your own ${title}? Once you've tried a homemade ${title}, you'll never go back.", style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), ), ); } }
Share article