해당 게시글은 다음 자료를 참고해서 작성하였습니다.
https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2#0
1. Introduction
Flutter is Google's UI toolkit for building beautiful, natively compiled apps for mobile, web, and desktop from a single codebase. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source.
In this codelab, you'll extend a basic, mobile Flutter app to include interactivity. You'll also create a second page (called a route) that the user can navigate to. Finally, you'll modify the app's theme (color). This codelab extends part 1, where you create an infinite lazily loaded list, but we'll provide the starting code, if you'd like to start with part 2.
Flutter은 단일 코드베이스에서 모바일, 웹 및 데스크톱을 위한 아름답고 기본적으로 컴파일된 앱을 구축하기 위한 구글의 UI 툴킷입니다. Flutter는 기존 코드로 작동하며 전 세계 개발자 및 조직에서 사용하며 무료 오픈 소스입니다.
이 코드 실습에서는 상호 작용성을 포함하도록 기본 모바일 Flutter 앱을 확장합니다. 사용자가 탐색할 수 있는 두 번째 페이지(경로라고 함)도 만듭니다. 마지막으로 앱의 테마(색상)를 수정합니다. 이 코드 랩은 파트 1을 확장하여 무한히 로드된 목록을 작성하지만 파트 2로 시작하려면 시작 코드를 제공합니다.
What you'll learn in part 2
How to write a Flutter app that looks natural on iOS, Android, and the web
How to use hot reload for a quicker development cycle
How to add interactivity to a stateful widget
How to create and navigate to a second screen
How to change the look of an app using themes
iOS, Android 및 웹에서 자연스럽게 보이는 Float 앱을 작성하는 방법
개발 주기를 단축하기 위해 핫 재로드 사용 방법
Stateful 위젯에 상호 작용을 추가하는 방법
두 번째 화면을 만들고 탐색하는 방법
테마를 사용하여 앱 모양을 변경하는 방법
What you'll build in part 2
You'll start with a simple mobile app that generates an endless list of proposed names for a startup company. By the end of the codelab, your end users can select and unselect names, saving the best ones. Tapping the list icon in the upper right of the app bar navigates to a new page (called a route) that lists only the favorited names.
The following animated GIF shows how the finished app will work.
먼저 신생 기업에 대해 제안되는 이름 목록을 끝없이 생성하는 간단한 모바일 앱으로 시작할 수 있습니다. 코드 랩이 끝날 때까지 최종 사용자는 이름을 선택 및 선택 취소할 수 있으므로 최상의 이름을 저장할 수 있습니다. 앱 모음의 오른쪽 상단에 있는 목록 아이콘을 누르면 즐겨찾기 이름만 나열된 새 페이지(라우트라고 함)로 이동합니다.
다음 애니메이션 GIF는 완료된 앱의 작동 방식을 보여줍니다.
2. Set up your Flutter environment
If you haven't completed Part 1, see Set up your Flutter environment, in Write your first Flutter app, part 1, to set up your environment for Flutter development.
이것은 part1을 따라 왔다면 문제될 것은 없어보인다.
3. Get the starting app
▶ If you have worked through part 1 of this codelab, you already have the starting app, startup_namer. You can proceed to the next step. If you don't have startup_namer, no fear, you can get it using the following instructions.
▶이 코드랩의 파트 1에서 작업했다면 startup_name이라는 시작 앱이 이미 있습니다. 다음 단계로 진행할 수 있습니다. startup_name(startup_nameer)이 없는 경우 다음 지침을 사용하여 받을 수 있습니다.
▶Create a simple templated Flutter app using the instructions in Create the app. Name the project startup_namer (instead of flutter_app).
▶앱 생성의 지시사항을 사용하여 간단한 템플릿 Flud 앱을 만듭니다. 프로젝트 이름을 flood_app 대신 startup_nameer로 지정합니다.
https://flutter.dev/docs/get-started/test-drive#create-app
▶Delete all of the code from lib/main.dart. Replace it with the code from this file, which displays an infinite, lazily loaded list of proposed startup names.
▶lib/main.dart에서 모든 코드를 삭제합니다. 제안된 startup 이름의 무한하게 나열된 목록을 표시하는 이 파일의 코드로 대체합니다.
▶Update pubspec.yaml by adding the English words package:
▶ 영어 단어 패키지를 추가하여 pubspec.yaml 업데이트:
The English words package generates pairs of random words, which are used as potential startup names.
▶ While viewing the pubspec in Android Studio's editor view, click Pub get in the upper right, which pulls the package into your project. You should see the following in the console:
English words package는 잠재적인 startup 이름으로 사용되는 임의의 단어 쌍을 생성합니다.
▶ Android Studio의 편집기 보기에서 pubspec을 보는 동안 오른쪽 상단에 있는 Pubget을 클릭하여 패키지를 프로젝트로 가져옵니다. 콘솔에서 다음을 확인해야 합니다.
▶ Run the app.
Scroll as far as you want, viewing a continual supply of proposed startup names.
4. Add icons to the list
In this step, you'll add heart icons to each row. In the next step, you'll make them tappable and save the favorites.
▶ Add a _saved Set to _RandomWordsState. This Set stores the word pairings that the user favorited. Set is preferred to List because a properly implemented Set doesn't allow duplicate entries.
이 단계에서는 각 row에 하트 아이콘을 추가합니다. 다음 단계에서 즐겨찾기를 톡톡 칠 수 있고 저장할 수 있게 만들 것입니다.
▶_saved Set을 _RandomWordsState. 추가합니다. 이 집합은 사용자가 선호하는 단어 쌍을 저장합니다. 제대로 구현된 집합은 중복 항목을 허용하지 않으므로 집합이 List보다 좋습니다.
class _RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = Set<WordPair>(); // NEW
final _biggerFont = TextStyle(fontSize: 18.0);
...
}
▶ In the _buildRow function, add an alreadySaved check to ensure that a word pairing has not already been added to favorites.
▶ _buildRow 함수에서 alreadySaved를 추가하여 단어 쌍이 즐겨찾기에 아직 추가되지 않았는지 확인합니다.
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair); // NEW
...
}
In _buildRow() , you'll also add heart-shaped icons to the ListTile objects to enable favoriting. In the next step, you'll add the ability to interact with the heart icons.
▶ Add the icons after the text, as shown below:
_buildRow()에서는 즐겨찾기를 활성화하기 위해 ListTile 개체에 하트 모양의 아이콘도 추가합니다. 다음 단계에서는 하트 아이콘과 상호 작용할 수 있는 기능을 추가합니다.
▶ 아래와 같이 텍스트 뒤에 아이콘을 추가합니다:
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon( // NEW from here...
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
), // ... to here.
);
}
▶ Hot reload the app.
You should now see open hearts on each row, but they are not yet interactive.
다음과 같이 빈 하트가 생긴 것을 볼 수 있습니다.
5. Add interactivity
In this step, you'll make the heart icons tappable. When the user taps an entry in the list, toggling its favorited state, that word pairing is added or removed from a set of saved favorites.
To do that, you'll modify the _buildRow function. If a word entry has already been added to favorites, tapping it again removes it from favorites. When a tile has been tapped, the function calls setState() to notify the framework that state has changed.
▶Add onTap to the _buildRow method, as shown below:
이 단계에서는 하트 아이콘을 고정할 수 있습니다. 사용자가 목록에서 항목을 누르고 즐겨찾기 상태를 전환하면 해당 단어 쌍이 저장된 즐겨찾기 집합에서 추가되거나 제거됩니다.
이를 위해 _buildRow 기능을 수정합니다. 단어 항목이 이미 즐겨찾기에 추가된 경우 다시 누르면 즐겨찾기에서 제거됩니다. 타일이 탭되면 함수는 setState()를 호출하여 상태가 변경되었음을 freamwork에 알립니다.
▶아래와 같이 onTap을 _buildRow method에 추가합니다:
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () { // NEW lines from here...
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
}, // ... to here.
);
}
Tip
In Flutter's reactive style framework, calling setState() triggers a call to the build() method for the State object, resulting in an update to the UI.
Flutter의 반응형 스타일 프레임워크에서 setState()를 호출하면 State 객체에 대한 build() method에 대한 호출이 트리거되어 UI가 업데이트됩니다.
다음과 같이 탭을 할 시에 상호작용이 일어난다
6. Navigate to a new screen
In this step, you'll add a new page (called a route in Flutter) that displays the favorites. You'll learn how to navigate between the home route and the new route.
In Flutter, the Navigator manages a stack containing the app's routes. Pushing a route onto the Navigator's stack updates the display to that route. Popping a route from the Navigator's stack returns the display to the previous route.
Next, you'll add a list icon to the AppBar in the build method for _RandomWordsState. When the user clicks the list icon, a new route that contains the saved favorites is pushed to the Navigator, displaying the icon.
▶ Add the icon and its corresponding action to the build method:
이 단계에서는 즐겨찾기를 표시하는 새 페이지(이동 경로라고 함)를 추가합니다. 홈 경로와 새 경로 사이를 이동하는 방법에 대해 알아봅니다.
Flutter에서 Navigator는 앱의 경로를 포함하는 스택을 관리합니다. Navigator의 스택에 경로를 누르면 해당 경로로 디스플레이가 업데이트됩니다. Navigator의 스택에서 경로를 입력하면 이전 경로로 표시됩니다.
그런 다음 _RandomWordsState의 build method에서 AppBar에 목록 아이콘을 추가합니다. 사용자가 목록 아이콘을 클릭하면 저장된 즐겨찾기가 포함된 새 경로가 Navigator로 푸시되어 아이콘이 표시됩니다.
▶빌드 방법에 아이콘과 해당 작업을 추가합니다:
class _RandomWordsState extends State<RandomWords> {
...
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Startup Name Generator'),
actions: [
IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
],
),
body: _buildSuggestions(),
);
}
...
}
Tip
Some widget properties take a single widget (child), and other properties, such as action, take an array of widgets (children), as indicated by the square brackets ([ ]).
일부 위젯 속성은 단일 위젯(child)을 사용하고, 작업과 같은 기타 속성은 대괄호([ ])로 표시된 대로 위젯(children) 배열을 사용합니다.
▶Add a _pushSaved() function to the _RandomWordsState class.
▶ _RandomWordsState class에 _pushSaved() 함수를 추가합니다.
void _pushSaved() {
}
▶ Hot reload the app. The list icon ▤
appears in the app bar. Tapping it does nothing yet because the _pushSaved function is empty.
Next, you'll build a route and push it to the Navigator's stack. That action changes the screen to display the new route. The content for the new page is built in MaterialPageRoute's builder property in an anonymous function.
▶ Call Navigator.push, as shown below, which pushes the route to the Navigator's stack. The IDE will complain about invalid code, but you will fix that in the next section.
▶ 앱을 다시 로드합니다. 목록 아이콘이 앱 표시줄에 나타납니다. _pushSaved 기능이 비어 있기 때문에 이 기능을 누르면 아직 아무 작업도 수행되지 않습니다.
그런 다음 경로를 작성하여 Navigator의 스택으로 이동합니다. 그러면 새 경로가 표시되도록 화면이 변경됩니다. 새 페이지의 내용은 익명 함수의 MaterialPageRoute의 builder 속성에 빌드됩니다.
▶ Call Navigator.push. 아래와 같이 누르면 경로가 네비게이터의 스택으로 이동합니다. IDE는 잘못된 코드에 대해 불만을 표시하지만 다음 섹션에서 이를 해결할 수 있습니다.
void _pushSaved() {
Navigator.of(context).push( );
}
Next, you'll add the MaterialPageRoute and its builder. For now, add the code that generates the ListTile rows. The divideTiles() method of ListTile adds horizontal spacing between each ListTile. The divided variable holds the final rows converted to a list by the convenience function, toList().
▶Add the code, as shown in the following code snippet:
그런 다음 MaterialPageRoute와 builder를 추가합니다. 지금은 ListTile row을 생성하는 코드를 추가합니다. ListTile의 divideTiles() 방법은 각 ListTile 사이에 수평 간격을 추가합니다. divided variable는 convenience function(toList())에 의해 목록으로 변환된 최종 행을 유지합니다.
▶ 다음 코드 조각에 표시된 대로 코드를 추가합니다:
void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
// NEW lines from here...
builder: (BuildContext context) {
final tiles = _saved.map(
(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();
return Scaffold(
appBar: AppBar(
title: Text('Saved Suggestions'),
),
body: ListView(children: divided),
);
}, // ...to here.
),
);
}
}
The builder property returns a Scaffold containing the app bar for the new route named SavedSuggestions. The body of the new route consists of a ListView containing the ListTiles rows. Each row is separated by a divider.
▶Hot reload the app. Favorite some of the selections and tap the list icon in the app bar. The new route appears containing the favorites. Note that the Navigator adds a "Back" button to the app bar. You did not have to explicitly implement Navigator.pop. Tap the back button to return to the home route.
builder 속성은 SavedSuggestions이라는 새 경로에 대한 앱 바가 들어 있는 Scaffold를 반환합니다. 새 경로의 본문은 ListTiles row을 포함하는 ListView로 구성됩니다. 각 row은 구분자로 구분됩니다.
▶앱을 Hot reload합니다. 일부 선택 항목을 즐겨찾고 앱 표시줄의 목록 아이콘을 누릅니다. 즐겨찾기가 포함된 새 경로가 나타납니다. 네비게이터는 앱 표시줄에 "Back" 단추를 추가합니다. Navigator.pop.을 명시적으로 구현할 필요는 없습니다. 홈 경로로 돌아가려면 뒤로 버튼을 누릅니다.
iOS - Main route |
iOS - Saved suggestions route |
7. Change the UI using themes
In this step, you'll modify the app's theme. The theme controls the look and feel of your app. You can either use the default theme, which is dependent on the physical device or emulator, or customize the theme to reflect your branding.
You can easily change an app's theme by configuring the ThemeData class. The app uses the default theme, but you'll change the app's primary color to white.
▶ Change the color in the MyApp class:
이 단계에서는 앱의 테마를 수정합니다. 테마는 앱의 모양과 느낌을 제어합니다. 물리적 장치 또는 에뮬레이터에 따라 달라지는 기본 테마를 사용하거나 테마를 사용자 정의하여 사용자의 브랜드를 반영할 수 있습니다.
테마 데이터 클래스를 구성하여 앱의 테마를 쉽게 변경할 수 있습니다. 앱은 기본 테마를 사용하지만 앱의 기본 색을 흰색으로 변경합니다.
▶ MyApp 클래스의 색상 변경:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
theme: ThemeData( // Add the 3 lines from here...
primaryColor: Colors.white,
), // ... to here.
home: RandomWords(),
);
}
}
----------------------------------------------------
theme: ThemeData( // Add the 3 lines from here...
primaryColor: Colors.white,
), // ... to here.
theme가 수정되어 전체 색깔도 변경된 것을 볼 수 있었다.
▶ Hot reload the app. The entire background is now white, even the app bar.
As an exercise, use ThemeData to change other aspects of the UI. The Colors class in the Material library provides many color constants that you can play with. Hot reload makes experimenting with the UI quick and easy.
▶ 앱을 Hot reload합니다. 이제 전체 배경은 흰색이고, 심지어 앱 바도 흰색입니다.
연습으로 ThemeData를 사용하여 UI의 다른 측면을 변경합니다. Material 라이브러리의 Colors 클래스는 재생할 수 있는 여러 색 상수를 제공합니다. 핫 다시 로드를 사용하면 UI를 빠르고 쉽게 테스트할 수 있습니다.
Colors class
https://api.flutter.dev/flutter/material/Colors-class.html
8. Well done!
You wrote an interactive Flutter app that runs on iOS and Android by doing the following:
다음과 같은 작업을 수행하여 iOS 및 Android에서 실행되는 대화형 Flutter 앱을 작성했습니다.
Writing Dart code
Using hot reload for a faster development cycle
Implementing a stateful widget, adding interactivity to your app
Creating a route and adding logic for moving between the home route and the new route
Learning about changing the look of your app's UI using themes
Dart 코드 쓰기
개발 주기를 단축하기 위해 hot reload 사용
stateful 위젯 구현, 앱에 상호 작용 추가
경로 생성 및 홈 경로와 새 경로 간에 이동하기 위한 논리 추가
테마를 사용하여 앱 UI 모양을 변경하는 방법 알아보기
9. Next steps
Learn more about the Flutter SDK from the following resources:
Add interactivity to your Flutter app
Flutter for Android developers
Flutter for React Native developers
Other resources include:
Also, connect with the Flutter community!
전체적인 파일은 github에 게시했습니다.
https://github.com/gurcks8989/Flutter/commit/1756a880a0224af8c7d3472a70d8ebf56c9270d1
문의 및 정정은 언제나 환영입니다.