[Flutter] Hero()

Tyger·2021년 10월 19일
0

Hero()

이번 글에서는 Animation 효과를 주는 위젯인 Hero() Widget에 대해서 알아보겠다

  const Hero({
    Key? key,
    required this.tag,
    this.createRectTween,
    this.flightShuttleBuilder,
    this.placeholderBuilder,
    this.transitionOnUserGestures = false,
    required this.child,
  }) 

Hero 위젯의 사용방법은 간단하다
Hero 위젯을 사용하고 싶은 위젯을 감싸서 tag 값을 주면 된다
tag는 String 타입이며, 고유의 값 만을 주어야 한다
tag의 값이 다른 값과 중복이 되면 에러가 발생함

주로 tag 값에는 lsitview의 index를 활용하거나 url 등 고유의 값만을 사용하면 된다

사용방법은 이벤트를 발생시켜 새로운 스크린을 열어 효과를 주는 형식이다

여기서 사용된 이미지 파일은 picsum.photos에서 제공하는 무료 api를 사용 하였으며, 먼저 사용하고 싶은 Image 위젯을 Hero 위젯으로 감싼 후 tag 값에 api에서 제공해주는 고유의 id값을 tag 값으로 사용하였다

id 값은 중복되지 않는다

InkWell(
  onTap: onTap,
  child: Hero(
    tag: picture.id,
    child: Image(
        image: NetworkImage(
         "http://picsum.photos/id/${picture.id}/400/400",
                  ),
                ),
              ),
            ),

위에서 만든 InkWell 위젯의 onTap을 활용해서 onTap 함수 안에 아래와 같이 router를 연결해 주는데 일반적으로 사용하는 MaterialPageRouter가 아닌 PageRouteBuilder를 사용해서 duration 값을 넣어서 전달하면 된다.

onTap: () {
   Navigator.push(
    context,
    PageRouteBuilder(
     transitionDuration:
         const Duration(milliseconds: 1000),
            pageBuilder: (_, __, ___) =>VelogWidgetHeroDetailPage(
                              picture: e,)));

이렇게 새로운 스크린에서 다시 보여줄 Image 위젯에 똑같은 tag 값을 주면 두 개의 Hero 위젯이 tag 값에 맞춰 animation 효과를 보여주게 된다

아래의 코드에서는 Hero 위젯을 Image를 감싼것이 아닌 Center 위젯을 감싸서 사용하였지만 정상 작동은 된다

class VelogWidgetHeroDetailPage extends StatelessWidget {
  final ApiPicture picture;
  const VelogWidgetHeroDetailPage({
    Key? key,
    required this.picture,
  }) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          const Positioned(
              right: 20,
              top: 45,
              child: Icon(
                Icons.clear_outlined,
                size: 30,
                color: Colors.teal,
              )),
          Hero(
            tag: picture.id,
            child: Center(
              child: Image(
                image: NetworkImage(
                  "http://picsum.photos/id/${picture.id}/400/400",
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Example

profile
Flutter Developer

0개의 댓글