일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 자바스크립트
- MSSQL
- .NET
- JavaScript
- Firebase
- 깃허브
- Flutter
- Animation
- 리엑트
- 닷넷
- 바인딩
- typescript
- page
- Binding
- 플러터
- HTML
- Maui
- spring boot
- AnimationController
- 마우이
- 애니메이션
- React JS
- 오류
- 파이어베이스
- listview
- GitHub
- MS-SQL
- MVVM
- 함수
- db
Archives
- Today
- Total
개발노트
67. ValueListenableBuilder 로 변동되는 값을 가진 특정 위젯만 리빌드하기 (with ValueNotifier) 본문
앱 개발/Flutter
67. ValueListenableBuilder 로 변동되는 값을 가진 특정 위젯만 리빌드하기 (with ValueNotifier)
mroh1226 2024. 2. 16. 15:46반응형
ValueListenableBuilder
ValueListenableBuilder는 Flutter 프레임워크에서 제공하는 위젯 중 하나로, 값이 변경될 때마다 자동으로 UI를 갱신하는 데 사용됩니다. 이 위젯은 값이 변경될 때마다 새로운 위젯 트리를 생성하는 대신 기존의 위젯 트리를 업데이트하여 효율적으로 화면을 갱신합니다.
ValueListenableBuilder는 세 가지 중요한 매개변수를 갖습니다:
- valueListenable: 값을 감시하는 ValueListenable입니다. 이 값이 변경될 때마다 ValueListenableBuilder는 자동으로 자식 위젯을 재빌드합니다.
- builder: 실제 위젯 트리를 생성하는 데 사용되는 빌더 함수입니다. 이 빌더 함수는 값이 변경될 때마다 호출되며, 현재 값과 빌드 컨텍스트를 매개변수로 받습니다.
- child: 선택적 매개변수로, 고정된 자식 위젯을 제공할 수 있습니다. 이 자식 위젯은 값이 변경될 때마다 새로 생성되는 대신 재사용됩니다.
ValueListenableBuilder는 보통 ValueNotifier나 AnimationController 등의 클래스와 함께 사용됩니다. 이러한 클래스들은 값의 변화를 감지할 수 있는 ValueListenable을 구현합니다. 예를 들어, ValueNotifier는 값이 변경될 때마다 리스너에게 알리고, AnimationController는 애니메이션 값의 변화를 감시할 수 있습니다.
구현 예제.
- 동그란 원을 Drag 하여 원하는 위치로 이동하는 기능을 만들어 봅니다.
- GestureDetector의 onPanUpdate(details) 로 가져온 x,y축 값을 ValueNotifier<Offset>에 실시간 저장합니다.
- ValueListenableBuilder 를 사용하여 child: 원의 x, y 축 값을 계속 감시하고 원을 나타내는 자식 위젯만 재빌드 시킵니다.
- 이외 애니메이션 기능
- Transform.translate의 offset: 속성값에 ValueNifier<Offset>을 넣어주고 값 변화에 따른 이동 애니메이션 구현
- Drag가 Start 되었을 때 Scale이 1.5배 커지고, End 되었을 때 원래 크기로 돌아오는 애니메이션 구현
- Drag가 Start 되고 원의 크기 Scale이 다 켜졌다면 푸른색(인디고 색상)으로 변하고, Drag가 End 되었을 때 다시 원래 색상(핑크색)으로 돌아오는 애니메이션 구현
예제 소스.
import 'package:flutter/material.dart';
class TestScreen extends StatefulWidget {
const TestScreen({super.key}); // 생성자
@override
State<TestScreen> createState() => _TestScreenState(); // 상태를 생성하는 createState 메서드
}
class _TestScreenState extends State<TestScreen>
with SingleTickerProviderStateMixin {
late final AnimationController _animationController = AnimationController(
vsync: this, // vsync에 현재 상태 객체를 제공하여 애니메이션을 위한 ticker를 제공
duration: const Duration(milliseconds: 300), // 애니메이션 지속 시간
);
late final Animation<double> _scale =
Tween(begin: 1.0, end: 1.5).animate(_animationController); // 크기 변환 애니메이션
late final ValueNotifier<Offset> _dxy = ValueNotifier(Offset.zero); // 드래그한 위치를 관리하는 ValueNotifier
void _onPanStart(DragStartDetails details) {
_animationController.forward(); // 드래그가 시작되면 애니메이션을 시작
}
void _onPanUpdate(DragUpdateDetails details) {
_dxy.value = Offset( // 드래그 이벤트가 발생할 때마다 드래그한 위치를 업데이트
_dxy.value.dx + details.delta.dx,
_dxy.value.dy + details.delta.dy,
);
}
void _onPanEnd(DragEndDetails details) {
_animationController.reverse(); // 드래그가 끝나면 애니메이션을 역방향으로 재생
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size; // 현재 화면의 크기
return Scaffold( // 화면의 기본 레이아웃 구조를 제공하는 Scaffold
body: Center( // 자식 위젯을 화면의 가운데에 배치하는 Center 위젯
child: ValueListenableBuilder( // ValueNotifier를 청취하고 해당 값이 변경될 때마다 리빌드
valueListenable: _dxy, // 드래그한 위치를 업데이트하기 위한 ValueNotifier
builder: (context, value, child) => GestureDetector( // 사용자의 터치 동작을 감지하는 GestureDetector
onPanStart: _onPanStart, // 드래그가 시작되면 호출되는 콜백
onPanUpdate: _onPanUpdate, // 드래그 이벤트가 업데이트될 때 호출되는 콜백
onPanEnd: _onPanEnd, // 드래그가 끝날 때 호출되는 콜백
child: Transform.translate( // 자식 위젯을 이동시키는 Transform.translate
offset: _dxy.value, // 드래그한 위치에 따라 자식 위젯을 이동
child: ScaleTransition( // 자식 위젯에 크기 변환을 적용하는 ScaleTransition
scale: _scale, // 크기 변환 애니메이션
child: Container( // 자식 위젯을 장식하는 Container
alignment: Alignment.center, // 자식 위젯을 가운데로 정렬
height: 100, // 높이
width: 100, // 너비
decoration: BoxDecoration( // 자식 위젯의 장식
color: _animationController.status == AnimationStatus.completed // 애니메이션 상태에 따라 배경색 변경
? Colors.indigo // 애니메이션이 완료된 경우의 배경색
: Colors.pink, // 애니메이션이 완료되지 않은 경우의 배경색
shape: BoxShape.circle, // 원형 모양으로 설정
),
child: Text( // 드래그한 위치를 표시하는 Text 위젯
'(${_dxy.value.dx.ceil()} , ${_dxy.value.dy.ceil()})'),
),
),
),
),
),
),
);
}
}
소스설명.
GestureDetector
- onPanUpdate: Drag 되는 동안 호출되며 x, y 축 값을 제공합니다. (DragUpdateDetails)
- onPanStart: Drag가 시작될 때 호출되며, 위에서 정의한_onPanStart() 메소드의 _animationController.forward()를 통해 애니메이션을 실행 시켜줍니다.(원의 스케일 커짐, 푸른색 색상으로 변함)
- onPanEnd: Drag가 종료되었을 때 호출되며, 위에서 정의한 _onPanStart() 메소드의 _animationController.reverse()를 통해 애니메이션을 반대로 실행 시켜줍니다. (원래 원의 스케일로 돌아옴, 원래 색상인 핑크색으로 돌아옴)
*onHorizontalDragUpdate: ,onVerticalDragUpdate: 이 아닌 onPan 을 사용한 이유:
- 각각 x축, y축 값만 제공하고 2개다 사용한다고 해도 메소드 호출이 동시에 이루어지지 않았습니다.
- 가로로 먼저 Drag한경우에는 onVerticalDragUpdate 이 호출되지않아 y축 값이 변동되지않았으며,
세로로 먼저 Drag한 경우에는 onHorizontalDragUpdate 이 호출되지않아 x축 값 변동이 이루어지지않았습니다.
ValueListenableBuilder
- ValueListenableBuilder 로 Container(원)를 감싸주고 ValueListenable 에 감시할 값을 넣어줍니다.
(감시할 값은 ValueNotifier<Offset> _dxy 로 Drag된 x, y 축값을 나타냅니다.) - ValueListenableBuilder는 ValueNotifier를 감시하고 해당 값이 변경될 때마다 자동으로 리빌드합니다.
(_dxy ValueNotifier를 사용하여 드래그한 위치를 업데이트합니다.)
이외 애니메이션 위젯들
- Transform.translate 위젯은 자식 위젯을 이동시키는 데 사용됩니다. 여기서는 _dxy.value와 _animationController.value를 곱하여 드래그한 위치에 따라 자식 위젯이 이동하도록 설정됩니다.
- ScaleTransition은 자식 위젯에 크기 변환을 적용합니다. 여기서는 _scale 애니메이션을 사용하여 자식 위젯에 크기 변환을 적용합니다.
반응형
'앱 개발 > Flutter' 카테고리의 다른 글
Comments