
출처 : https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1/#0
개발 환경이 구성되지 않은 경우, 링크를 클릭하여 관련 정보를 확인 바랍니다.
IDE 에서 "New Flutter Project" 메뉴가 보이지 않는 경우 plugin 을 설치 하시기 바랍니다.
New Flutter Project 를 확인 할 수 있습니다.아래 코드를 변형하면서 작업을 진행할 예정 입니다.
개발하다 보면 글의 간격이(줄맞춤) 어긋나서 코드의 가독성이 떨어지는데, 이때 Android Studio/IntelliJ IDEA 에서는 우클릭 후
Reformat Code with dartfmt, vscode 에서는 우클릭 후Format Document, terminal 에서는flutter format <filename>을 입력하면 코드가 정렬되는 것을 확인할 수 있습니다.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
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'),
),
),
);
}
=> 화살표 함수를 활용하여 코드를 간결하게 줄일 수 있습니다.Scaffold 위젯은 기본 앱 바, 제목 및 홈 스크린의 위젯 트리를 포함하는 본문 속성을 제공합니다. 위젯 하위 트리는 상당히 복잡 할 수 있습니다. (우선적으로 필요 속성부터 배워나가면 좋아요)build 메소드를 제공하는 것입니다.
pubspec.yaml파일을 열어 패키지 정보를 추가 합니다.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
english_words: ^3.1.0 # 이 라인을 추가하면 됩니다.
packages get명령을 통해 추가된 의존성(dependencies) 정보를 다운로드 합니다.
flutter packages get
Running "flutter packages get" in startup_namer...
Process finished with exit code 0
소스(
lib/main.dart) 상단에 패키지 정보를 추가 합니다.
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart'; // 이 라인 추가
실행 할 때 마다 (hot deploy) 중앙의 단어가 변경되는 것을 확인할 수 있습니다
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final wordPair = WordPair.random(); // Add this line.
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
//child: Text('Hello World'), // Replace this text...
child: Text(wordPair.asPascalCase), // With this text.
),
),
);
}
}
StatelessWidget 은 변경할 수 없으므로 해당 속성을 변경할 수 없습니다.StatefulWidget 은 위젯의 수명 기간 동안 변경 될 수 있는 상태를 유지 합니다.
State<RandomWords>RandomWords 클래스에서 사용하는 상태(State)를 구현한 클래스 입니다.
class RandomWordsState extends State<RandomWords> {
// TODO Add build method
}
StatefulWidget위젯을 상속받아 클래스를 만들고, 상태변화를 담당할 클래스(RandomWordsState)를 지정 합니다.
class RandomWords extends StatefulWidget {
@override
RandomWordsState createState() => RandomWordsState();
}
RandomWords클래스에서 상태가 변화하면build구문을 자동적으로 수행
class RandomWordsState extends State<RandomWords> {
@override // Add from this line ...
Widget build(BuildContext context) {
final WordPair wordPair = WordPair.random();
return Text(wordPair.asPascalCase);
} // ... to this line.
}
이전과 비교해 보면 main에서 랜덤 단어를 생성한 것을
StatefulWidgetRandomWords 에 위임하여 값을 생성 및 관리하도록 하여, 좀더 유연한(확장하기 쉬운) 소스로 되었습니다.
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: RandomWords(),
),
),
);
}
}
class RandomWordsState extends State<RandomWords>{
@override
Widget build(BuildContext context) {
final WordPair wordPair = WordPair.random();
return Text(wordPair.asPascalCase);
}
}
class RandomWords extends StatefulWidget {
@override
RandomWordsState createState() => RandomWordsState();
}
ListView 의 factory build 생성자를 사용하여, 스크롤 할 때 목록을 느리게 빌드 할 수 있습니다. (필요 시 목록을 동적으로 생성하므로 효율적)
_ (언더스코어) 로 시작하면 dart 언어에서는 private 으로 인식하게 됩니다.단어 목록 정보와, 텍스트 스타일을 추가 합니다
class RandomWordsState extends State<RandomWords> {
// 아래 두 라인 추가
final List<WordPair> _suggestions = <WordPair>[];
final TextStyle _biggerFont = const TextStyle(fontSize: 18);
...
}
Widget _buildSuggestions() {
return ListView.builder(
padding: const EdgeInsets.all(16),
// itemBuilder는 대상 아이템을 만들어주는 역할을 합니다.
// 인덱스가 홀수냐 짝수냐에 따라 대상 항목(ListTile)을 보여주거나 구분선(Divider)을 보여줍니다.
itemBuilder: (BuildContext _context, int i) {
// 인덱스가 홀수인 경우 구분선을 보여준다
if (i.isOdd) {
return Divider();
}
final int index = i ~/ 2; // 나누기를 하면 double 임 하지만 ~/ 연산자를 통해 int로 바꿔준다 == (a / b).truncate().toInt() 와 동일한 값 임.
// i : itemBuilder 내부에 들어가는 실제 항목의 index 값
// index : i를 2로 나눈 값 ( 홀수 라인에 구분선이 들어가기 때문 )
// 목록이 증가한 경우에만 값을 더 추가하는 엑션을 처리, 이미 추가한 값은 더이상 추가하지 않음
// print('$i ::: $index');
if (index >= _suggestions.length) {
// index 값이 _suggestions 길이보다 커지는 경우
_suggestions.addAll(generateWordPairs()
.take(10)); // 단어 목록에서 10개를 _suggestions 목록 정보에 추가한다
}
// item 인덱스(i)가 짝수인 경우에는 해당 _suggestions 인덱스(index)에 값을 보여주도록 한다
return _buildRow(_suggestions[index]);
});
}
Widget _buildRow(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
}