using System; using System.Linq; using UnityEngine; using UnityEngine.UI; namespace UIWidgets { public class ListViewCustomHeight : ListViewCustom where TComponent : ListViewItem where TItem : IItemHeight { [Tooltip("Calculate height automaticly without using IListViewItemHeight.Height.")] [SerializeField] private bool ForceAutoHeightCalculation = true; private TComponent defaultItemCopy; private RectTransform defaultItemCopyRect; private bool IsCanCalculateHeight; private LayoutGroup defaultItemlayoutGroup; protected TComponent DefaultItemCopy { get { if (defaultItemCopy == null) { defaultItemCopy = UnityEngine.Object.Instantiate(DefaultItem); defaultItemCopy.transform.SetParent(DefaultItem.transform.parent); Utilites.FixInstantiated(DefaultItem, defaultItemCopy); defaultItemCopy.gameObject.name = "DefaultItemCopy"; defaultItemCopy.gameObject.SetActive(false); } return defaultItemCopy; } } protected RectTransform DefaultItemCopyRect { get { if (defaultItemCopyRect == null) { defaultItemCopyRect = defaultItemCopy.transform as RectTransform; } return defaultItemCopyRect; } } public ListViewCustomHeight() { IsCanCalculateHeight = typeof(IListViewItemHeight).IsAssignableFrom(typeof(TComponent)); } protected override void Awake() { Start(); } protected override void CalculateMaxVisibleItems() { SetItemsHeight(base.DataSource); float height = scrollHeight; maxVisibleItems = base.DataSource.OrderBy(GetItemHeight).TakeWhile(delegate(TItem x) { height -= x.Height; return height > 0f; }).Count() + 2; } protected override void CalculateItemSize() { RectTransform rectTransform = DefaultItem.transform as RectTransform; ILayoutElement[] source = rectTransform.GetComponents(); if (itemHeight == 0f) { float num = source.Max((ILayoutElement x) => Mathf.Max(x.minHeight, x.preferredHeight)); itemHeight = ((!(num > 0f)) ? rectTransform.rect.height : num); } if (itemWidth == 0f) { float num2 = source.Max((ILayoutElement x) => Mathf.Max(x.minWidth, x.preferredWidth)); itemWidth = ((!(num2 > 0f)) ? rectTransform.rect.width : num2); } } protected override void ScrollTo(int index) { if (CanOptimize()) { float scrollValue = GetScrollValue(); float num = GetScrollValue() + scrollHeight; float num2 = ItemStartAt(index); float num3 = ItemEndAt(index) + LayoutBridge.GetMargin(); if (num2 < scrollValue) { SetScrollValue(num2); } else if (num3 > num) { SetScrollValue(num3 - GetScrollSize()); } } } protected override float CalculateBottomFillerSize() { if (bottomHiddenItems == 0) { return 0f; } float num = base.DataSource.GetRange(topHiddenItems + visibleItems, bottomHiddenItems).SumFloat(GetItemHeight); return Mathf.Max(0f, num + LayoutBridge.GetSpacing() * (float)(bottomHiddenItems - 1)); } protected override float CalculateTopFillerSize() { if (topHiddenItems == 0) { return 0f; } float num = base.DataSource.GetRange(0, topHiddenItems).SumFloat(GetItemHeight); return Mathf.Max(0f, num + LayoutBridge.GetSpacing() * (float)(topHiddenItems - 1)); } private float GetItemHeight(TItem item) { return item.Height; } private float ItemStartAt(int index) { float num = base.DataSource.GetRange(0, index).SumFloat(GetItemHeight); return num + LayoutBridge.GetSpacing() * (float)index; } private float ItemEndAt(int index) { float num = base.DataSource.GetRange(0, index + 1).SumFloat(GetItemHeight); return num + LayoutBridge.GetSpacing() * (float)index; } public override int Add(TItem item) { if (item == null) { throw new ArgumentNullException("item", "Item is null."); } if (item.Height == 0f) { item.Height = CalculateItemHeight(item); } return base.Add(item); } private void SetItemsHeight(ObservableList items, bool forceUpdate = true) { items.ForEach(delegate(TItem x) { if (x.Height == 0f || forceUpdate) { x.Height = CalculateItemHeight(x); } }); } public override void Resize() { SetItemsHeight(base.DataSource); base.Resize(); } protected override void SetNewItems(ObservableList newItems) { SetItemsHeight(newItems); base.SetNewItems(newItems); } private int GetIndexByHeight(float height) { float spacing = LayoutBridge.GetSpacing(); return base.DataSource.TakeWhile(delegate(TItem item, int index) { height -= item.Height; if (index > 0) { height -= spacing; } return height >= 0f; }).Count(); } protected override int GetLastVisibleIndex(bool strict = false) { int indexByHeight = GetIndexByHeight(GetScrollValue() + scrollHeight); return (!strict) ? (indexByHeight + 2) : indexByHeight; } protected override int GetFirstVisibleIndex(bool strict = false) { int indexByHeight = GetIndexByHeight(GetScrollValue()); if (strict) { return indexByHeight; } return Mathf.Min(indexByHeight, Mathf.Max(0, base.DataSource.Count - visibleItems)); } private float CalculateItemHeight(TItem item) { if (defaultItemlayoutGroup == null) { TComponent val = DefaultItemCopy; defaultItemlayoutGroup = val.GetComponent(); } float num = 0f; if ((!IsCanCalculateHeight || ForceAutoHeightCalculation) && defaultItemlayoutGroup != null) { TComponent val2 = DefaultItemCopy; val2.gameObject.SetActive(true); SetData(DefaultItemCopy, item); defaultItemlayoutGroup.CalculateLayoutInputHorizontal(); defaultItemlayoutGroup.SetLayoutHorizontal(); defaultItemlayoutGroup.CalculateLayoutInputVertical(); defaultItemlayoutGroup.SetLayoutVertical(); num = LayoutUtility.GetPreferredHeight(DefaultItemCopyRect); TComponent val3 = DefaultItemCopy; val3.gameObject.SetActive(false); } else { SetData(DefaultItemCopy, item); num = (DefaultItemCopy as IListViewItemHeight).Height; } return num; } public override void ForEachComponent(Action func) { base.ForEachComponent(func); func(DefaultItemCopy); } } }