-
Notifications
You must be signed in to change notification settings - Fork 483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
根据index获取指定Item,以及ScrollToCell滑动到指定位置而不是顶部 #170
Comments
这里我其实是建议提供数据的时候在外部逻辑里缓存一份,也就是在实现 public Transform GetItemByIndex(int index)
{
return m_Content.GetChild(index - itemTypeStart);
}
比较接近的是
可以考虑监听scrollbar的onValueChanged,在触发拖动的时候检查一下 |
我们也遇到类似的问题,Item它移动到ViewPort中间位置的需求非常普遍 |
手头项目上线压力非常大,抱歉最近一段时间实在抽不出手来处理。如果方便的话可以来个pull request? |
这是我修改的版本,可以适应自动移动到中间、上边或者移动到可视范围内。(性能无法保证,因为可能会出现每个Item的ProvideData执行两次) public enum ScrollMode
{
/// <summary>
/// 滚动到视框的前面(左边或上边),即可以看到的第一个item
/// </summary>
ViewForwards,
/// <summary>
/// 尽量保持原来的状态:如果item在视框内,保持它不动;如果item在视框外,就近将它滚动到视框内
/// </summary>
Stay,
/// <summary>
/// 滚动到视框的中间
/// </summary>
ViewCenter,
}
IEnumerator ScrollToCellCoroutine(int index, float speed,ScrollMode scrollMode)
{
bool needMoving = true;
//if Stay && item in viewRect,do stay
if(speed <= 0)
{
if(scrollMode == ScrollMode.Stay)
{
var m_ItemBounds = GetBounds4Item(index);
if (m_ItemBounds.extents == Vector3.zero && m_ItemBounds.center == Vector3.zero)
RefillCells(index);
else
{
m_ViewBounds = new Bounds(viewRect.rect.center, viewRect.rect.size);
var offset = GetItemViewOffset(m_ItemBounds, m_ViewBounds, scrollMode);
if (offset == 0)
yield break;
}
}
else
{
RefillCells(index);
}
}
while (needMoving && !m_Dragging)
{
float move = 0;
if (index < itemTypeStart && speed > 0)
{
move = -Time.deltaTime * speed;
}
else if (index >= itemTypeEnd && speed > 0)
{
move = Time.deltaTime * speed;
}
else
{
m_ViewBounds = new Bounds(viewRect.rect.center, viewRect.rect.size);
var m_ItemBounds = GetBounds4Item(index);
var offset = GetItemViewOffset(m_ItemBounds, m_ViewBounds, scrollMode);
if (offset == 0f)
break;
// check if we cannot move on
if (totalCount >= 0)
{
var verticalNormalizedPosition = GetVerticalNormalizedPosition();
if (direction == LoopScrollRectDirection.Vertical && ((offset > 0 && verticalNormalizedPosition >= 1) || (offset <= 0 && verticalNormalizedPosition < 0)))
{
break;
}
else
{
var horizontalNormalizedPosition = GetHorizontalNormalizedPosition();
if (direction == LoopScrollRectDirection.Horizontal && ((offset > 0 && horizontalNormalizedPosition >= 1) || (offset < 0 && horizontalNormalizedPosition < 0)))
break;
}
}
float maxMove = Time.deltaTime * speed;
if (speed <= 0)
{
move = offset;
needMoving = false;
}
else if (Mathf.Abs(offset) < maxMove)
{
needMoving = false;
move = offset;
}
else
move = Mathf.Sign(offset) * maxMove;
}
if (move != 0)
{
Vector2 offset = GetVector(move);
m_Content.anchoredPosition += offset;
m_PrevPosition += offset;
m_ContentStartPosition += offset;
UpdateBounds(true);
}
if (speed > 0)
yield return null;
}
StopMovement();
UpdatePrevData();
if(speed <= 0)
{
if(direction == LoopScrollRectDirection.Vertical)
{
if ((!reverseDirection && verticalNormalizedPosition >= 1) || (reverseDirection && verticalNormalizedPosition < 0))
RefillCellsFromEnd();
else if ((!reverseDirection && verticalNormalizedPosition < 0) || (reverseDirection && verticalNormalizedPosition >= 1))
RefillCells();
}
else
{
if((!reverseDirection && horizontalNormalizedPosition >= 1) || (reverseDirection && horizontalNormalizedPosition < 0))
RefillCellsFromEnd();
else if ((!reverseDirection && horizontalNormalizedPosition < 0) || (reverseDirection && horizontalNormalizedPosition >= 1))
RefillCells();
}
}
}
float GetItemViewOffset(Bounds itemBounds, Bounds viewBounds, ScrollMode scrollMode)
{
var offset = 0.0f;
if (direction == LoopScrollRectDirection.Vertical)
{
switch (scrollMode)
{
case ScrollMode.ViewForwards:
offset = reverseDirection ? (viewBounds.min.y - itemBounds.min.y) : (viewBounds.max.y - itemBounds.max.y);
break;
case ScrollMode.Stay:
if (viewBounds.max.y > itemBounds.max.y && viewBounds.min.y < itemBounds.min.y)
offset = 0;
else if (viewBounds.max.y < itemBounds.max.y)
offset = viewBounds.max.y - itemBounds.max.y;
else
offset = viewBounds.min.y - itemBounds.min.y;
break;
case ScrollMode.ViewCenter:
offset = viewBounds.center.y - itemBounds.center.y;
break;
}
}
else
{
switch (scrollMode)
{
case ScrollMode.ViewForwards:
offset = reverseDirection ? (itemBounds.max.x - viewBounds.max.x) : (itemBounds.min.x - viewBounds.min.x);
break;
case ScrollMode.Stay:
if (viewBounds.max.x > itemBounds.max.x && viewBounds.min.x < itemBounds.min.x)
offset = 0f;
else if (viewBounds.min.x > itemBounds.min.x)
offset = itemBounds.min.x - viewBounds.min.x;
else
offset = itemBounds.max.x - viewBounds.max.x;
break;
case ScrollMode.ViewCenter:
offset = itemBounds.center.x - viewBounds.center.x;
break;
}
}
return offset;
} |
感谢~ 我看了下确实就是你实现的这个路子(核心是要用center比较)。 master分支提交了版本,可以先看看~我自己这个礼拜再都构造一些极端用例测试下 |
参考你的实现,补全了下 |
大佬你好,我现在在用这份插件制作无限循环列表,发现:
The text was updated successfully, but these errors were encountered: