Flutter教程-自定義無限滾動輪播器infinity_slider-增加多輪播巢狀聯動功能(二)

麼姐發表於2019-09-02

簡介

上篇文章我們通過組合PageView方式,實現一個自定義的infinity_slider小部件,這篇文章我們實現多個infinity_slider巢狀實現滑動互聯的效果

目標

  • 多個infinity_slider巢狀實現滑動互聯的效果

完整程式碼

思路

  1. 通過widget樹找到父infinity_slider控制元件
  2. 使用NotificationListener監聽當前infinity_slider控制元件滾動
  3. 使用父infinity_slider控制元件的_pageController移動父infinity_slider控制元件的位置
  4. 禁用當前infinity_slider控制元件在父infinity_slider控制元件未抵達邊緣時產生的光暈效果

步驟

1) 找到父infinity_slider控制元件

InfinitySlider類中新增此程式碼

static InfinitySliderState of(BuildContext context) {
    return context.ancestorStateOfType(TypeMatcher<InfinitySliderState>());
}
複製程式碼

initState中初始化下方程式碼

InfinitySliderState _ancestor;

@override
void initState() {
    _linkAncestorIfNeeded();
}
void _linkAncestorIfNeeded() {
    _ancestor = InfinitySlider.of(context);
}
複製程式碼

2) 監聽當前infinity_slider控制元件滾動

@override
Widget build(BuildContext context) {
    return NotificationListener(
        onNotification: _handleScrollNotification,
        child: PageView.builder(
            ......
        )
    );
}

void _handleScrollNotification(ScrollNotification notification) {
    
}
複製程式碼

3) 控制父infinity_slider控制元件滾動

bool _handleScrollNotification(ScrollNotification notification) {
    if (notification is OverscrollNotification && _ancestor != null) {
      if (_canLinkWithAncestorScroll(notification.overscroll < 0)) {
        _ancestor._pageController.position
            .moveTo(_ancestor._pageController.offset + notification.overscroll);
      }
    }
}
  
bool _canLinkWithAncestorScroll(bool onLeftEdge) {
    if (_ancestor == null) return false;
    return (onLeftEdge &&
        _ancestor._pageController.offset !=
            _ancestor._pageController.position.minScrollExtent) ||
        ((!onLeftEdge &&
            _ancestor._pageController.offset !=
                _ancestor._pageController.position.maxScrollExtent));
}
複製程式碼

4) 禁用infinity_slider控制元件在與父infinity_slider控制元件聯動產生的光暈

@override
Widget build(BuildContext context) {
    return NotificationListener(
      onNotification: _handleScrollNotification,
      child: NotificationListener(
            onNotification: _handleGlowNotification,
            child: PageView.builder(
                ......
            )
        )
    );
)

bool _handleGlowNotification(OverscrollIndicatorNotification notification) {
    if (notification.depth == 0 &&
        _canLinkWithAncestorScroll(notification.leading)) {
      notification.disallowGlow();
      return true;
    }
    return false;
}
複製程式碼

相關文章