일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Collection
- List
- 함수
- variable
- 코틀린
- 다트
- pushnamed
- textstyle
- text
- 클래스
- map
- 웹크롤러
- import
- package
- animation
- DART
- 콜렉션
- set
- function
- kotlin
- python
- Android
- 플러터
- 파이썬
- Class
- crawler
- Yocto
- ML
- Flutter
- 크롤러
- Today
- Total
조용한 담장
Flutter: Hero 본문
앱의 페이지(Page) 또는 루트(Route) 사이의 이동할 때 animation 을 만들어주는 위젯이다.
특히 이동하는 페이지 사이에 공통된 이미지 영역이 있다면 이를 기반으로 animation 을 만들기 위해 사용할 수 있다.
예를 들어 쇼핑앱의 제품 사진으로 된 목록중 하나를 선택하면 그 사진이 커지면서 제품의 상세 내용을 보여주는 동작을 생각해 볼 수 있다.
위와 같이 이동하는 페이지 사이의 공통되게 보여주는 부분에 대한 animation 을 만드는데 사용한다.
Hero({
Key key, @required Object tag, CreateRectTween createRectTween,
HeroFlightShuttleBuilder flightShuttleBuilder,
HeroPlaceholderBuilder placeholderBuilder, bool transitionOnUserGestures: false,
@required Widget child})
두 페이지의 공통된 영역을 tag 를 통해 child 위젯을 animation 생성 대상으로 연결하므로 같은 값을 가져야 올바른 대상과 작동이 된다.
Behind the scenes
https://flutter.dev/docs/development/ui/animations/hero-animations#behind-the-scenes
Hero animation 이 동작하는 과정을 첫 route 에서 다음 route 까지의 과정을 살펴보자.
hero 동작이 시작하면 첫 화면인 source route 의 화면은 사라지고(offscreen), 최종 화면인 destination hero 를 source route 와 같은 위치와 같은 크기로 Overlay 를 화면에 그린다. (t = 0.0)
위에서 선택한 첫번째 꽃 사진이 움직이는 animation 이 그려지는 공간이 Overlay 이다.
이때는 Tween<Rect> 를 이용하며 createRectTween 속성값에 따라 달라질 수 있다.
기본은 MaterialRectArcTween 을 사용한다.
animation 이 완료되면 hero 위젯을 overlay 에서 destination route 으로 옮긴다. (t = 1.0)
destination hero 가 destination route 의 최종 위치에 나타난다.
Sample code
List<Widget> items(BuildContext context) {
_loadAsset(context);
return List.generate(assets[assetImages].length, (index) {
return Container(
padding: EdgeInsets.all(8),
child: Container(
child: Hero(
tag: index,
//..
),
));
});
}
//...
body: Center(
child: GridView.count(
crossAxisCount: 2,
children: items(context),
),
),
첫 페이지에 GridView 를 사용한다.
이미지 목록은 assets 에 저장되어 있다.
이미지의 index 값을 Hero 의 tag 로 사용하여 구분한다.
Hero(
tag: index,
child: Material(
color: Colors.transparent,
child: InkWell(
child: Image(
image: AssetImage(
"$imagePath${assets[assetImages]['image${index + 1}']}"),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute<void>(
builder: (BuildContext context) {
return _buildPage(context, index);
}
));
},
),
),
),
Hero 는 이미지의 index 를 tag 로 가지고 Image 를 최종 child 로 가진다.
터치 반응을 위해 Material 과 InkWell 을 사용한다.
이미지는 assets 에서 index 값에 따라 불러온다.
여기까지로 source route 의 화면이 만들어 졌다.
onTap 에서 navigate 를 통해 MaterialPageRoute 로 destination route 를 만든다.
Widget _buildPage(BuildContext context, int index) {
return Scaffold(
appBar: AppBar(
title: Text('Item'),
),
body: Center(
child: Container(
width: 300.0,
height: 300.0,
child: Column(
children: <Widget>[
Card(
child: Column(
children: <Widget>[
Hero(
tag: index,
child: Image(
image: AssetImage(
"$imagePath${assets[assetImages]['image${index + 1}']}"),
),
),
Container(
height: 40.0,
alignment: Alignment.center,
child: Text("File name: ${assets[assetImages]['image${index + 1}']}"),
),
],
),
),
FlatButton(
color: Colors.blue[100],
child: Text("Back"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
),
),
);
}
Card 에 Image 와 "File name" 텍스트를 index 에 따라 넣어 만든다.
Image 를 Hero 의 child 로 지정하고 tag 를 index 로 하여 source route 의 hero widget 과 매칭한다.
Reference
https://api.flutter.dev/flutter/widgets/Hero-class.html
https://flutter.dev/docs/development/ui/animations/hero-animations
'Flutter' 카테고리의 다른 글
WHO 에서 Flutter 로 앱 개발 중 (0) | 2020.03.27 |
---|---|
Flutter: Staggered Animations (0) | 2020.02.19 |
Flutter : Animation (3) | 2020.02.07 |
플러터 프로젝트 코멘트 지우기 (remove comments) (0) | 2020.01.28 |
[플러터] Flutter 1.12 release (0) | 2019.12.12 |