Created
February 16, 2021 22:16
-
-
Save skjalgsm/1f48219306861081fb6f4b39c971050b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary>Only works on vertical scroll views</summary> | |
public class TableStickyRow : MonoBehaviour | |
{ | |
[SerializeField] | |
RectTransform stickyPrefab = null; | |
//Todo: Set this in another way | |
[SerializeField] | |
private int stickyIndex; | |
ITableAdapter tableAdapter; | |
TableParams tableParams; | |
Type viewHolderType; | |
TupleViewsHolder stickyRow; | |
/// <summary>If the header should have a different model-to-view binding logic, use this</summary> | |
public void InitWithCustomItemViewsHolder<TCustomItemViewsHolder>(ITableAdapter hierarchyOSA) | |
where TCustomItemViewsHolder : AbstractViewsHolder, ITupleProvider | |
{ | |
Init(hierarchyOSA, typeof(TCustomItemViewsHolder)); | |
} | |
public void InitWithSameItemViewsHolder(ITableAdapter hierarchyOSA) | |
{ | |
Init(hierarchyOSA, hierarchyOSA.GetViewsHolderType()); | |
} | |
void Init(ITableAdapter adapter, Type viewHolderItemType) | |
{ | |
tableAdapter = adapter; | |
viewHolderType = viewHolderItemType; | |
tableParams = tableAdapter.BaseParameters as TableParams; | |
tableAdapter.ScrollPositionChanged -= OnScrollPositionChanged; | |
tableAdapter.ScrollPositionChanged += OnScrollPositionChanged; | |
if (stickyRow == null) | |
{ | |
stickyRow = CreateStickyRow(); | |
} | |
ManageSticky(); | |
} | |
TupleViewsHolder CreateStickyRow() | |
{ | |
var instance = Activator.CreateInstance(viewHolderType) as TupleViewsHolder; | |
var headerAsAbstractVh = instance as AbstractViewsHolder; | |
// Index is never stored. it's retrieved only on expand/collapse, since it's currently expensive to get it | |
headerAsAbstractVh.Init(stickyPrefab, tableAdapter.BaseParameters.Viewport, stickyIndex); | |
headerAsAbstractVh.root.SetAsLastSibling(); | |
#if UNITY_EDITOR | |
headerAsAbstractVh.root.name = "Sticky Row"; | |
#endif | |
// Positioning a views holder. Taken from OSA.AddViewsHolderAndMakeVisible() method in OSAInternal.cs (15-Feb-19, 16:33) | |
var layoutInfo = tableAdapter.GetLayoutInfoReadonly(); | |
SetStickyInset(instance, layoutInfo.startEdge, layoutInfo.transvStartEdge); | |
DeactivateVH(instance); | |
return instance; | |
} | |
private void OnScrollPositionChanged(double position) | |
{ | |
if (tableAdapter == null) // not ready yet | |
return; | |
ManageSticky(); | |
} | |
private static void ActivateVH(TupleViewsHolder viewHolder) | |
{ | |
viewHolder.root.gameObject.SetActive(true); | |
} | |
private static void DeactivateVH(TupleViewsHolder viewHolder) | |
{ | |
viewHolder.root.gameObject.SetActive(false); | |
} | |
private void SetStickyInset(TupleViewsHolder sticky, RectTransform.Edge startEdge, RectTransform.Edge transvStartEdge) | |
{ | |
var layoutInfo = tableAdapter.GetLayoutInfoReadonly(); | |
sticky.root.anchorMin = sticky.root.anchorMax = layoutInfo.constantAnchorPosForAllItems; | |
// Positioning a views holder. Taken from OSA.AddViewsHolderAndMakeVisible() method in OSAInternal.cs (15-Feb-19, 16:33) | |
sticky.root.SetInsetAndSizeFromParentEdgeWithCurrentAnchors(startEdge, 0, tableAdapter.BaseParameters.DefaultItemSize); | |
if (layoutInfo.transversalPaddingContentStart == -1d) | |
throw new OSAException("transversalPaddingContentStart is not allowed to be -1 when using " + typeof(TableStickyRow).Name); | |
sticky.root.SetInsetAndSizeFromParentEdgeWithCurrentAnchors(transvStartEdge, (float)layoutInfo.transversalPaddingContentStart, (float)layoutInfo.itemsConstantTransversalSize); | |
} | |
private void ManageSticky() | |
{ | |
// Nothing to show when sticky index is out of bounds | |
int itemsCount = tableAdapter.GetItemsCount(); | |
if (stickyIndex < 0 || stickyIndex >= itemsCount) | |
{ | |
DeactivateVH(stickyRow); | |
return; | |
} | |
//Sticky row always shows | |
ActivateVH(stickyRow); | |
stickyRow.ItemIndex = stickyIndex; | |
stickyRow.UpdateViews(tableAdapter.Tuples.GetTuple(stickyIndex), tableAdapter.Columns); | |
var viewHolder = tableAdapter.GetBaseItemViewsHolderIfVisible(stickyIndex); | |
if (viewHolder != null) | |
{ | |
//Debug.Log("view holder is not null (already showing)"); | |
float headerHeight = tableParams.Table.ColumnsTupleSize; | |
//Debug.Log("headerHeight: " + headerHeight); | |
float amountBeforeViewport = -tableAdapter.GetItemRealInsetFromParentStart(viewHolder.root); | |
//Debug.Log("amountBeforeViewport: " + amountBeforeViewport); | |
bool isRowVisible = amountBeforeViewport <= -headerHeight; | |
//Debug.Log("isRowVisible: " + isRowVisible + " = " + amountBeforeViewport + " <= " + -headerHeight); | |
//_StickyRow.root.SetInsetAndSizeFromParentEdge(edge, edge == RectTransform.Edge.Bottom ? 0 : _Params.Table.ColumnsTupleSize, _Params.DefaultItemSize); | |
float amountAfterViewport = -tableAdapter.GetItemRealInsetFromParentEnd(viewHolder.root); | |
//Debug.Log("amountAfterViewport" + amountAfterViewport); | |
isRowVisible &= amountAfterViewport < 0; | |
if (isRowVisible) | |
{ | |
//Debug.Log("view holder is not null (already showing), so we disable."); | |
stickyRow.root.anchorMin = viewHolder.root.anchorMin; | |
stickyRow.root.anchorMax = viewHolder.root.anchorMax; | |
stickyRow.root.sizeDelta = viewHolder.root.sizeDelta; | |
stickyRow.root.anchoredPosition = viewHolder.root.anchoredPosition; | |
return; | |
} | |
} | |
//Figure out if its going on top or bottom | |
var firstViewHolder = tableAdapter.GetBaseItemViewsHolder(0); | |
int firstIndex = firstViewHolder.ItemIndex; | |
var lastViewHolder = tableAdapter.GetBaseItemViewsHolder(tableAdapter.VisibleItemsCount - 1); | |
int lastIndex = lastViewHolder.ItemIndex; | |
int closeToFirstIndex = Mathf.Abs(firstIndex - stickyIndex); | |
int closeToLastIndex = Mathf.Abs(lastIndex - stickyIndex); | |
var edge = closeToLastIndex > closeToFirstIndex ? RectTransform.Edge.Top : RectTransform.Edge.Bottom; | |
stickyRow.root.SetInsetAndSizeFromParentEdge(edge, edge == RectTransform.Edge.Bottom ? 0 : tableParams.Table.ColumnsTupleSize, tableParams.DefaultItemSize); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment