Swift로 네이티브 앱 개발을 주력으로 하다가 팀 프로젝트에서 하이브리드 앱을 만들 필요성이 생겨 그토록 미뤄왔던 flutter를 시작한다. 코드 위주로 작성을 하고, 필요한 개념들만 간단히 정리할 계획이다. 이미 시중에 플러터 관련 코드가 많지만, 내가 찾아보기엔 iOS cupertino design 기반의 예제 코드가 부족해 보여, 기존의 material design 코드를 iOS 느낌으로 전환하는 방식으로 작성해본다.
1. Hello World
import 'package:flutter/cupertino.dart';
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
child: Center(
child: Text(
'Hello World.',
),
)
),
),
);
}
모든 컴공과의 기본. 어딜 가든 일단 Hello World부터 시작하자. iOS 디자인을 위해 CupertinoApp을 사용하였고, 가운데에 'Hello World.'를 표현해 보았다.
2. NavigationBar
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: Center(
child: Text(
'Hello World.'
),
),
),
),
);
}
화면 상단에 내비게이션 바를 구현해 보자. 안드로이드의 Appbar가 아닌 CupertinoNavigationBar를 사용하고, 가운데에 'Welcome to Flutter'라는 글씨를 넣어보았다.
3. child, children, Container
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: SafeArea(
child: Column( // Row는 가로로 쌓는다
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
color: CupertinoColors.systemRed,
width: 100,
height: 100,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
),
Container(
color: CupertinoColors.systemGreen,
width: 100,
height: 100,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
),
Container(
color: CupertinoColors.systemBlue,
width: 100,
height: 100,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
),
],
),
),
),
),
);
}
(체인 방식의 dart 언어는 가독성이 좋긴 한데, 코드 수정할 때 들여 쓰기 위치를 찾는 데에 번거로움이 있다. 뭔가 팁이 있을 듯한데..)
child는 단일 객체를 뜻한다. 이 안에는 위젯 하나만 들어갈 수 있다. 반면에 children에는 여러 위젯이 들어갈 수 있다. container는 화면 구성을 위해 넣는 빈 박스를 의미한다. 패딩을 주거나 해당 위치에 배경색을 주거나 하는 방식으로 쓰일 수 있다.
mainAxisSize: MainAxisSize.max
주축의 사이즈를 설정한다. Column 위젯 내에 있으므로 세로축을 의미한다. 현재는 세로 축의 최대 사이즈로 크기를 설정했다.
mainAxisAlignment: MainAxisAlignment.center
주축의 정렬을 선택한다. 가운데 정렬을 했다.
crossAxisAlignment: CrossAxisAlignment.center
교차축 (가로면 세로축, 세로면 가로축)의 정렬을 선택한다. 가운데 정렬을 했다. 하나 Width의 최대 사이즈를 정해주지 않았으므로 이는 동작하지 않는다. 만약 Column을 Row로 바꾼다면 해당 코드로 인해 생성한 박스 세 개는 가로축으로 가운데 정렬을 이룰 수 있다.
4. Text custom, alignment
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: Text(
'Hello World',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w700,
color: CupertinoColors.systemBlue,
),
),
),
)
),
)
);
}
단조로운 text에 스타일을 추가할 수 있다. 크기와 굵기, 그리고 색상을 설정해 주었다. 특히 색상 부분은 Material design에서는 Colors를 쓰기 때문에 차이를 기억해 두면 좋다 (쿠퍼티노 디자인에서도 사용 가능함).
위젯의 레이아웃을 정렬하는 방법은 다양하다. alignment의 값을 아래 값들 중 하나로 설정해 주면 쉽게 변경된다. 위 코드에서는 NavigationBar를 설정해 두었기 때문에 SafeArea로 감싸주지 않으면 Hello World가 그 밑으로 배치되어 글이 안 보일 수도 있으니 조심하도록 하자.
5. button
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: ElevatedButton(
onPressed: () {
print('Click');
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
),
child: Text(
'button',
style: TextStyle(
color: CupertinoColors.white,
),
)
)
),
)
),
)
);
}
다음으로는 버튼 위젯이다. Button을 쳐보면 엄청 많은 종류의 버튼이 존재하지만, 자주 사용하는 버튼은 TextButton, OutlinedButton, ElevatedButton, IconButton 등이 있다. 각각의 버튼마다 디자인이 조금씩 다르니 하나씩 써보면서 모양을 봐보자.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; // for Icon
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(top: 8.0), // 여백 추가
child: CircleAvatar(
backgroundColor: CupertinoColors.systemBlue,
child: IconButton(
onPressed: () {
print('click');
},
color: CupertinoColors.white,
icon: Icon(
Icons.home,
),
),
),
),
),
),
),
),
);
}
아이콘 버튼을 넣었을 때에는 아이콘을 넣을 버튼의 모양과 배경색, 그리고 아이콘의 모양을 설정해줘야 하므로 좀 더 코드가 길어진다. 또 여백을 주지 않으면 내비게이션 바에 딱 붙어버리기에 보기 좋게 Padding 위젯으로 한번 감싸서 8의 여백을 주었다.
6. GestureDetector
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Align(
alignment: Alignment.topCenter,
child:GestureDetector(
onTap: () {
print('on tap');
},
onDoubleTap: () {
print('on double tap');
},
onLongPress: () {
print('on long press');
},
child: Container(
decoration: BoxDecoration(
color: CupertinoColors.systemRed,
),
width: 100.0,
height: 100.0,
),
),
),
),
),
),
),
);
}
제스처이다. 버튼이 아니라 객체 위에서 여러 제스처를 감지할 수 있다. 예시에서는 빨간 컨테이너에 클릭, 더블 클릭, 꾹 누르기 제스처를 추가하고 해당 제스처에 맞는 로그를 찍는 태스크를 구현해 보았다. 아래와 같이 모든 제스처에 대해 잘 나오는 것을 확인할 수 있다.
7. Flexible
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: SafeArea(
child: Center(
child: Column(
children: [
Flexible(
flex: 2,
child: Container(
color: Colors.blue,
),
),
Flexible(
flex: 1,
child: Container(
color: Colors.red,
),
)
],
),
),
),
),
),
);
}
다음으로는 flexible widget이다. flexible 위젯은 남은 공간을 비율별로 차지한다. 이해를 위해 파란 컨테이너와 빨간 컨테이너를 children 위젯으로 감싸서 Column 방향으로 2:1로 배치해 보았다.
8. Expanded
Expanded(
child: Container(
color: CupertinoColors.activeOrange,
),
expanded 위젯은 Row/Column 위젯에서 모든 위젯들을 배치하고 남은 영역에 해당하는 부분을 사용한다. 3번 예제 코드에서 children 위젯 내에 마지막 요소로 위 코드를 추가해 주면 아래와 같은 화면 배치를 가질 수 있다.
9. Stack
void main() {
runApp(
CupertinoApp(
home: CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Welcome to Flutter'),
),
child: SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: Stack(
alignment: Alignment.center,
children: [
Container(
height: 300.0,
width: 300.0,
color: CupertinoColors.systemGreen,
),
Container(
height: 250.0,
width: 250.0,
color: CupertinoColors.activeBlue,
),
Container(
height: 200.0,
width: 200.0,
color: CupertinoColors.white,
),
Container(
child: Text(
'iOS',
),
)
],
),
),
),
),
),
);
}
마지막으로 stack 위젯이다. 화면 위로 (z axis) 쌓아 올리는 방식인데, children 요소에서 첫 번째 요소부터 아래에 깔리기 때문에 요소의 순서가 중요하다. 가운데 정렬로 색이 다르게 배치해 보았다.
'Dev > flutter' 카테고리의 다른 글
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (5) - STT, TTS (2) | 2024.08.08 |
---|---|
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (4) - 서버에 이미지 업로드 (2) | 2024.08.06 |
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (3) - Camera, Gallery (2) | 2024.08.05 |
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (2) - Image (0) | 2024.08.05 |
[Dev, flutter] 플러터에서 iOS device에 빌드해보기 (0) | 2024.07.29 |