앱의 특정 UI 요소 위에 순차적으로 도움말(툴팁)을 표시하여 사용자에게 기능을 안내하는 '온보딩(Onboarding)' 또는 '가이드 투어(Guided Tour)' 기능을 구현하기 위한 위젯 세트입니다.
- 순차적 툴팁 표시:
displayIndex를 통해 지정된 순서대로 툴팁을 표시합니다. - 동적 위치 계산:
GlobalKey를 사용하여 대상 위젯의 위치를 동적으로 찾아 툴팁을 정확하게 배치합니다. - 커스터마이징: 오버레이 색상, 애니메이션, 툴팁 위치 등 다양한 옵션을 제공합니다.
- 흐름 제어:
TooltipController를 통해 툴팁 표시를 시작, 중지, 이동하는 등 완벽하게 제어할 수 있습니다.
OverlayTooltipScaffold: 툴팁 시스템을 활성화할 화면의 최상위 루트 위젯입니다.TooltipController: 툴팁의 표시 상태와 순서를 관리하는 컨트롤러입니다.OverlayTooltipItem: 툴팁을 표시할 대상 위젯을 감싸는 위젯입니다.
가장 먼저, 툴팁의 상태를 관리할 TooltipController를 생성합니다. 일반적으로 StatefulWidget의 State 내에서 관리합니다.
class _MyScreenState extends State<MyScreen> {
late final TooltipController _tooltipController;
@override
void initState() {
super.initState();
_tooltipController = TooltipController(
// 모든 툴팁이 표시된 후 호출될 콜백
onDone: () {
print('툴팁 표시 완료!');
},
// 툴팁 표시를 시작할 조건 (예: 3개의 툴팁 아이템이 모두 등록되었을 때)
startWhen: (instantiatedCount) async {
return instantiatedCount >= 3;
},
);
}
@override
void dispose() {
_tooltipController.dispose();
super.dispose();
}
// ...
}툴팁을 표시할 화면의 Scaffold 또는 루트 위젯을 OverlayTooltipScaffold로 감싸고, 생성한 컨트롤러를 전달합니다.
// _MyScreenState 내 build 메서드
@override
Widget build(BuildContext context) {
return OverlayTooltipScaffold(
controller: _tooltipController,
builder: (context) => Scaffold(
appBar: AppBar(title: const Text('Overlay Tooltip 예제')),
body: ... // 3단계에서 설명할 위젯들
),
);
}툴팁을 표시하고 싶은 각 위젯을 OverlayTooltipItem으로 감쌉니다. displayIndex로 순서를 지정하고, tooltip 빌더로 툴팁 위젯을 만듭니다.
// Scaffold의 body 부분
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 첫 번째 툴팁
OverlayTooltipItem(
displayIndex: 0,
tooltip: (controller) => TextButton(
onPressed: controller.next,
child: const Text('첫 번째 위젯입니다. 다음으로!'),
),
child: const Text('여기를 보세요!'),
),
const SizedBox(height: 50),
// 두 번째 툴팁
OverlayTooltipItem(
displayIndex: 1,
tooltipVerticalPosition: TooltipVerticalPosition.top,
tooltip: (controller) => Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('이 버튼을 누르면 액션이 실행됩니다.'),
TextButton(
onPressed: controller.next,
child: const Text('알겠습니다.'),
),
],
),
child: ElevatedButton(
onPressed: () {},
child: const Text('중요한 버튼'),
),
),
const SizedBox(height: 50),
// 세 번째 툴팁 (마지막)
OverlayTooltipItem(
displayIndex: 2,
tooltip: (controller) => TextButton(
onPressed: controller.dismiss, // dismiss로 툴팁 종료
child: const Text('마지막입니다. 닫기'),
),
child: const Icon(Icons.info),
),
],
),
),TooltipController의 startWhen 조건이 충족되면 툴팁이 자동으로 시작됩니다. 만약 수동으로 시작하고 싶다면, 원하는 시점에 start() 메서드를 호출하면 됩니다.
FloatingActionButton(
onPressed: () {
// 0번 인덱스부터 툴팁을 시작합니다.
_tooltipController.start(0);
},
child: const Icon(Icons.play_arrow),
)