flutter 使用 inview_notifier_list与pull_to_refresh_plus冲突无法刷新问题

siman 20 小时前 24 0
SmartRefresher原因是 inview_notifier_list 在使用 InViewNotifierList 或 InViewNotifierCustomScrollView  是外层都包裹了一层InViewNotifier  造成pull_to_refresh_plus 这类插件无法刷新
我的解决方法是复写InViewNotifier
1.新建 aa.dart 把下面的代码复制进去
  1. import 'dart:async';

  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/rendering.dart';
  4. import 'package:stream_transform/stream_transform.dart';

  5. import 'package:inview_notifier_list/src/inherited_inview_widget.dart';
  6. import 'package:inview_notifier_list/src/inview_state.dart';


  7. ///builds a [ScrollView] and notifies when the widgets are on screen within a provided area.
  8. class InViewNotifier extends StatefulWidget {
  9.   ///The String list of ids of the child widgets that should be initialized as inView
  10.   ///when the list view is built for the first time.
  11.   final List<String> initialInViewIds;

  12.   ///The widget that should be displayed in the [InViewNotifier].
  13.   final Widget child;

  14.   ///The distance from the bottom of the list where the [onListEndReached] should be invoked.
  15.   final double endNotificationOffset;

  16.   ///The function that is invoked when the list scroll reaches the end
  17.   ///or the [endNotificationOffset] if provided.
  18.   final VoidCallback? onListEndReached;

  19.   ///The duration to be used for throttling the scroll notification.
  20.   ///Defaults to 200 milliseconds.
  21.   final Duration throttleDuration;

  22.   ///The axis along which the scroll view scrolls.
  23.   final Axis scrollDirection;

  24.   ///The function that defines the area within which the widgets should be notified
  25.   ///as inView.
  26.   final IsInViewPortCondition isInViewPortCondition;

  27.   InViewNotifier({
  28.     Key? key,
  29.     required this.child,
  30.     this.initialInViewIds = const [],
  31.     this.endNotificationOffset = 0.0,
  32.     this.onListEndReached,
  33.     this.throttleDuration = const Duration(milliseconds: 200),
  34.     this.scrollDirection = Axis.vertical,
  35.     required this.isInViewPortCondition,
  36.   })  : assert(endNotificationOffset >= 0.0),
  37.         super(key: key);

  38.   @override
  39.   _InViewNotifierState createState() => _InViewNotifierState();

  40.   static InViewState? of(BuildContext context) {
  41.     final widget = context
  42.         .getElementForInheritedWidgetOfExactType<InheritedInViewWidget>()!
  43.         .widget as InheritedInViewWidget;
  44.     return widget.inViewState;
  45.   }
  46. }

  47. class _InViewNotifierState extends State<InViewNotifier> {
  48.   InViewState? _inViewState;
  49.   StreamController<ScrollNotification>? _streamController;

  50.   @override
  51.   void initState() {
  52.     super.initState();
  53.     _initializeInViewState();
  54.     _startListening();
  55.   }

  56.   @override
  57.   void didUpdateWidget(InViewNotifier oldWidget) {
  58.     if (oldWidget.throttleDuration != widget.throttleDuration) {
  59.       //when throttle duration changes, close the existing stream controller if exists
  60.       //and start listening to a stream that is throttled by new duration.
  61.       _streamController?.close();
  62.       _startListening();
  63.     }

  64.     super.didUpdateWidget(oldWidget);
  65.   }

  66.   @override
  67.   void dispose() {
  68.     _inViewState?.dispose();
  69.     _inViewState = null;
  70.     _streamController?.close();
  71.     super.dispose();
  72.   }

  73.   void _startListening() {
  74.     _streamController = StreamController<ScrollNotification>();

  75.     _streamController!.stream
  76.         .audit(widget.throttleDuration)
  77.         .listen(_inViewState!.onScroll);
  78.   }

  79.   void _initializeInViewState() {
  80.     _inViewState = InViewState(
  81.       intialIds: widget.initialInViewIds,
  82.       isInViewCondition: widget.isInViewPortCondition,
  83.     );
  84.   }

  85.   @override
  86.   Widget build(BuildContext context) {
  87.     return InheritedInViewWidget(
  88.       inViewState: _inViewState,
  89.       child: NotificationListener<ScrollNotification>(
  90.         child: widget.child,
  91.         onNotification: (ScrollNotification notification) {
  92.           late bool isScrollDirection;
  93.           //the direction of user scroll up, down, left, right.
  94.           final AxisDirection scrollDirection =
  95.               notification.metrics.axisDirection;

  96.           switch (widget.scrollDirection) {
  97.             case Axis.vertical:
  98.               isScrollDirection = scrollDirection == AxisDirection.down ||
  99.                   scrollDirection == AxisDirection.up;
  100.               break;
  101.             case Axis.horizontal:
  102.               isScrollDirection = scrollDirection == AxisDirection.left ||
  103.                   scrollDirection == AxisDirection.right;
  104.               break;
  105.           }
  106.           final double maxScroll = notification.metrics.maxScrollExtent;

  107.           //end of the listview reached
  108.           if (isScrollDirection &&
  109.               maxScroll - notification.metrics.pixels <=
  110.                   widget.endNotificationOffset) {
  111.             if (widget.onListEndReached != null) {
  112.               widget.onListEndReached!();
  113.             }
  114.           }

  115.           //when user is not scrolling
  116.           if (notification is UserScrollNotification &&
  117.               notification.direction == ScrollDirection.idle) {
  118.             if (!_streamController!.isClosed && isScrollDirection) {
  119.               _streamController!.add(notification);
  120.             }
  121.           }

  122.           if (!_streamController!.isClosed && isScrollDirection) {
  123.             _streamController!.add(notification);
  124.           }
  125.           return false;
  126.         },
  127.       ),
  128.     );
  129.   }
  130. }

  131. ///The function that defines the area within which the widgets should be notified
  132. ///as inView.
  133. typedef bool IsInViewPortCondition(
  134.     double deltaTop,
  135.     double deltaBottom,
  136.     double viewPortDimension,
  137.     );
复制代码



使用方法:
  1. child: InViewNotifier(
  2.                       /定义什么情况算"进入视野"
  3.                       isInViewPortCondition: (double deltaTop, double deltaBottom, double vpHeight) {
  4.                         // return deltaTop < (0.5 * vpHeight) && deltaBottom > (0.5 * vpHeight);

  5.                         //底部不准确 -取 bar 高度
  6.                         return deltaTop > 0 && deltaBottom < vpHeight -66.h-ScreenUtil().statusBarHeight; //deltaTop < (0.4 * vpHeight);
  7.                       },

  8.                       throttleDuration: Duration.zero, //取消延迟
  9.                       child: RefreshConfiguration(
  10.                         springDescription: SpringDescription.withDampingRatio(
  11.                           mass: 1.0, // 减小质量,让物体更轻巧、更容易被拉动
  12.                           stiffness: 200, // 大幅提升刚度,让回弹更有力、更迅速
  13.                           ratio: 1.0, // 保持临界阻尼,确保不回弹
  14.                         ),
  15.                         child: SmartRefresher(
  16.                           controller: logic.refreshCtrl,
  17.                           header: const MomentsIndicator(),
  18.                           // header: const MaterialClassicHeader(color: Color(0xFF041d31)),
  19.                           footer: IMViews.buildFooter(),
  20.                           onRefresh: logic.queryWorkingCircleList,
  21.                           onLoading: logic.loadMore,
  22.                           //  enablePullUp: true,
  23.                           child: CustomScrollView(
复制代码
ok这样就行了
评论
登录 后才能评论

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2026-7-1 23:55, Processed in 0.248142 second(s), 30 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表