OSA实战笔记一
本文是我在实际项目开发中,总结和归纳的笔记,主要记录了OSA常用的函数、参数以及具体的代码示例。
1、ScrollTo(int cellIndex, float normalizedOffsetFromViewportStart = 0, float
normalizedPositionOfItemPivotToUse = 0)
功能:
使列表滚动⾄某⼀个cell;
参数:
cellIndex:cell的序号;
normalizedOffsetFromViewportStart:纵向列表距顶部的偏移量,就是Top值;横向列表cell
滚动到left、center、right偏移量;
normalizedPositionOfItemPivotToUse:cell的锚点;
例:
纵向列表ScrollTo(0,30),列表移⾄第1个cell,距顶部30像素;
横向列表ScrollTo(4,0.5f,0.5f),列表移⾄第5个cell,cell的中⼼显⽰于列表的中间;
2、SmoothScrollTo(intitemIndex, float duration, float
normalizedOffsetFromViewportStart = 0f, float normalizedPositionOfItemPivotToUse
= 0f, Func<float, bool> onProgress = null,Action onDone = null,bool
overrideCurrentScrollingAnimation = false)
功能:
使列表缓动⾄某⼀个cell;
参数:
itemIndex:cell的序号;
duration:缓动时间;
normalizedOffsetFromViewportStart:纵向列表距顶部的偏移量,就是Top值;横向列表cell
滚动到left、center、right偏移量;
normalizedPositionOfItemPivotToUse:cell的锚点;
onProgress:缓动中调⽤;
onDone:缓动结束调⽤;
overrideCurrentScrollingAnimation:是否覆盖当前滚动;
⽰例可以参考ScrollTo;
3、Grid单预设尺⼨修改的实现;
a、⾸先在UpdateCellViewsHolder中判断正⽅、⻓⽅模型,修改Grid尺⼨;
1 if(xml.isSpecial)
2 {
3 newOrRecycled.rootLayoutElement.preferredWidth = 508;
4 newOrRecycled.rootLayoutElement.preferredHeight = 622;
5 }
6 else
7 {
8 newOrRecycled.rootLayoutElement.preferredWidth = 508;
9 newOrRecycled.rootLayoutElement.preferredHeight = 807;
10 }
b、接着给Grid的Group添加ContentSizeFitter,让Group的⾼度随Grid改变;
1 public override void CollectViews()
2 {
3 base.CollectViews();
4 // Since the group views holder is created at runtime internally, we also
need to add the CSF by code
5 contentSizeFitterComponent =
root.gameObject.AddComponent<UnityEngine.UI.ContentSizeFitter>();
6 contentSizeFitterComponent.verticalFit =
UnityEngine.UI.ContentSizeFitter.FitMode.PreferredSize;
7
8 // Keeping the CSF always enabled is easier to manage. We'll trigger a Twin
pass very frequently, anyway
9 contentSizeFitterComponent.enabled = true;
10 }
4、Grid缩放滚动效果的实现;
a、⾸先,插⼊数据时,为了让Cell都可以滚动⾄列表中间位置,在数据前后分别插⼊3个空数
据;
1 //切换成就信息
2 awardList.Data.List.Clear();
3 awardList.Data.List.Add(new AchieveTarg() { id = 0 });
4 awardList.Data.List.Add(new AchieveTarg() { id = 0 });
5 awardList.Data.List.Add(new AchieveTarg() { id = 0 });
6 foreach (AchieveTarg atarg in data.data)
7 {
8 awardList.Data.List.Add(atarg);
9 }
10 awardList.Data.List.Add(new AchieveTarg() { id = 0 });
11 awardList.Data.List.Add(new AchieveTarg() { id = 0 });
12 awardList.Data.List.Add(new AchieveTarg() { id = 0 });13 awardList.Data.NotifyListChangedExternally();
b、选中时记录cellIndex修改animating为true,在Update中处理动效;
1 if (animating)
2 {
3 //通过间隔时间,计算size的渐变值
4 float elapsedTime = Time - animStart;
5 float t01 = elapsedTime / 0.05f;
6 if (t01 >= 1f)
7 {
8 t01 = 1f;
9 animating = false;
10 }
11 else
12 t01 = Mathf.Sqrt(t01);
13 float size = Mathf.Lerp(120f, 180f, t01);
14 //改变Cell的尺⼨
15 bool accepted = awardList.HandleSizeChangeRequest(awardCellIndex, size);
16 if (!accepted)
17 animating = false;
18 if (!animating)
19 {
20 //当前选择Cell尺⼨修改完成,恢复上⼀个选择Cell的尺⼨
21 awardList.OnExpandedStateChanged(awardCellIndex);
22 //必须等所有尺⼨修改完成后,进⾏位置缓动,尺⼨改变会影响位置偏移的计算
23 if (sReason.Equals("click"))
24 {
25 awardList.SmoothScrollTo(awardCellIndex, 0.3f, 0.5f, 0f);
26 }
27 else
28 {
29 awardList.ScrollTo(awardCellIndex, 0.5f, 0f);
30 }
31 }
32 }
c、在Adapter中添加Cell的尺⼨改变函数;
1 public bool HandleSizeChangeRequest(int itemIndex, float newSize)
2 {
3 if (itemIndex < Data.Count)
4 {
5 //找到CellHolder修改尺⼨
6 var modelOfExpandingItem = Data[itemIndex] as AchieveTarg;
7 var viewholder = GetItemViewsHolderIfVisible(itemIndex);
8 if (viewholder != null)
9 {10 viewholder.ScaleTo(newSize / modelOfExpandingItem.nonExpandedSize);
11 }
12 //刷新布局
13 RequestChangeItemSizeAndUpdateLayout(itemIndex, newSize);
14 if (nClickIdx != -1)
15 {
16 //如果有原选中Cell,反算出需要缩⼩的渐变值
17 float expandingItem_ExpandedAmount01 = newSize /
(modelOfExpandingItem.nonExpandedSize * _Params.itemExpandFactor);
18 var modelOfExpandedItem = Data[nClickIdx] as AchieveTarg;
19 var expandedItemNewRequestedSize =
20 Mathf.Lerp(
21 modelOfExpandedItem.nonExpandedSize,
22 modelOfExpandedItem.nonExpandedSize *
_Params.itemExpandFactor,
23 1f - expandingItem_ExpandedAmount01
24 );
25 //找到CellHolder修改尺⼨
26 viewholder = GetItemViewsHolderIfVisible(nClickIdx);
27 if (viewholder != null)
28 {
29 viewholder.ScaleTo(expandedItemNewRequestedSize /
modelOfExpandingItem.nonExpandedSize);
30 }
31 //刷新布局
32 RequestChangeItemSizeAndUpdateLayout(nClickIdx,
expandedItemNewRequestedSize);
33 }
34 return true;
35 }
36 return false;
37 }
38
39 public void OnExpandedStateChanged(int itemIndex)
40 {
41 if (itemIndex < Data.Count)
42 {
43 //找到数据源,标记为放⼤状态;
44 var asExpandableModel = Data[itemIndex] as AchieveTarg;
45 if (asExpandableModel == null) return;
46 if (asExpandableModel.id == 0) return;
47 asExpandableModel.expanded = true;
48 if (nClickIdx != -1)
49 {
50 //原选中Cell数据源标记为正常状态
51 var lastExpandedModel = Data[nClickIdx] as AchieveTarg;
52 lastExpandedModel.expanded = false;
53 }
54 //修改选中Cell的Index55 nClickIdx = itemIndex;
56 if(oClickCell != null)
57 {
58 //还原原选中Cell的size
59 oClickCell.ScaleTo(1f);
60 }
61 //重置选中的Cell
62 oClickCell = GetItemViewsHolderIfVisible(nClickIdx);
63 }
64 }
d、拖拽⾄左右两端回弹的处理;
1 public override void OnEndDrag(PointerEventData eventData)
2 {
3 base.OnEndDrag(eventData);
4 //拖拽结束进⼊回弹检测;
5 ischeck = true;
6 }
7
8 protected override void LateUpdate()
9 {
10 base.LateUpdate();
11 if(ischeck && Velocity.x == 0)
12 {
13 ischeck = false;
14 double dnow = GetNormalizedPosition();
15 int nall = (int)Math.Ceiling(dnow * Data.List.Count);
16 if (nall < 3)
17 SmoothScrollTo(3, 0.2f, 0.5f, 0.5f);
18 else if (nall > Data.List.Count - 3)
19 SmoothScrollTo(Data.List.Count - 4, 0.2f, 0.5f, 0.5f);
20 }
21 }