새로운 이름을 마구잡이로 생성하는 모바일 앱을 구현합니다. 사용자는 마음에 드는 이름을 선택해서 저장할 수 있습니다. 이름으 한번에 10개씩 로딩되고 스크롤하면 더 생성됩니다.
이 실습을 완료하려면 Flutter SDK 및 편집기 라는 두 가지 소프트웨어가 필요합니다 . Android Studio를 사용하지만 원하는 편집기를 사용해도 됩니다.
다음 장치 중 하나를 사용하여이 예제를 실행할 수 있습니다.
여러가지 방법으로 Flutter 프로젝트를 생성할 수 있습니다. 동일하게 실행하기 위해 Terminal로 해보겠습니다.
$ flutter create google_codelab
$ cd google_codelab
$ flutter devices
# No devices dected가 뜨면 에뮬레이터를 띄워야한다.
$ flutter emulators
# 몇가지 가능한 선택지가 있을텐데 그 중 하나를 실행한다.
# 없으면 에뮬레이터를 설치해야한다.
$ flutter emulators --launch ios
$ flutter devices
# 이제 하나 연결 가능한 디바이스가 있을것이다.
$ flutter run
lib/maind.dart
의 모든 내용을 아래 내용으로 교체한다.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: const Center(
child: const Text('Hello World'),
),
),
);
}
}
교체한 후 저장을 누르고 터미널에서 r
을눌러 리로딩한다.
build
를 사용하여 하위 위젯들을 표시하는 방법을 제공하는 것입니다.이 단계에서는 english_words 라는 오픈 소스 패키지를 사용합니다 . 여기에는 가장 많이 사용되는 영어 단어 몇 가지와 일부 유틸리티 기능이 포함되어 있습니다.
pub 사이트에서 english_words 이외에 다른 오픈소스 패키지를 확인할 수 있습니다.
이 파일은 현재 프로젝트의 Flutter 앱의 Resource들을 관리합니다.
여기에 우리가 사용할 english_words: ^3.1.0
을 추가합니다.
dependencise:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
english_words: ^3.1.0 # 이걸 추가해주세요!
Pubspec.yaml에 새 dependencise 를 추가했으면 해당 패키지를 가져와야하기때문에 명령어를 입력해줍니다.
flutter packages get
새 패키지를 가져와서 사용하기위해 lib/main.dart
파일을 수정합니다. 총 네군데를 변경해줍니다.
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart'; // 여기 추가!
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
final wordPair = wordPair.random(); // 여기 추가!
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Center( // const 삭제!
child: Text(wordPair.asPascalCase), // const 삭제, 내용 변경
),
),
);
}
}
앱이 실행중인 경우 Terminal에서 r
버튼을 눌러 수정사항을 적용할 수 있습니다. ( 핫 리로드 기능 ) 핫 리로드를 수행할때마다 임의로 선택된 다른 단어들이 표시됩니다. 그 이유는 MaterialApp이 렌더링을 재 수행할때마다 새 단어쌍이 생성되기 때문입니다.
Stateless 위젯은 값이 변하지 않는 위젯입니다. 즉, final로 선언된 값입니다.
Statefulwidget은 위젯의 생명주기동안 값이 변할 수 있는 위젯입니다. 구현을 위해서는 반드시 State
인스턴스를 생성하는 StatefulWidget
클래스를 생성해야합니다. StatefulWidget 자체의 값은 변하지 않지만 내부의 State
클래스는 생명주기동안 값이 바뀔 수 있습니다.
RandomWordsState
를 생성하는 RnadomWords 클래스를 추가합니다. 그 다음 MyApp의 StatelessWidget의 하위 인스턴스로 사용합니다.class RandomWordsState extends State<RandomWords> {
// TODO Add build method
}
State<RandomWords>
는 RandomWords와 함께 사용하도록하는 State 클래스를 사용하는 것을 나타냅니다. RandomWords 위젯의 상태를 관리하며 앱의 Logic과 State는 대부분 여기에 존재할 것입니다. 이 클래스는 생성된 단어들과 즐겨찾기들을 저장합니다.
class RandomWords extends StatefulWidget {
RandomWordsState createState() => RandomWordsState();
}
State 클래스를 추가한 후 IDE에서 build 메서드를 구현하지 않았다고 에러가 뜰것입니다.
class RandomWordsState extends State<RandomWords> {
Widget build(BuildContext context) {
final WordPair wordPair = WordPair.random();
return Text(wordPair.asPascalCase);
}
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
final WordPair wordPair = WordPair.random(); // 삭제합니다.
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
//child: Text(wordPair.asPascalCase), // 이 라인을 삭제하고
child: RandomWords(), // ... 이렇게 변경합니다.
),
),
);
}
}
이 단계에서는 RandomWordsState를 확장하여 단어 목록을 생성하고 표시합니다. 사용자가 스크롤하면 ListView 위젯에 표시되는 목록이 무한대로 보이게됩니다. ListView의 builder
팩토리 생성자를 사용하면 Lazy load 를 구현할 수 있습니다.
_suggestions
은 단어들을 저장하기 위해 사용합니다. 또한 글꼴 크기를 크게하려면 _biggerFont
변수를 추가합니다.class RandomWordsState extends State<RandomWords> {
final List<WordPair> _suggestions = <WordPair>[];
final TextStyle _biggerFont = const TextStyle(fontSize: 18);
...
}
TIP: 변수명에 밑줄을 붙이면 Dart 언어로 해당 속성은 프라이빗 변수임을 알립니다.
다음으로, RandomWordsState 클래스에 _buildSuggestions()
함수를 추가합니다. 이 메소드는 단쌍들을 표시하는 ListView를 빌드합니다.
ListView 클래스는 익명의 함수로 지정된 팩토리 빌더 및 콜백 함수인 itemBuilder
를 제공합니다. 두 개의 매개변수(BuildContext 및 반복 변수인 i
)가 함수에 제공됩니다. 반복자 i
는 0에서 시작하여 함수가 호출된때마다 하나씩 증가합니다. 이 모델을 사용하면 사용자가 스크롤 할 때 _suggestions
는 무한대로 커질 수 있습니다.
_buildSuggestions
기능을 추가합니다.Widget _buildSuggestions() {
retunr ListView.builder(
padding: const EdgeInsets.all(16),
// itemBuilder 콜백은 _suggestions 의 하나당 한 번 호출되며
// 각 suggestion을 ListTile에 배치합니다.
// 짝수 행의 경우 함수는 단어 쌍을 위한 ListTile 행을 추가합니다.
// 홀수 행의 경우, 시각적으로 구분하기 위한 구분자 위젯을 추가합니다.
// 소형 장치에서 구분자를 보기 어려울 수 있다는 점에 유의해야합니다.
itemBuilder: (BuildContext _context, int i) {
// ListView에 1 px의 구분자를 각 행마다 추가합니다.
if (i.isOdd) {
return Divider();
}
// "i ~/ 2"는 2로나눈 몫을 가져옵니다.
// 예로: 1, 2, 3, 4, 5 는 0, 1, 1, 2, 2.
// 홀수번은 Divider가 배치되므로 짝수의 결과를 가져와야합니다.
final int index = i ~/ 2;
// 만약 _suggestions의 끝에 도달하면
if (index >= _suggestions.length) {
// 10개의 아이템을 _suggstions에 추가합니다.
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
)
}
_buildSuggestions
함수는 단어당 _buildRow
를 한 번 호출합니다. _buildRow
는 2부에서 더 매력적으로 ListTile을 표시할 수 있습니다.
_buildRow
함수를 추가합니다.Widget _buildRow(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
)
)
}
_buildSuggestions()
를 사용하도록 RandomWordsState의 빌드 메서드를 업데이트합니다. (Scaffold
는 기본 메터리얼 디자인 비주얼 레이아웃을 구현합니다.)build(BuildContext context) {
// final wordPair = WordPair.random(); // 삭제합니다.
// return Text(wordPair.asPascalCase); // 삭제합니다.
return Scaffold( // 여기서부터
appBar: AppBar(
title: Text('Startup Name Generator'),
),
body: _buildSuggestions(), // 여기까지 추가합니다.
)
}
Widget
build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
home: RandomWords(),
)
}
Widget