Flutter 스크롤 감청 및 실전 app Bar 스크롤 그 라 데 이 션 실현

소개 하 다.
Flutter 에서 스크롤 감청 은 일반적으로 두 가지 방식 으로 이 루어 질 수 있 는데 각각 ScrollControllerNotificationListener 이라는 두 가지 방식 이다.
스크롤 컨트롤 러 소개
ScrollControllerScrollController 에서 자주 사용 하 는 속성 과 방법 을 소개 합 니 다.
  • offset:구성 요소 의 현재 스크롤 위 치 를 스크롤 할 수 있 습 니 다.
  • jumpTo(double offset) 은 지 정 된 위치 로 이동 하고 offset 은 스크롤 오프셋 입 니 다.
  • animateTo(double offset,@required Duration duration,@required Curve curve)jumpTo(double offset) 과 마찬가지 로 animateTo 이 점프 할 때 애니메이션 을 실행 하기 때문에 애니메이션 을 실행 하 는 데 필요 한 시간 과 애니메이션 곡선 을 입력 해 야 한다.
  • ScrollPosition
    스크롤 포지션 은 스크롤 가능 한 구성 요소 의 스크롤 위 치 를 저장 하 는 데 사 용 됩 니 다.스크롤 컨트롤 러 대상 은 여러 개의 스크롤 가능 한 구성 요소 에 의 해 사 용 될 수 있 습 니 다.
    스크롤 컨트롤 러 는 스크롤 구성 요소 마다 스크롤 포지션 대상 을 만들어 위치 정 보 를 저장 합 니 다.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 이 스크롤 가능 한 구성 요소 와 연 결 될 때 스크롤 가능 한 구성 요 소 는 먼저 ScrollControllercreateScrollPosition 방법 으로 ScrollPosition 을 만들어 스크롤 위치 정 보 를 저장 합 니 다.
    
    ScrollPosition createScrollPosition(
      ScrollPhysics physics,
      ScrollContext context,
      ScrollPosition oldPosition);
    2.스크롤 구성 요소 가 createScrollPosition 방법 을 호출 한 후에 attach 방법 으로 번 호 를 만 드 는 ScrollPosition 정 보 를 positions 속성 에 추가 합 니 다.이 단 계 는'등록 위치'라 고 부 르 고 등록 후 animateTo()jumpTo() 만 호출 할 수 있 습 니 다.
    
    void attach(ScrollPosition position);
    3.마지막 으로 스크롤 가능 한 구성 요소 가 소각 되 었 을 때 detach() 방법 을 사용 하여 ScrollPosition 대상 을 ScrollControllerpositions 속성 에서 제거 합 니 다.이 단 계 는'로그아웃 위치'라 고 부 르 고 로그아웃 후 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;
    }
    그 중에서 ScrollStartNotificationScrollUpdateNotification 등 은 모두 ScrollNotification 류 를 계승 하고 서로 다른 유형의 알림 자 류 는 서로 다른 정 보 를 포함 하 며 ScrollUpdateNotificationscrollDelta 속성 을 가지 고 이동 의 위 치 를 기록 했다.NotificationListenerStatelessWidget 류 의 액 수 를 계승 할 수 있 습 니 다.좌우 에 우 리 는 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 파일 을 참고 하 십시오.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기