1. 程式人生 > >Flutter 擴充套件NestedScrollView (三)下拉重新整理的解決

Flutter 擴充套件NestedScrollView (三)下拉重新整理的解決

解決點之前的2個問題。開心的上專案試了下。完美。

但是在使用官方的下拉重新整理 RefreshIndicator 發現沒法使用。

默默打開了原始碼,我們再來看一看。。

首先,我除錯到這個,發現notification.depth不為0,其實也好理解,因為NestedScrollView裡面有很多能滾動的東西。預設的RefreshIndicator要求的是必須是第一層的它才其效果。

/// A [ScrollNotificationPredicate] that checks whether
/// `notification.depth == 0`, which means that the notification did not bubble
/// through any intervening scrolling widgets.
bool defaultScrollNotificationPredicate(ScrollNotification notification) {
  return
notification.depth == 0; } 複製程式碼

那麼我改成,再試試呢?

bool defaultScrollNotificationPredicate(ScrollNotification notification) {
  return true;
  return notification.depth == 0;
}
複製程式碼

在_handleScrollNotification方法中,我們可以看到會有很多ScrollNotification進來,不同的,當你滑動在一個不能滾動的list裡面的時候,獲取的viewportDimension是為0.。這會覆蓋掉之前有viewportDimension的值。

所以我做了以下改動

double maxContainerExtent = 0.0;
  bool _handleScrollNotification(ScrollNotification notification) {
    if (!widget.notificationPredicate(notification)) return false;
    maxContainerExtent = math.max(
        notification.metrics.viewportDimension, this.maxContainerExtent);
    if (notification is
ScrollStartNotification && notification.metrics.extentBefore == 0.0 && _mode == null && _start(notification.metrics.axisDirection)) { setState(() { _mode = _RefreshIndicatorMode.drag; }); return false; } bool indicatorAtTopNow; switch (notification.metrics.axisDirection) { case AxisDirection.down: indicatorAtTopNow = true; break; case AxisDirection.up: indicatorAtTopNow = false; break; case AxisDirection.left: case AxisDirection.right: indicatorAtTopNow = null; break; } if (indicatorAtTopNow != _isIndicatorAtTop) { if (_mode == _RefreshIndicatorMode.drag || _mode == _RefreshIndicatorMode.armed) _dismiss(_RefreshIndicatorMode.canceled); } else if (notification is ScrollUpdateNotification) { if (_mode == _RefreshIndicatorMode.drag || _mode == _RefreshIndicatorMode.armed) { if (notification.metrics.extentBefore > 0.0) { _dismiss(_RefreshIndicatorMode.canceled); } else { _dragOffset -= notification.scrollDelta; _checkDragOffset(maxContainerExtent); } } if (_mode == _RefreshIndicatorMode.armed && notification.dragDetails == null) { // On iOS start the refresh when the Scrollable bounces back from the // overscroll (ScrollNotification indicating this don't have dragDetails // because the scroll activity is not directly triggered by a drag). _show(); } } else if (notification is OverscrollNotification) { if (_mode == _RefreshIndicatorMode.drag || _mode == _RefreshIndicatorMode.armed) { _dragOffset -= notification.overscroll / 2.0; _checkDragOffset(maxContainerExtent); } } else if (notification is ScrollEndNotification) { switch (_mode) { case _RefreshIndicatorMode.armed: _show(); break; case _RefreshIndicatorMode.drag: _dismiss(_RefreshIndicatorMode.canceled); break; default: // do nothing break; } } return false; } 複製程式碼

對於NestedScrollView 來說。我們只需要關注最大能滾動viewportDimension,用這個來驅動整個下拉重新整理.

Sample Code

用法跟官方一致

 return NestedScrollViewRefreshIndicator(
      onRefresh: onRefresh,
      child: extended.NestedScrollView(
複製程式碼

最後放上 Github extended_nested_scroll_view,如果你有更好的方式解決這個問題或者有什麼不明白的地方,都請告訴我,由衷感謝。