좋아요 인터렉션을 참고해 만든 커스텀 인터렉션

2024. 6. 12. 15:59IT/Flutter

SMALL

 

 

 

사내에서 인스타 라이브의 좋아요 인터렉션을 응용하면 구현이 가능할만한 인터렉션 요소를 개발해달라는 요구가 들어와서 한번 공유해보고자 한다.

 

먼저 맨 아래의 [인스타 라이브의 좋아요 인터렉션] 블로그 글을 참고하면 이해하는데 더욱 도움이 될 것 같다.

 

 

구현 프로세스

1. 아이콘 터치
2. 터치 위치에 인터렉션 요소를 가진 아이템 추가
3. 애니메이션 종료
4. 아이템 삭제

 

 

* 터치 및 해당 위치에 인터렉션 요소를 가진 아이템 추가

 

터치 위치값을 알기 위해선 GestureDetector 의 onTapDown 콜백 메서드를 활용할 수 있다.

localPostion 과 globalPosition 을 가져올 수 있는데, 

globalPostion - 전체 스크린 영역에서 절대위치 값

localPosition - 탭 한 위젯 내에서의 상대적인 위치 값

정도로 이해할 수 있다.

 

어떤 position 을 사용해서 구현해도 무방하지만 나는 커다란 코인버튼 영역 내에서 생성되기를 원했기 때문에 localPosition을 이용하여 구현하였다.

onTapDown: (details) {
  final localPosition = details.localPosition;
  addTouchInteractionIcon(localPosition);
  widget.onTap.call();
  setState(() {});
},

 

void addTouchInteractionIcon(Offset tapPosition) {
  touchInteractionIcons = [
    ...touchInteractionIcons,
    _TouchInteractionIcon(
      key: UniqueKey(),
      tapPosition: tapPosition,
      onAnimationEnd: () {
        _removeTouchInteractionIcon(touchInteractionIcons);
      },
    )
  ];
}

 

이렇게 position 값을 얻어왔다면 해당 위치에 인터렉션 아이콘을 삽입해준다.

여기서 주의할 점은 Flutter 프레임워크가 새로 추가된 인터렉션 아이템의 renderobject 를 재사용하게 하면 안된다는 것이다.

해당 인터렉션 아이템은 생성되는 즉시 TransForm 위젯을 이용하여 위치를 이동하고 transition, opacity, scale 등의 애니메이션을 animationController 을 통해 수행하게 되는데, 재사용을 하게되면 원치않는 인터렉션이 생길수가있다.

 

Flutter 프레임워크에서 트리내의 위젯의 재사용을 결정하는 방식은 크게 두가지가 있는데,

먼저 key 가 주어지지 않은 경우 해당 위치의 위젯의 Type 을 이용하여 비교한다. 

만약 key가 주어진다면 type과 함께 key를 이용하여 비교한다.

 

따라서 Type 은 같을 수 밖에 없으므로 프레임워크 내부적으로 중복되지않는 키값을 생성해주는 UniqueKey() 메서드를 이용하여 key를 넘겨주게 되면 위와같은 현상을 방지할 수 있다.

 

* 인터렉션 아이템 

class _TouchInteractionIcon extends HookWidget {
  const _TouchInteractionIcon({required this.tapPosition, required this.onAnimationEnd, super.key});

  final VoidCallback onAnimationEnd;

  final Offset tapPosition;

  @override
  Widget build(BuildContext context) {
    final animationController = useAnimationController(
      duration: const Duration(milliseconds: 1000),
    );

    final initialRotationAngle = useState(_getRotationAngle());
    final initialScale = useState(_getInitialScale());
    final initialXPosition = useState(tapPosition.dx + Random().nextInt(20) - 58.w);

    useEffect(() {
      Future.microtask(() {
        animationController.addStatusListener((status) {
          if (status == AnimationStatus.completed) {
            onAnimationEnd.call();
          }
        });

        animationController.forward();
      });

      () => null;
    }, []);

    return AnimatedBuilder(
      animation: animationController,
      builder: (context, child) {
        return Opacity(
          opacity: _getOpacity(animationController.value),
          child: Transform(
            transform: Matrix4.translationValues(
              ...)

 

인터렉션 아이템 내부에서는 생성과 동시에 초기 위치, 스케일 등의 인터렉션에 필요한 요소들을 초기화해주고, 애니메이션을 실행하며 Transform 으로 위치를 이동시키고 있다. 


이에 더하여 원하는 애니메이션 요소들을 추가해주면 더욱 더 멋진 인터렉션을 만들 수 있을것이다.

 

 

* 참고

https://velog.io/@locked/Flutter-%EC%9D%B8%EC%8A%A4%ED%83%80-%EB%9D%BC%EC%9D%B4%EB%B8%8C-%EC%A2%8B%EC%95%84%EC%9A%94-%EC%9D%B8%ED%84%B0%EB%A0%89%EC%85%98

 

[Flutter] 인스타 라이브의 좋아요 인터렉션

인스타 라이브의 좋아요 인터렉션은 어떻게 만들까?

velog.io

 

LIST