standby method

dynamic standby({
  1. BuildContext? sliverContext,
  2. bool isRemove = false,
  3. int changeCount = 1,
  4. ChatScrollObserverHandleMode mode = ChatScrollObserverHandleMode.normal,
  5. int refItemRelativeIndex = 0,
  6. int refItemRelativeIndexAfterUpdate = 0,
})

Prepare to adjust position for sliver.

The changeCount parameter is used only when isRemove parameter is false.

The mode parameter is used to specify the processing mode.

refItemRelativeIndex parameter and refItemRelativeIndexAfterUpdate parameter are only used when the mode is ChatScrollObserverHandleMode.specified. Usage: When you insert a new message, assign refItemRelativeIndex to the index of the reference message (latest message) before insertion, and assign refItemRelativeIndexAfterUpdate to the index of the reference message after insertion, they refer to the index of the same message.

Implementation

standby({
  BuildContext? sliverContext,
  bool isRemove = false,
  int changeCount = 1,
  ChatScrollObserverHandleMode mode = ChatScrollObserverHandleMode.normal,
  int refItemRelativeIndex = 0,
  int refItemRelativeIndexAfterUpdate = 0,
}) {
  innerMode = mode;
  this.isRemove = isRemove;
  this.changeCount = changeCount;
  observeSwitchShrinkWrap();

  final firstItemModel = observerController.observeFirstItem(
    sliverContext: sliverContext,
  );
  if (firstItemModel == null) return;
  int _innerRefItemIndex;
  int _innerRefItemIndexAfterUpdate;
  double _innerRefItemLayoutOffset;
  switch (mode) {
    case ChatScrollObserverHandleMode.normal:
      _innerRefItemIndex = firstItemModel.index;
      _innerRefItemIndexAfterUpdate = _innerRefItemIndex + changeCount;
      _innerRefItemLayoutOffset = firstItemModel.layoutOffset;
      break;
    case ChatScrollObserverHandleMode.generative:
      int index = firstItemModel.index + changeCount;
      final model = observerController.observeItem(
        sliverContext: sliverContext,
        index: index,
      );
      if (model == null) return;
      _innerRefItemIndex = index;
      _innerRefItemIndexAfterUpdate = index;
      _innerRefItemLayoutOffset = model.layoutOffset;
      break;
    case ChatScrollObserverHandleMode.specified:
      int index = firstItemModel.index + refItemRelativeIndex;
      final model = observerController.observeItem(
        sliverContext: sliverContext,
        index: index,
      );
      if (model == null) return;
      _innerRefItemIndex = index;
      _innerRefItemIndexAfterUpdate =
          firstItemModel.index + refItemRelativeIndexAfterUpdate;
      _innerRefItemLayoutOffset = model.layoutOffset;
      break;
  }
  // Record value.
  innerIsNeedFixedPosition = true;
  innerRefItemIndex = _innerRefItemIndex;
  innerRefItemIndexAfterUpdate = _innerRefItemIndexAfterUpdate;
  innerRefItemLayoutOffset = _innerRefItemLayoutOffset;

  // When the heights of items are similar, the viewport will not call
  // [performLayout], In this case, the [adjustPositionForNewDimensions] of
  // [ScrollPhysics] will not be called, which makes the function of keeping
  // position invalid.
  //
  // So here let it record a layout-time correction to the scroll offset, and
  // call [markNeedsLayout] to prompt the viewport to be re-layout to solve
  // the above problem.
  //
  // Related issue
  // https://github.com/fluttercandies/flutter_scrollview_observer/issues/64
  final ctx = observerController.fetchSliverContext();
  if (ctx == null) return;
  final obj = ObserverUtils.findRenderObject(ctx);
  if (obj == null) return;
  final viewport = ObserverUtils.findViewport(obj);
  if (viewport == null) return;
  if (!viewport.offset.hasPixels) return;
  viewport.offset.correctBy(0);
  viewport.markNeedsLayout();
}