Flutter 스크롤 감청 및 실전 app Bar 스크롤 그 라 데 이 션 실현
11522 단어 Flutter스크롤 감청appBar스크롤 그 라 데 이 션
Flutter 에서 스크롤 감청 은 일반적으로 두 가지 방식 으로 이 루어 질 수 있 는데 각각
ScrollController
과 NotificationListener
이라는 두 가지 방식 이다.스크롤 컨트롤 러 소개
ScrollController
ScrollController
에서 자주 사용 하 는 속성 과 방법 을 소개 합 니 다.offset
:구성 요소 의 현재 스크롤 위 치 를 스크롤 할 수 있 습 니 다.jumpTo(double offset)
은 지 정 된 위치 로 이동 하고 offset
은 스크롤 오프셋 입 니 다.animateTo(double offset,@required Duration duration,@required Curve curve)
은 jumpTo(double offset)
과 마찬가지 로 animateTo
이 점프 할 때 애니메이션 을 실행 하기 때문에 애니메이션 을 실행 하 는 데 필요 한 시간 과 애니메이션 곡선 을 입력 해 야 한다.스크롤 포지션 은 스크롤 가능 한 구성 요소 의 스크롤 위 치 를 저장 하 는 데 사 용 됩 니 다.스크롤 컨트롤 러 대상 은 여러 개의 스크롤 가능 한 구성 요소 에 의 해 사 용 될 수 있 습 니 다.
스크롤 컨트롤 러 는 스크롤 구성 요소 마다 스크롤 포지션 대상 을 만들어 위치 정 보 를 저장 합 니 다.ScrollPosition 에 저 장 된 것 은 ScrollController 의 positions 속성 입 니 다.그 는
List<ScrollPosition>
배열 입 니 다.ScrollController 에서 위치 정 보 를 진정 으로 저장 하 는 것 은 ScrollPosition 입 니 다.offset 은 편리 하 게 사용 할 수 있 는 속성 일 뿐 입 니 다.원본 코드 를 보면 offset 가 져 오기 가 ScrollPosition 에서 가 져 온 것 을 발견 할 수 있 습 니 다.
/// Returns the attached [ScrollPosition], from which the actual scroll offset
/// of the [ScrollView] can be obtained.
/// Calling this is only valid when only a single position is attached.
ScrollPosition get position {
assert(_positions.isNotEmpty, 'ScrollController not attached to any scroll views.');
assert(_positions.length == 1, 'ScrollController attached to multiple scroll views.');
return _positions.single;
}
/// The current scroll offset of the scrollable widget.
/// Requires the controller to be controlling exactly one scrollable widget.
double get offset => position.pixels;
하나의 ScrollController
은 여러 개의 스크롤 가능 한 구성 요소 에 대응 할 수 있 지만 스크롤 위 치 를 읽 는 offset
은 1 대 1 로 읽 어야 합 니 다.한 쌍 이 많은 상황 에서 우 리 는 다른 방법 으로 스크롤 위 치 를 읽 을 수 있다.현재 ScrollController
이 스크롤 할 수 있 는 두 개의 구성 요소 에 대응 하고 있다 고 가정 하면 position.elementAt(index)
을 통 해 ScrollPosition
을 얻 을 수 있 고 offset
을 얻 을 수 있 습 니 다.
controller.positions.elementAt(0).pixels
controller.positions.elementAt(1).pixels
스크롤 포지션 방법ScrollPosition
은 두 가지 상용 방법 이 있다.각각 animateTo()
과 jumpTo()
이다.그들 이 야 말로 스크롤 위치 로 이동 하 는 것 을 진정 으로 제어 하 는 방법 이다.Scroll Controller 에서 이 두 가지 동명 의 방법 은 내부 에서 최종 적 으로 Scroll Position 이라는 두 가지 방법 을 호출 할 것 이다.
Future<void> animateTo(
double offset, {
@required Duration duration,
@required Curve curve,
}) {
assert(_positions.isNotEmpty, 'ScrollController not attached to any scroll views.');
final List<Future<void>> animations = List<Future<void>>(_positions.length);
for (int i = 0; i < _positions.length; i += 1)
// ScrollPosition animateTo
animations[i] = _positions[i].animateTo(offset, duration: duration, curve: curve);
return Future.wait<void>(animations).then<void>((List<void> _) => null);
}
스크롤 컨트롤 러 제어 원리ScrollController
그리고 다른 중요 한 세 가지 방법 이 있 습 니 다.1、createScrollPosition
:ScrollController
이 스크롤 가능 한 구성 요소 와 연 결 될 때 스크롤 가능 한 구성 요 소 는 먼저 ScrollController
의 createScrollPosition
방법 으로 ScrollPosition
을 만들어 스크롤 위치 정 보 를 저장 합 니 다.
ScrollPosition createScrollPosition(
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition);
2.스크롤 구성 요소 가 createScrollPosition
방법 을 호출 한 후에 attach
방법 으로 번 호 를 만 드 는 ScrollPosition
정 보 를 positions
속성 에 추가 합 니 다.이 단 계 는'등록 위치'라 고 부 르 고 등록 후 animateTo()
과 jumpTo()
만 호출 할 수 있 습 니 다.
void attach(ScrollPosition position);
3.마지막 으로 스크롤 가능 한 구성 요소 가 소각 되 었 을 때 detach()
방법 을 사용 하여 ScrollPosition
대상 을 ScrollController
의 positions
속성 에서 제거 합 니 다.이 단 계 는'로그아웃 위치'라 고 부 르 고 로그아웃 후 animateTo()
과 jumpTo()
은 다시 호출 할 수 없습니다.
void detach(ScrollPosition position);
알림 리스터 소개알림 거품
Flutter Widget 트 리 중성자 Widge t 는 알림(Notification)을 보 내 아버지(조상 포함)Widget 과 통신 할 수 있 으 며,아버지 급 구성 요 소 는
NotificationListener
구성 요 소 를 통 해 자신 이 주목 하 는 알림 을 감청 할 수 있 습 니 다.이러한 통신 방식 은 웹 개발 에서 브 라 우 저의 이벤트 거품 과 유사 하 며 Flutter 에 서 는'거품'이라는 용 어 를 사용 하여 거품 을 알 리 는 것 이 라 고 합 니 다.알림 거품 은 사용자 터치 이벤트 거품 과 비슷 하지만 한 가지 차이 가 있 습 니 다.알림 거품 은 중단 할 수 있 지만 사용자 터치 사건 은 안 됩 니 다.
스크롤 알림
Flutter 에 서 는 스크롤 가능 한 구성 요소(Scrollable Widget)가 미 끄 러 질 때 스크롤 알림(Scroll Notification)을 나 눠 주 는 알림 을 많이 사 용 했 습 니 다.
Scrollbar
은 바로 감청 ScrollNotification
을 통 해 스크롤 바 위 치 를 확인 합 니 다.
switch (notification.runtimeType){
case ScrollStartNotification: print(" "); break;
case ScrollUpdateNotification: print(" "); break;
case ScrollEndNotification: print(" "); break;
case OverscrollNotification: print(" "); break;
}
그 중에서 ScrollStartNotification
과 ScrollUpdateNotification
등 은 모두 ScrollNotification
류 를 계승 하고 서로 다른 유형의 알림 자 류 는 서로 다른 정 보 를 포함 하 며 ScrollUpdateNotification
은 scrollDelta
속성 을 가지 고 이동 의 위 치 를 기록 했다.NotificationListener
시 StatelessWidget
류 의 액 수 를 계승 할 수 있 습 니 다.좌우 에 우 리 는 Widget 수 에 직접 배치 할 수 있 습 니 다.안의 onNotification
을 통 해 템 플 릿 파 라 메 터 를 지정 할 수 있 습 니 다.이 템 플 릿 매개 변 수 는 Notification
에서 계승 해 야 합 니 다.템 플 릿 파 라 메 터 를 명시 적 으로 지정 할 수 있 을 때 예 를 들 어 알림 의 유형 은 스크롤 종료 알림 입 니 다.
NotificationListener<ScrollEndNotification>
이때 NotificationListener
은 이 매개 변수 형식의 알림 만 받 습 니 다.onNotification
은 알림 처리 반전 으로 되 돌 아 왔 습 니 다.그의 반환 값 은 불 형식(bool)입 니 다.반환 값 이 true
일 때 거품 이 발생 하 는 것 을 막 습 니 다.아버지 급 Widget 은 더 이상 이 알림 을 받 을 수 없습니다.반환 값 이 false
일 때 계속 위로 거품 알림 을 올 립 니 다.양자 차이
우선 이 두 가지 방식 은 모두 스크롤 에 대한 감청 을 실현 할 수 있 지만 그들 은 약간의 차이 가 있다.
ScrollController
은 스크롤 컨트롤 의 스크롤 을 제어 할 수 있 지만 NotificationListener
은 안 됩 니 다.NotificationListener
을 통 해 스크롤 가능 한 구성 요소 부터 widget 트 리 뿌리 사이 의 임의의 위치 까지 감청 할 수 있 으 며,ScrollController
은 구체 적 인 스크롤 가능 한 구성 요소 와 만 연 결 된 후에 만 가능 합 니 다.NotificationListener
은 스크롤 이 벤트 를 받 았 을 때 현재 스크롤 위치 와 Viewport 의 정 보 를 가지 고 있 으 며,ScrollController
은 현재 스크롤 위치 만 가 져 올 수 있 습 니 다.ScrollController 실례 효과 도 코드 구현 절차
스크롤 에 필요 한 인터페이스 를 만 듭 니 다.
Scaffold
구성 요소 body
의 방식 은 Stack
의 레이 어드 위 젯 입 니 다.그 안에 listview
과 사용자 정의 appBar
을 설치 합 니 다.floatingActionButton
상단 으로 돌아 가 는 부유 단 추 를 설치 합 니 다.
Scaffold(
body: Stack(
children: <Widget>[
MediaQuery.removePadding(
removeTop: true,
context: context,
child: ListView.builder(
// ScrollController
controller: _controller,
itemCount: 100,
itemBuilder: (context, index) {
if (index == 0) {
return Container(
height: 200,
child: Swiper(
itemBuilder: (BuildContext context, int index) {
return new Image.network(
"http://via.placeholder.com/350x150",
fit: BoxFit.fill,
);
},
itemCount: 3,
autoplay: true,
pagination: new SwiperPagination(),
),
);
}
return ListTile(
title: Text("ListTile:$index"),
);
},
),
),
Opacity(
opacity: toolbarOpacity,
child: Container(
height: 98,
color: Colors.blue,
child: Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Center(
child: Text(
"ScrollerDemo",
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
),
),
),
)
],
),
floatingActionButton: !showToTopBtn
? null
: FloatingActionButton(
child: Icon(Icons.keyboard_arrow_up),
onPressed: () {
_controller.animateTo(0.0, duration: Duration(milliseconds: 500), curve: Curves.ease);
},
),
)
ScrollController
대상 을 만 들 고 초기 화 에 스크롤 에 대한 감청 을 추가 하 며 ListView
이 스크롤 가능 한 위 젯 과 연결 합 니 다.
double t = _controller.offset / DEFAULT_SCROLLER;
if (t < 0.0) {
t = 0.0;
} else if (t > 1.0) {
t = 1.0;
}
setState(() {
toolbarOpacity = t;
});
재controller.addListener 에 관련 업무 코드 를 추가 하고 스크롤 의 오프셋 에 따라 투명 도 를 계산 하여 app Bar 스크롤 그 라 데 이 션 을 실현 합 니 다.
if(_controller.offset < DEFAULT_SHOW_TOP_BTN && showToTopBtn){
setState(() {
showToTopBtn = false;
});
}else if(_controller.offset >= DEFAULT_SHOW_TOP_BTN && !showToTopBtn){
setState(() {
showToTopBtn = true;
});
}
더욱 구 르 는 높이 와 현재 floatingActionButton
의 현실 상 태 를 가지 고 floatingActionButton
을 보 여 줘 야 하 는 지 판단 합 니 다.
if(_controller.offset < DEFAULT_SHOW_TOP_BTN && showToTopBtn){
setState(() {
showToTopBtn = false;
});
}else if(_controller.offset >= DEFAULT_SHOW_TOP_BTN && !showToTopBtn){
setState(() {
showToTopBtn = true;
});
}
floatingActionButton
을 누 르 면 맨 위로 돌아 갑 니 다:
_controller.animateTo(0.0, duration: Duration(milliseconds: 500), curve: Curves.ease);
전체 코드 는 아래 GitHub 프로젝트 의 /demo/scroller_demo.dart
파일 을 참고 하 십시오.알림 리스터 인 스 턴 스
효과 도
코드 구현 절차
NotificationListener 인 스 턴 스 의 레이아웃 은 기본적으로 ScrollController 와 일치 합 니 다.다른 점 은 ListView 가 NotificationListener 에 감 싸 서 child 로 해 야 한 다 는 것 입 니 다.그리고 NotificationListener 는 onNotification 에서 스크롤 오프셋 을 판단 합 니 다.
if (notification is ScrollUpdateNotification && notification.depth == 0) {
double t = notification.metrics.pixels / DEFAULT_SCROLLER;
if (t < 0.0) {
t = 0.0;
} else if (t > 1.0) {
t = 1.0;
}
setState(() {
toolbarOpacity = t;
});
print(notification.metrics.pixels); //
}
전체 코드 는 아래 GitHub 프로젝트 의 /demo/notification_listener_demo.dart
파일 을 참고 하 십시오.이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Flutter】DateTime 전월의 일수를 취득한다달의 일수를 취득할 필요가 있어, 의외로 수요 있을까라고 생각했으므로 비망록 정도에 남겨 둡니다. DateTime 날짜에 0을 입력하면 전월 DateTime이 됩니다. 2021년 3월 0일 = 2021년 2월 28일...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.