Youtube 코딩셰프님의 강의를 요약 정리한 글이다. dart 언어나 이론 부분은 자바와 유사하여 대부분 제외하였고, flutter 기초 위주로 정리한다.
https://www.youtube.com/@codingchef
in-app background image reference : https://wallpapercave.com/cartoon-chickens-wallpapers
이제 로그인 및 채팅이 가능한 채팅앱을 만든다. 이번 글에서는 UI 만들기에 집중한다. 강의에서 설명하는 것처럼 UI 작성에 익숙해지기 위한 과정으로 최대한 리팩토링을 자제하고 하나의 파일에 쭉 이어서 만든다. 앞서 배웠던 부분들도 활용하겠지만, 주로 새로 나온 부분들을 위주로 정리해놓는다.
1. 전체 구조
디렉토리 구조
아래사진 처럼 구성한다.
palette, painting.dart
여러 색깔 값들을 참고하기 위해서 lib/config/palette.dart 파일을 만들고 아래 코드들을 추가한다. 여기서 import 하는 painting.dart는 나중에 login_screen 에서도 추가해서 BorderRadius, BoxDecoration 등 다양한 UI관련 위젯들을 활용하게 된다. 자세한 내용은 아래 링크에서 볼 수 있다.
https://api.flutter.dev/flutter/painting/painting-library.html
import 'package:flutter/painting.dart';
class Palette{
static const Color iconColor = Color(0xFFB6C7D1);
static const Color activeColor = Color(0xFF09126C);
static const Color textColor1 = Color(0XFFA7BCC7);
static const Color textColor2 = Color(0XFF9BB3C0);
static const Color facebookColor = Color(0xFF3B5999);
static const Color googleColor = Color(0xFFDE4B39);
static const Color backgroundColor = Color(0xFFECF3F9);
}
main_screen 기본 구조
아래 코드 구조로 쌓아나간다. LoginSignupScreen을 main.dart에서 MaterialApp의 home:에 등록한다. 그리고 Scaffold의 body에는 Stack을 만들어서 여러 위젯들을 쌓아나가는 형태로 만들 것이다.
그리고 사용자가 화면상의 요소들을 탭 했을 때 어떤 동작의 기준이 될 수 있도록 isSignupScreen 변수값도 초기화해주었다.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../config/palette.dart';
class LoginSignupScreen extends StatefulWidget {
const LoginSignupScreen({Key? key}) : super(key: key);
@override
State<LoginSignupScreen> createState() => _LoginSignupScreenState();
}
class _LoginSignupScreenState extends State<LoginSignupScreen> {
bool isSignupScreen = true;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Palette.backgroundColor,
body: Stack(
children: [
],
)
);
}
}
2. Background: Image, Text
Positioned
Stack 위에 위치를 조정할 수 있고, 나중에는 애니메이션 기능을 가진 위젯으로 전환할 수 있는 Positioned 위젯으로 위젯들을 쌓아나간다.
신규 인자값 및 위젯들
- decoration: BoxDecoration
- DecorationImage
- BoxFit.cover
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Palette.backgroundColor,
body: Stack(
children: [
Positioned(
top: 0,
right: 0,
left: 0,
child: Container(
height: 300,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('image/background_image.jpeg'),
fit: BoxFit.cover,
opacity: 0.7
)
),
)
)
],
)
);
텍스트 표현: RichText, TextSpan
child: Container(
padding: EdgeInsets.only(top: 90, left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
text: 'Welcome',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 25,
color: Colors.black
),
children: [
TextSpan(
text: ' to Chicken Chat',
style: TextStyle(
letterSpacing: 1.0,
fontSize: 25,
color: Colors.black,
fontWeight: FontWeight.bold
),
)
]
),
)
],
),
),
Container의 child로 또 다른 Container를 삽입 후, padding 및 Text들을 추가했다.
- RichText: 폰트, 크기와 특징이 다른 텍스트들을 한 번에 표현하고 싶을 때 사용. children 인자를 받아와서 또 다른 TextSpan을 추가하는 방식으로 사용한다.
- TextSpan: 텍스트나 문단을 모아서 구성할 수 있다.
아래 그림을 보면 RichText 바깥쪽에(Column의 children 부분) SizedBox와 Text를 추가하여 signup to continue 라는 문구를 다른 줄에 표기해주었다.
위젯 정리
다른 위젯 작업을 위해 Positioned 위젯을 cmd + . 키를 누르거나 왼쪽 bar의 -버튼을 눌러 축소해놓는다. 그리고 구분을 위해 주석을 달아놓는다.
3. Login, Signup 골격 만들기
BoxDecoration, MediaQuery
Positioned 위젯을 추가하고 BoxDecoration으로 Box형태를 만든다.
body: Stack(
children: [
Positioned(...),//background,
Positioned(
top: 180,
child: Container(
height: 280.0,
width: MediaQuery.of(context).size.width-40,
margin: EdgeInsets.symmetric(horizontal: 20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 15,
spreadRadius: 5
)
]
),
)
)
],
)
MediaQuery.of(context).size.width 로 기기나 View 환경에 상관없이 사용자가 보는 화면의 가로 너비값을 구해올 수 있다.
BoxDecoration으로 Box 형태를 만들고, BorderRadius, BoxShadow 값을 줄 수 있다.
LOGIN, SIGNUP 버튼 만들기 : GetstureDetector, setState
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
GestureDetector(
onTap: () {
setState(() {
isSignupScreen = false;
});
},
child: Column(
children: [
Text('LOGIN',
style: TextStyle(
color: !isSignupScreen? Palette.activeColor : Palette.textColor1,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 5.0,
),
Container(
height: 2.0,
width: 50.0,
color: Colors.brown,
)
],
),
Row와 Column을 반복되는 트리구조로 만들어서 LOGIN, SIGNUP 버튼을 만든다. 새로 배운 사항들은 다음과 같다.
- Container 자체로 밑줄 효과를 만들 수 있다.
- 텍스트 디자인을 다 해놓고, Column 위젯을 GestureDector로 감싸서 setState 처리한다.
*spaceBetween, spaceAround, spaceEvenly 차이
모두 다 각 요소간 간격을 동일하게 맞추지만, between은 양 끝 요소의 바깥쪽 여백이 남지 않게, around는 양 끝 요소의 바깥쪽 여백이 간격의 절반만큼만 되도록, evenly는 양 끝 요소의 바깥쪽 여백이 간격과 같게 맞춘다.
삼항연산자 적용
마지막으로 삼항연산자를 적용하여 각 위젯의 color를 바꿀 수 있다. LOGIN 위젯 부분을 클릭했을 때는 isSignupScreen 변수 앞에 !를 붙여서 부정을 해줬다. SIGNUP 위젯에는 반대로 적용해주면 된다!
'Programming-[CrossPlatform] > Flutter' 카테고리의 다른 글
Flutter 기본-17. 채팅앱 - 로그인 Validation (0) | 2023.02.07 |
---|---|
Flutter 기본-16. 채팅앱 - TextFormField, inline if, AnimatedPositioned (0) | 2023.02.05 |
Flutter 기본-14. 날씨 앱 만들기 데이터, 이미지 연동, Key 개념 이해하기 (0) | 2023.02.03 |
Flutter 기본-13. 날씨 앱 만들기 기본3, UI 구성 실습 (0) | 2023.01.29 |
Flutter 기본-12. 날씨 앱 만들기 기본2 (0) | 2023.01.28 |