standby method
dynamic
standby({
- BuildContext? sliverContext,
- bool isRemove = false,
- int changeCount = 1,
- ChatScrollObserverHandleMode mode = ChatScrollObserverHandleMode.normal,
- int refItemRelativeIndex = 0,
- 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();
}