/// <summary> /// <para>An item width/height can be changed with this method. </para> /// <para>Should NOT be called during <see cref="ComputeVisibilityForCurrentPosition(bool, bool, bool)"/>, <see cref="UpdateViewsHolder(TItemViewsHolder)"/>, <see cref="CreateViewsHolder(int)"/> or from any critical view-recycling code. Suggestion: call it from MonBehaviour.Update()</para> /// <para>Will change the size of the item's RectTransform to <paramref name="requestedSize"/> and will shift the other items accordingly, if needed.</para> /// </summary> /// <param name="itemIndex">the index of the item to be resized. It doesn't need to be visible(case in which only the cached size will be updated and, obviously, the visible items will shift accordingly) </param> /// <param name="requestedSize">the height or width (depending on scrollview's orientation)</param> /// <param name="itemEndEdgeStationary">if to grow to the top/left (less common) instead of down/right (more common)</param> /// <returns>the resolved size. This can be slightly different than <paramref name="requestedSize"/> if the number of items is huge (>100k))</returns> public float RequestChangeItemSizeAndUpdateLayout(int itemIndex, float requestedSize, bool itemEndEdgeStationary = false, bool computeVisibility = true) { CancelAnimationsIfAny(); var skipCompute_oldValue = _SkipComputeVisibilityInUpdateOrOnScroll; _SkipComputeVisibilityInUpdateOrOnScroll = true; _Params.scrollRect.StopMovement(); // we don't want a ComputeVisibility() during changing an item's size, so we cut off any inertia int itemIndexInView = _ItemsDesc.GetItemViewIndexFromRealIndex(itemIndex); var viewsHolderIfVisible = GetItemViewsHolderIfVisible(itemIndex); float oldSize = _ItemsDesc[itemIndexInView]; bool vrtContentPanelIsAtOrBeforeEnd = _InternalState.ContentPanelVirtualInsetFromViewportEnd >= 0d; if (requestedSize <= oldSize) // collapsing { if (_InternalState.ContentPanelVirtualInsetFromViewportStart >= 0d) { itemEndEdgeStationary = false; // doesn't make sense to move the start edge if the content pos is at start (or after) } else if (vrtContentPanelIsAtOrBeforeEnd) { itemEndEdgeStationary = true; // doesn't make sense to move the end edge if the content pos is at end (or before) } } float resolvedSize = _InternalState.ChangeItemSizeAndUpdateContentSizeAccordingly( viewsHolderIfVisible, itemIndexInView, requestedSize, itemEndEdgeStationary ); float reportedScrollDelta; if (itemEndEdgeStationary) { reportedScrollDelta = .1f; } else { // If start edge is stationary, either if the item shrinks or expands the reportedDelta should be negative, // indicating that a fake "slight scroll towards end" was done. This triggers a virtualization of the the content's position correctly to compensate for the new ctEnd // and makes any item after it be visible again (in the shirnking case) if it was after viewport reportedScrollDelta = -.1f; // ..but if the ctEnd is fully visible, the items will act as if they're shrinking with itemEndEdgeStationary=true, because the content's end can't exceed the vpEnd if (vrtContentPanelIsAtOrBeforeEnd) { reportedScrollDelta = .1f; } } if (computeVisibility) { ComputeVisibilityForCurrentPosition(true, true, false, reportedScrollDelta); } if (!_CorrectedPositionInCurrentComputeVisibilityPass) { CorrectPositionsOfVisibleItems(false); // itemEndEdgeStationary); } _SkipComputeVisibilityInUpdateOrOnScroll = skipCompute_oldValue; return(resolvedSize); }
public float RequestChangeItemSizeAndUpdateLayout(int itemIndex, float requestedSize, bool itemEndEdgeStationary = false, bool computeVisibility = true) { CancelAnimationsIfAny(); var skipCompute_oldValue = _SkipComputeVisibilityInUpdateOrOnScroll; _SkipComputeVisibilityInUpdateOrOnScroll = true; _Collocation.scrollRect.StopMovement(); int cellIndex = _ItemsDesc.GetItemViewIndexFromRealIndex(itemIndex); var viewsHolderIfVisible = GeUILoopSmartItemIfVisible(itemIndex); float oldSize = _ItemsDesc[cellIndex]; bool vrtContentPanelIsAtOrBeforeEnd = _InternalState.ContentPanelVirtualInsetFromViewportEnd >= 0d; if (requestedSize <= oldSize) // collapsing { if (_InternalState.ContentPanelVirtualInsetFromViewportStart >= 0d) { itemEndEdgeStationary = false; } else if (vrtContentPanelIsAtOrBeforeEnd) { itemEndEdgeStationary = true; } } float resolvedSize = _InternalState.ChangeItemSizeAndUpdateContentSizeAccordingly( viewsHolderIfVisible, cellIndex, requestedSize, itemEndEdgeStationary ); float reportedScrollDelta; if (itemEndEdgeStationary) { reportedScrollDelta = .1f; } else { reportedScrollDelta = -.1f; if (vrtContentPanelIsAtOrBeforeEnd) { reportedScrollDelta = .1f; } } if (computeVisibility) { ComputeVisibilityForCurrentPosition(true, true, false, reportedScrollDelta); } if (!_CorrectedPositionInCurrentComputeVisibilityPass) { CorrectPositionsOfVisibleItems(false); } _SkipComputeVisibilityInUpdateOrOnScroll = skipCompute_oldValue; return(resolvedSize); }