private void GenerateScrollItem(int index, float position, bool topItem) { int itemType = dataSourceInterface.GetItemType(index); ScrollItemInfo scrollItemInfo = GetPooledObj(itemType); scrollItemInfo.index = index; scrollItemInfo.obj = dataSourceInterface.GetListItem(index, itemType, scrollItemInfo.obj); if (scrollItemInfo.obj == null) { return; } scrollItemInfo.obj.SetActive(true); scrollItemInfo.obj.transform.SetParent(content, false); SetupRectTransform(scrollItemInfo.obj.transform as RectTransform); visibleObjects.Add(scrollItemInfo); if (!CanvasUpdateRegistry.IsRebuildingLayout()) { Canvas.ForceUpdateCanvases(); } PositionScrollItem(scrollItemInfo, position, topItem); UpdateScrollItems(); }
private void ReturnPooledObj(ScrollItemInfo scrollItemInfo) { lock (rObjLock) { scrollItemInfo.obj.SetActive(false); scrollItemInfo.obj.transform.SetParent(pooledObjContainer.transform, false); visibleObjects.Remove(scrollItemInfo); reuseableObjects.Add(scrollItemInfo); } }
private void PositionScrollItem(ScrollItemInfo listItemInfo, float listPos, bool addedItemAtBeginning) { RectTransform objRectT = listItemInfo.obj.transform as RectTransform; float objSize = isVertical ? objRectT.rect.height : objRectT.rect.width; float spacingOffset = 0; if (addedItemAtBeginning) { spacingOffset = isVertical ? scrollRectContent.spacing : -scrollRectContent.spacing; } else if (listItemInfo.index != 0) { spacingOffset = isVertical ? -scrollRectContent.spacing : scrollRectContent.spacing; } float sizeOffset = (addedItemAtBeginning ? objSize : 0); float pos = isVertical ? listPos + spacingOffset + sizeOffset : listPos + spacingOffset - sizeOffset; SetAnchoredPosition(objRectT, pos); if (!cachedSizes.ContainsKey(listItemInfo.index) || objSize != cachedSizes[listItemInfo.index]) { float defaultSize = scrollInfo.usedSavedSize ? scrollInfo.SavedAvgSize : 0; float sizeDifference = objSize - (!cachedSizes.ContainsKey(listItemInfo.index) ? defaultSize : cachedSizes[listItemInfo.index]); Vector2 contentsNewSize = new Vector2(content.sizeDelta.x, content.sizeDelta.y); bool includeSpacing = (!cachedSizes.ContainsKey(listItemInfo.index) && listItemInfo.index != itemCount - 1); if (isVertical) { contentsNewSize.y += sizeDifference + (includeSpacing ? scrollRectContent.spacing : 0); } else { contentsNewSize.x += sizeDifference + (includeSpacing ? scrollRectContent.spacing : 0); } content.sizeDelta = contentsNewSize; if (addedItemAtBeginning) { sizeDifference += (!cachedSizes.ContainsKey(listItemInfo.index) && listItemInfo.index != 0) ? scrollRectContent.spacing : 0; sizeDifference *= isVertical ? 1 : -1; ShiftContentBy(sizeDifference); } scrollInfo.currentTotalSize -= !cachedSizes.ContainsKey(listItemInfo.index) ? 0 : cachedSizes[listItemInfo.index]; scrollInfo.currentTotalSize += objSize; scrollInfo.currentCount += !cachedSizes.ContainsKey(listItemInfo.index) ? 1 : 0; cachedSizes[listItemInfo.index] = objSize; } }
private ScrollItemInfo GetPooledObj(int itemType) { lock (rObjLock) { ScrollItemInfo scrollItemInfo = null; for (int i = 0; i < reuseableObjects.Count; i++) { if (itemType == reuseableObjects[i].itemType) { scrollItemInfo = reuseableObjects[i]; reuseableObjects.RemoveAt(i); break; } } if (scrollItemInfo == null) { scrollItemInfo = new ScrollItemInfo(); scrollItemInfo.itemType = itemType; } return(scrollItemInfo); } }
private bool UpdateScrollItems() { if (itemCount <= 0) { return(false); } float topPosValue = isVertical ? content.anchoredPosition.y : -content.anchoredPosition.x; float bottomPosValue = topPosValue + ViewportSize; int highestIndex = int.MaxValue; int lowestIndex = int.MinValue; float highestVal = float.MinValue; float lowestVal = float.MaxValue; for (int i = visibleObjects.Count - 1; i >= 0; i--) { ScrollItemInfo listItemInfo = visibleObjects[i]; RectTransform childRectT = listItemInfo.obj.transform as RectTransform; float val1 = isVertical ? -1 * childRectT.anchoredPosition.y : childRectT.anchoredPosition.x; float val2 = isVertical ? childRectT.rect.height : childRectT.rect.width; if (val1 < lowestVal) { lowestVal = val1; lowestIndex = listItemInfo.index; } else if (val1 == lowestVal && lowestIndex > listItemInfo.index) { lowestIndex = listItemInfo.index; } if (val1 + val2 > highestVal) { highestVal = val1 + val2; highestIndex = listItemInfo.index; } else if (val1 + val2 == highestVal && highestIndex < listItemInfo.index) { highestIndex = listItemInfo.index; } if (val1 + val2 <= topPosValue || val1 >= bottomPosValue) { ReturnPooledObj(listItemInfo); } } if (lowestVal >= bottomPosValue) { float gapSize = lowestVal - topPosValue; int numItemsInGap = Mathf.CeilToInt(gapSize / scrollInfo.CurrentAvgSize); int gotoIndex = lowestIndex - numItemsInGap; if (gotoIndex < 0) { gotoIndex = 0; } GoToScrollItem(gotoIndex); return(true); } if (lowestVal - scrollRectContent.spacing > topPosValue && lowestIndex > 0) { GenerateScrollItem(lowestIndex - 1, isVertical ? -lowestVal : lowestVal, true); return(true); } if (highestVal <= topPosValue) { float gapSize = topPosValue - highestVal; int numItemsInGap = Mathf.CeilToInt(gapSize / scrollInfo.CurrentAvgSize); int gotoIndex = highestIndex + numItemsInGap; if (gotoIndex >= itemCount) { gotoIndex = itemCount - 1; } GoToScrollItem(gotoIndex); return(true); } if (highestVal + scrollRectContent.spacing < bottomPosValue && highestIndex < itemCount - 1) { GenerateScrollItem(highestIndex + 1, isVertical ? -highestVal : highestVal, false); return(true); } return(false); }