Write Your First Flutter App, part 2

Ashe·2019년 12월 9일
0

잿더미의 Flutter

목록 보기
4/8

원문

Part 2에서 배울 내용

  • IOS와 Android 모두에서 자연스럽게 보이는 Flutter 앱을 작성하는 방법
  • 더 빠른 개발을 위해 핫 리로드 사용
  • Stateful Widget에 반응 추가하기
  • 두번째 화면으로 이동하는 기능 생성
  • 앱 테마 변경하는 법

2부에서 만들 내용

무한으로 만들어지는 이름들을 선택하거나 해제하여 즐겨찾기에 포함할 수 있고, 앱 바의 오른쪽 상단에 목록 아이콘을 통해 즐겨찾기에 포함한 목록만을 볼 수 있습니다.

목록에 즐겨찾기 아이콘 추가

각 행에 좋아요 아이콘을 추가합니다. 다음으로 행을 누르면 즐겨찾기 기능이 되게합니다.

  • RandomWordsState에 _saved 를 추가합니다. 이 Set 목록은 유저가 즐겨찾기한 단어 목록을 저장합니다. List를 사용하지 않고 Set을 사용하는 이유는 중복을 허용하지 않기 때문입니다.
class RandomWordsState extends State<RandomWords> {
	final List<WordPair> _suggestions = <WordPair>[];
  final Set<WordPair> _saved = Set<WordPair>();  // 이 행을 추가합니다.
	...
}
  • _buildRow 함수에서 단어가 이미 즐겨찾기에 저장되었는지 확인하는 Boolean 값을 추가합니다.
Widget _buildRow(WordPair pair) {
	final bool alreadySaved = _saved.contains(pair);  // 이 줄을 추가합니다.
}
  • 즐겨찾기 아이콘을 추가합니다.
Widget _buildRow(WordPair pair) {
	final bool 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,
		),  // 여기까지 추가합니다.
	);
}

동작 추가

즐겨찾기 아이콘을 탭할 수 있는 기능을 추가합니다. 사용자가 목록에서 한 항목을 누르면 즐겨찾기 상태로 전환되고 해당 단어는 즐겨찾기 목록에 추가되거나 삭제됩니다.

이를 위해 _buildRow 기능을 수정합니다. 단어가 이미 즐겨찾기에 추가된 경우 단어가 즐겨찾기에서 제거됩니다. 한 항목을 누르면 setState() 를 사용하여 상태가 변경되었음을 프레임워크에 알립니다.

  • _buildRowonTap 을 추가합니다.
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: () {  // 여기서부터
			setState(() {
				if (alreadySaved) { 
					_saved.remove(pair);
				} else {
					_saved.add(pair);
				}
			});
		},  // 여기까지 추가
	);
}

TIP: Flutter에서 setState가 트리거되면 build 메서드가 재트리거되어 UI가 업데이트됩니다.

즐겨찾기 화면으로 이동

이 단계에서는 홈과 새 화면으로 이동하는 방법을 학습할 수 있습니다.

Flutter에서 Navigator는 앱 경로가 포함된 스택을 관리합니다. 경로를 네비게이터의 스택으로 쌓으면 디스플레이가 해당 경로로 업데이트됩니다. 네비게이터의 스택에서 빼면 이전 경로로 되돌아갑니다.

다음으로 RandomWordsState의 AppBar에 목록 아이콘을 추가합니다. 사용자가 목록 아이콘을 클릭하면 저장된 즐겨찾기가 포함된 새 화면이 네비게이터로 푸시됩니다.

  • 아이콘과 해당 아이콘을 누르면 수행되는 Action을 추가합니다.
class RandomWordsState extends State<RandomWords> {
	...
	
	Widget build(BuildContext context) {
		return Scaffold(
			appBar: AppBar(
				title: Text('Startup Name Generator'),
				actions: <Widget>[
					IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
				],
			),
			body: _buildSuggestions(),
		);
	}
	...
}
  • _pushSaved() 함수를 RandomWordsState 클래스에 추가합니다.
void _pushSaved() {

}
  • 앱을 리로드해서 앱바에 목록 아이콘이 나오는지 확인합니다. 현재는 아이콘을 눌러도 _pushSaved 가 비어있어 아무것도 동작하지 않습니다.

다음으로 경로를 만들고 네비게이터의 스택으로 푸시합니다. 이 Action은 화면을 변경하여 새 경로를 표시합니다. 새 페이지의 내용은 MaterialPageRoute의 builder 속성에 익명함수로 작성됩니다.

  • Navigator.push 를 호출하여 Navigator의 스택으로 푸시합니다. IDE는 에러를 내지만 다음 섹션에서 수정할 것입니다.
void _pushSaved() {
  Navigator.of(context).push(
  );
}

다음으로 MaterialPageRoute와 builder 메서드를 추가합니다. 우선 ListTile 행을 생성하는 코드를 추가합니다. diviedTiles() 메서드는 각 ListTile 사이에 수평 구분자 추가합니다.

  • 위에서 설명된 내용처럼 코드를 수정합니다.
void _pushSaved() {
  Navigator.of(context).push(
  	MaterialPageRoute<void>(  // 여기서부터
    	builder: (BuildContext context) {
        final Iterable<ListTile> tiles = _saved.map(
        	(WordPair pair) {
            return ListTile(
            	title: Text(
              	pair.asPascalCase,
                style: _biggerFont,
              ),
            );
          },
        );
        
        final List<Widget> divied = ListTile
          .divideTiles(
            context: context,
            tiles: tiles,
          )
          .toList();  // 여기까지
      }
    ),
  );
}

builder 속성은 "Saved Suggestions" 라는 이름의 새 경로의 app bar를 포함한 Scaffold 를 리턴합니다.

void _pushSaved() {
  Navigator.of(context).push(
  	MaterialPageRoute<void>(
    	builder: (BuildContext context) {
        final Iterable<ListTile> tiles = _saved.map(
        	(WordPair pair) {
            return ListTile(
            	title: Text(
              	pair.asPascalCase,
                style: _biggerFont,
              ),
            );
          },
        );
        
        final List<Widget> divied = ListTile
          .divideTiles(
            context: context,
            tiles: tiles,
          )
          .toList();
        
        return Scaffold(  // 여기서부터
        	appBar: AppBar(
          	title: Text('Saved Suggestions'),
          ),
          body: ListView(children: divieded),
        );  // 여기까지
      }
    )
  )
}

UI Theme 변경하기

ThemeData 클래스 를 구성하여 앱 테마를 쉽게 변경할 수 있습니다 . 이 앱은 현재 기본 테마를 사용하지만 앱의 기본 색상을 흰색으로 변경합니다.

  • MyApp 클래스에서 색상을 변경했습니다.
class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      theme: ThemeData(
				primaryColor: Colors.white,
      ),
      home: RandomWords(),
    )
  }
}
profile
Qué será, será

0개의 댓글