반응형
Flutter로 개발을 하다 보면 특정 이벤트 발생 시(예를 들어 버튼 클릭), 특정 위젯의 위치로 스크롤을 이동시켜야 하는 경우가 생긴다. 이때 유용한 메서드가 Scrollable.ensureVisible 이다.
사용법
사용법은 간단하다.
- GlobalKey를 선언
- 1에서 선언한 GlobalKey를 이동하길 원하는 위젯의 Key로 등록
- Scrollable.ensureVisible의 첫 번째 파라미터로 위에서 선언된 GlobalKey의 currentContext를 넘기며 메서드를 실행
Scrollable.ensureVisible(
globalKey.currentContext!,
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
);
위와 같은 방식으로 간단하게 사용 가능하며, 아래는 위와 같은 방식으로 구현한 예제 화면이다. 상단 AppBar의 버튼을 클릭하면 해당하는 색상의 위젯으로 스크롤이 이동하는 것을 확인할 수 있다.
사용 예시 코드
// GlobalKey 선언
final redKey = GlobalKey();
final blueKey = GlobalKey();
final greenKey = GlobalKey();
// key 등록
SliverToBoxAdapter(
key: greenKey,
child: Container(
color: Colors.green,
height: MediaQuery.of(context).size.height / 2 + 100,
),
),
// Scrollable.ensureVisible 메소드 호출
ElevatedButton(
style: const ButtonStyle(
backgroundColor:
MaterialStatePropertyAll<Color>(Colors.green),
),
onPressed: () {
Scrollable.ensureVisible(
greenKey.currentContext!,
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: const Text('Green'),
),
주의점
사용법에서 알 수 있듯이 Scrollable.ensureVisible은 위젯의 context를 사용하기 때문에 GlobalKey로 접근하려는 위젯의 context가 존재해야 사용할 수 있다. (해당 context가 위젯 트리상에 존재해야 한다) 그렇기 때문에 실제코드에선, 예시 코드의 null assertion operator(느낌표 표시,!)를 사용한 부분을 예외 처리해주어야 한다.
if (redKey.currentContext != null) {
Scrollable.ensureVisible(
redKey.currentContext!,
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
);
}
아래는 위 예시의 전체 코드이다
더보기
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ScrollExample(),
);
}
}
class ScrollExample extends StatelessWidget {
const ScrollExample({super.key});
@override
Widget build(BuildContext context) {
final redKey = GlobalKey();
final blueKey = GlobalKey();
final greenKey = GlobalKey();
return Scaffold(
body: SafeArea(
child: CustomScrollView(
slivers: [
SliverAppBar(
backgroundColor: Colors.white,
pinned: true,
title: Row(
children: [
ElevatedButton(
style: const ButtonStyle(
backgroundColor:
MaterialStatePropertyAll<Color>(Colors.red),
),
onPressed: () {
if (redKey.currentContext != null) {
Scrollable.ensureVisible(
redKey.currentContext!,
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
);
}
},
child: const Text('Red'),
),
const SizedBox(
width: 10,
),
ElevatedButton(
style: const ButtonStyle(
backgroundColor:
MaterialStatePropertyAll<Color>(Colors.blue),
),
onPressed: () {
Scrollable.ensureVisible(
blueKey.currentContext!,
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: const Text('Blue'),
),
const SizedBox(
width: 10,
),
ElevatedButton(
style: const ButtonStyle(
backgroundColor:
MaterialStatePropertyAll<Color>(Colors.green),
),
onPressed: () {
Scrollable.ensureVisible(
greenKey.currentContext!,
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: const Text('Green'),
),
],
),
),
SliverToBoxAdapter(
// key: redKey,
child: Container(
color: Colors.red,
height: MediaQuery.of(context).size.height / 2 + 100,
),
),
SliverToBoxAdapter(
key: blueKey,
child: Container(
color: Colors.blue,
height: MediaQuery.of(context).size.height / 2 + 100,
),
),
SliverToBoxAdapter(
key: greenKey,
child: Container(
color: Colors.green,
height: MediaQuery.of(context).size.height / 2 + 100,
),
),
SliverToBoxAdapter(
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height / 2 + 100,
),
)
],
),
),
);
}
}
반응형
'Flutter&Dart' 카테고리의 다른 글
flutter_hooks - 실무에서 유용한 패키지 Flutter package 소개 (0) | 2023.04.15 |
---|---|
Flutter InheritedWidget 동작원리 (0) | 2023.02.16 |
플러터 개발 환경 구축(Mac, Android), Flutter 최신버전 설치 (0) | 2023.02.03 |
플러터 개발 환경 구축(Mac, iOS), Flutter 최신버전 설치 (0) | 2023.02.02 |
Flutter 버전관리, FVM을 이용한 SDK 버전 관리 (0) | 2023.01.29 |
댓글