using System.Collections;
|
using System.Collections.Generic;
|
using UnityEngine;
|
using EnhancedUI.EnhancedScroller;
|
using System;
|
using UnityEngine.UI;
|
|
public enum EnhanceLockType
|
{
|
None,
|
LockHorizonRight,
|
LockHorizonLeft,
|
LockVerticalTop,
|
LockVerticalBottom,
|
KeepHorizon,
|
KeepVertical,
|
KeepVertical2,
|
}
|
public class ScrollerController : MonoBehaviour, IEnhancedScrollerDelegate {
|
|
private List<ScrollerData> _data = new List<ScrollerData>();
|
public delegate void OnRefreshCellDelegate(ScrollerDataType type, CellView cell);
|
public event OnRefreshCellDelegate OnRefreshCell;
|
|
public delegate bool OnDynamicCell(ScrollerDataType type,int index,out float height);
|
public event OnDynamicCell OnGetDynamicSize;
|
|
public event Action OnRefreshCompleteEvent;
|
|
public event Action<Vector2> onValueChange;
|
|
|
public EnhancedScrollerCellView GetCellView(EnhancedScroller scroller, int dataIndex, int cellIndex)
|
{
|
CellView cell = GetCellView(scroller, dataIndex);
|
if (!cell.gameObject.activeSelf) cell.SetActive(true);
|
cell.SetData(_data[dataIndex], _data[dataIndex].m_ScrollerType,this);
|
if (_data[dataIndex].OnClick != null) {
|
cell.OnClick = _data[dataIndex].OnClick;
|
}
|
cell.info = _data[dataIndex].info;
|
if (OnRefreshCell != null) {
|
OnRefreshCell(_data[dataIndex].m_ScrollerType, cell);
|
}
|
cell.RefreshUI();
|
return cell;
|
}
|
|
private CellView GetCellView(EnhancedScroller scroller, int dataIndex)
|
{
|
CellView cell = null;
|
switch (_data[dataIndex].m_ScrollerType) {
|
case ScrollerDataType.Header:
|
cell = scroller.GetCellView(m_CellHeaderPrefab) as CellView;
|
break;
|
case ScrollerDataType.Normal:
|
cell = scroller.GetCellView(m_CellNomalPrefab) as CellView;
|
break;
|
case ScrollerDataType.Tail:
|
cell = scroller.GetCellView(m_CellTailPrefab) as CellView;
|
break;
|
case ScrollerDataType.Extra1:
|
cell = scroller.GetCellView(m_CellExtraPrefab1) as CellView;
|
break;
|
case ScrollerDataType.Extra2:
|
cell = scroller.GetCellView(m_CellExtraPrefab2) as CellView;
|
break;
|
case ScrollerDataType.Extra3:
|
cell = scroller.GetCellView(m_CellExtraPrefab3) as CellView;
|
break;
|
}
|
return cell;
|
}
|
|
public float GetCellViewSize(EnhancedScroller scroller, int dataIndex)
|
{
|
if (OnGetDynamicSize != null) {
|
float height = 0;
|
if (OnGetDynamicSize(_data[dataIndex].m_ScrollerType, _data[dataIndex].index,out height)) {
|
return height;
|
}
|
}
|
switch (_data[dataIndex].m_ScrollerType) {
|
case ScrollerDataType.Header:
|
return m_CellHeaderPrefab.height;
|
case ScrollerDataType.Normal:
|
return m_CellNomalPrefab.height;
|
case ScrollerDataType.Tail:
|
return m_CellTailPrefab.height;
|
case ScrollerDataType.Extra1:
|
return m_CellExtraPrefab1.height;
|
case ScrollerDataType.Extra2:
|
return m_CellExtraPrefab2.height;
|
case ScrollerDataType.Extra3:
|
return m_CellExtraPrefab3.height;
|
}
|
return 80;
|
}
|
|
public void OnRefreshCellActive(CellView cell)
|
{
|
if (OnRefreshCell != null) {
|
OnRefreshCell(cell.type, cell);
|
}
|
}
|
|
public int GetNumberOfCells(EnhancedScroller scroller)
|
{
|
return _data.Count;
|
}
|
|
public EnhancedScroller m_Scorller;
|
private ScrollRect m_ScrollRect;
|
public ScrollRect mScrollRect {
|
get {
|
if (m_ScrollRect == null)
|
m_ScrollRect = m_Scorller.GetComponent<ScrollRect>();
|
return m_ScrollRect;
|
}
|
}
|
public CellView m_CellHeaderPrefab;
|
public CellView m_CellNomalPrefab;
|
public CellView m_CellTailPrefab;
|
public CellView m_CellExtraPrefab1;
|
public CellView m_CellExtraPrefab2;
|
public CellView m_CellExtraPrefab3;
|
public int maxCellCnt = 0;
|
public bool fakeMiddleCenter = false; //是否需要假居中, 居中时当cell个数少 尺寸小于最大尺寸时 不可滑动; 只有header类型时才准确
|
int jiaMiddleWithMaxSize = 0; //假居中的最大尺寸,自动设为预制体里的初始尺寸
|
|
public bool horizontal = false;
|
public bool vertical = false;
|
private bool inited = false;
|
private int cacheJump = -1;
|
private void Awake()
|
{
|
m_Scorller.Delegate = this;
|
horizontal = mScrollRect.horizontal;
|
vertical = mScrollRect.vertical;
|
|
mScrollRect.onValueChanged.AddListener(OnValueChangle);
|
|
inited = m_Scorller.inited;
|
m_Scorller.OnFirstLoadAllEvent += OnFirstLoadAllEvent;
|
if (m_Scorller.OnCompLoad == null && !m_Scorller.inited)
|
{
|
m_Scorller.OnCompLoad = OnCompLoad;
|
}
|
HideDefaultCell();
|
}
|
|
private void OnValueChangle(Vector2 delta)
|
{
|
if (onValueChange != null)
|
{
|
onValueChange(delta);
|
}
|
}
|
|
private void OnFirstLoadAllEvent()
|
{
|
if (cacheJump != -1)
|
{
|
JumpIndex(cacheJump);
|
}
|
}
|
|
private void HideDefaultCell()
|
{
|
HideDefaultCell(m_CellHeaderPrefab);
|
HideDefaultCell(m_CellNomalPrefab);
|
HideDefaultCell(m_CellTailPrefab);
|
HideDefaultCell(m_CellExtraPrefab1);
|
HideDefaultCell(m_CellExtraPrefab2);
|
HideDefaultCell(m_CellExtraPrefab3);
|
}
|
|
private void HideDefaultCell(CellView _cell)
|
{
|
if (_cell != null)
|
{
|
_cell.SetActive(false);
|
}
|
}
|
|
List<CellView> list = new List<CellView>();
|
|
private void OnCompLoad()
|
{
|
inited = true;
|
if (_data.Count > 0)
|
{
|
Restart();
|
}
|
}
|
|
public void Refresh()
|
{
|
inited = m_Scorller.inited;
|
if (m_Scorller.OnCompLoad == null && !m_Scorller.inited)
|
{
|
m_Scorller.OnCompLoad = OnCompLoad;
|
}
|
_data.Clear();
|
|
if (!inited)
|
{
|
return;
|
}
|
|
//假居中恢复尺寸
|
if (fakeMiddleCenter && jiaMiddleWithMaxSize != 0)
|
{
|
var rect = (transform as RectTransform);
|
if (horizontal)
|
{
|
rect.sizeDelta = rect.sizeDelta.SetX(jiaMiddleWithMaxSize);
|
}
|
else if (vertical)
|
{
|
rect.sizeDelta = rect.sizeDelta.SetY(jiaMiddleWithMaxSize);
|
}
|
}
|
|
|
if (m_Scorller.LayoutGroup != null)
|
{
|
m_Scorller.LayoutGroup.spacing = m_Scorller.spacing;
|
}
|
|
lastScrollPos = horizontal ? mScrollRect.horizontalNormalizedPosition : mScrollRect.verticalNormalizedPosition;
|
lastContentSize = m_Scorller._ScrollSize;
|
|
mScrollRect.verticalNormalizedPosition = 1;
|
mScrollRect.horizontalNormalizedPosition = 0;
|
|
lastScrollPos = Mathf.Clamp01(lastScrollPos);
|
|
}
|
|
public CellView GetActiveCellView(int _index)
|
{
|
if (m_Scorller == null)
|
{
|
return null;
|
}
|
var _cellView = m_Scorller.GetActiveCellView(_index);
|
if (_cellView != null)
|
{
|
return _cellView as CellView;
|
}
|
return null;
|
}
|
|
public CellView GetActiveCellView(int _index, ScrollerDataType type)
|
{
|
if (m_Scorller == null)
|
{
|
return null;
|
}
|
var views = m_Scorller.GetActiveCellViews();
|
for (int i = 0; i < views.Count; i++)
|
{
|
var _cellView = views[i] as CellView;
|
if (views[i].index == _index && _cellView.type == type)
|
{
|
return _cellView;
|
}
|
}
|
return null;
|
}
|
|
public void AddCell(ScrollerDataType type, int index, Action<CellView> action = null, CellInfo? info = null)
|
{
|
ScrollerData data = null;
|
switch (type) {
|
case ScrollerDataType.Header:
|
data = new ScrollerHeaderData(index, action);
|
break;
|
case ScrollerDataType.Normal:
|
data = new ScrollerNormalData(index, action);
|
break;
|
case ScrollerDataType.Tail:
|
data = new ScrollerTailData(index, action);
|
break;
|
case ScrollerDataType.Extra1:
|
case ScrollerDataType.Extra2:
|
case ScrollerDataType.Extra3:
|
data = new ScrollerExtraData(index, type, action);
|
break;
|
}
|
if (data != null) {
|
data.info = info;
|
_data.Add(data);
|
}
|
}
|
|
public void AddCell(ScrollerDataType type, int index, CellInfo info)
|
{
|
ScrollerData data = null;
|
switch (type) {
|
case ScrollerDataType.Header:
|
data = new ScrollerHeaderData(index);
|
break;
|
case ScrollerDataType.Normal:
|
data = new ScrollerNormalData(index);
|
break;
|
case ScrollerDataType.Tail:
|
data = new ScrollerTailData(index);
|
break;
|
case ScrollerDataType.Extra1:
|
case ScrollerDataType.Extra2:
|
case ScrollerDataType.Extra3:
|
data = new ScrollerExtraData(index, type);
|
break;
|
}
|
if (data != null) {
|
data.info = info;
|
_data.Add(data);
|
}
|
}
|
|
public void OnRefreshAdd()
|
{
|
Restart();
|
}
|
|
public void Restart()
|
{
|
if (!inited) return;
|
|
|
m_Scorller.ReloadData();
|
|
if (fakeMiddleCenter && _data.Count <= maxCellCnt)
|
{
|
//只有设置header时,进行假居中处理才能达到效果
|
if (jiaMiddleWithMaxSize == 0)
|
{
|
jiaMiddleWithMaxSize = (int)m_Scorller.ScrollRectSize;
|
}
|
|
|
var rect = (transform as RectTransform);
|
if (horizontal)
|
{
|
|
rect.sizeDelta = rect.sizeDelta.SetX(Math.Min(jiaMiddleWithMaxSize, (m_CellHeaderPrefab.height + m_Scorller.spacing) * _data.Count - m_Scorller.spacing));
|
}
|
else if (vertical)
|
{
|
rect.sizeDelta = rect.sizeDelta.SetY(Math.Min(jiaMiddleWithMaxSize, (m_CellHeaderPrefab.height + m_Scorller.spacing) * _data.Count - m_Scorller.spacing));
|
}
|
if (rect.sizeDelta.x < jiaMiddleWithMaxSize)
|
{
|
mScrollRect.horizontal = false;
|
mScrollRect.vertical = false;
|
}
|
else
|
{
|
mScrollRect.horizontal = horizontal;
|
mScrollRect.vertical = vertical;
|
}
|
}
|
else if (maxCellCnt != 0 && _data.Count <= maxCellCnt)
|
{
|
mScrollRect.horizontal = false;
|
mScrollRect.vertical = false;
|
}
|
else
|
{
|
mScrollRect.horizontal = horizontal;
|
mScrollRect.vertical = vertical;
|
}
|
|
ResetScrollPos();
|
|
lastDataCnt = _data.Count;
|
}
|
|
public void JumpIndex(int index)
|
{
|
if (!inited)
|
{
|
cacheJump = index;
|
return;
|
}
|
if ((index < 0 || index >= _data.Count) && !m_Scorller.Loop)
|
{
|
return;
|
}
|
var _size = m_Scorller.GetScrollPositionForDataIndex(index, EnhancedScroller.CellViewPositionEnum.Before);
|
var _contentSize = vertical ? m_Scorller.scrollRect.content.rect.size.y : m_Scorller.scrollRect.content.rect.size.x;
|
if (_contentSize - _size < m_Scorller.ScrollRectSize)
|
{
|
_size = _contentSize - m_Scorller.ScrollRectSize;
|
}
|
m_Scorller.ScrollPosition = _size;
|
}
|
|
public void JumpIndex(int index,ref float offset)
|
{
|
if (!inited)
|
{
|
cacheJump = index;
|
return;
|
}
|
if ((index < 0 || index >= _data.Count) && !m_Scorller.Loop)
|
{
|
return;
|
}
|
var _size = m_Scorller.GetScrollPositionForDataIndex(index, EnhancedScroller.CellViewPositionEnum.Before);
|
var _contentSize = vertical ? m_Scorller.scrollRect.content.rect.size.y : m_Scorller.scrollRect.content.rect.size.x;
|
offset = 0f;
|
if (_contentSize - _size < m_Scorller.ScrollRectSize)
|
{
|
offset = _size - (_contentSize - m_Scorller.ScrollRectSize);
|
_size = _size - offset;
|
}
|
m_Scorller.ScrollPosition = _size;
|
}
|
|
public float GetCellSize(int _dataIndex)
|
{
|
if (!inited)
|
{
|
return 0;
|
}
|
return m_Scorller.GetCellSize(_dataIndex);
|
}
|
|
public void JumpIndex(float _delta, float _time, EnhancedScroller.TweenType _tweenType)
|
{
|
if (!inited)
|
{
|
return;
|
}
|
m_Scorller.Tween(_tweenType, _time, m_Scorller.ScrollPosition + _delta);
|
}
|
|
public float GetPreScrollSize(int index)
|
{
|
float _size = 0;
|
for (int i = 0; i < _data.Count; i++) {
|
_size += GetCellViewSize(m_Scorller, i);
|
if (i >= index) break;
|
}
|
return _size;
|
}
|
|
public void RefreshSingleCellView(int _index)
|
{
|
CellView _cell;
|
if (IsDisplay(_index, out _cell))
|
{
|
_cell.RefreshCellView();
|
}
|
}
|
|
public bool IsDisplay(int index, out CellView _cell)
|
{
|
_cell = null;
|
if (m_Scorller == null)
|
{
|
return false;
|
}
|
var _base = m_Scorller.GetActiveCellView(index);
|
if (_base != null)
|
{
|
_cell = _base as CellView;
|
return true;
|
}
|
return false;
|
}
|
|
public bool IsDisplay(int index)
|
{
|
if (m_Scorller == null)
|
{
|
return false;
|
}
|
return m_Scorller.GetActiveCellView(index) != null;
|
}
|
|
public bool OutOfStartView(int index)
|
{
|
float value=m_Scorller.GetScrollPositionForCellViewIndex(index, EnhancedScroller.CellViewPositionEnum.Before);
|
if (value < m_Scorller.ScrollPosition) {
|
return true;
|
}
|
return false;
|
}
|
|
private void OnDestroy()
|
{
|
if (m_Scorller != null)
|
{
|
m_Scorller.OnFirstLoadAllEvent -= OnFirstLoadAllEvent;
|
}
|
}
|
|
public void OnRebuildComplete()
|
{
|
if (OnRefreshCompleteEvent != null)
|
{
|
OnRefreshCompleteEvent();
|
}
|
}
|
|
#region 滚动定位
|
|
private EnhanceLockType m_lockType = EnhanceLockType.None;
|
|
public EnhanceLockType lockType {
|
get { return m_lockType; }
|
set {
|
m_lockType = value;
|
}
|
}
|
|
private float lastContentSize = 0;
|
|
private int lastDataCnt = 0;
|
|
private float lastScrollPos = 0;
|
|
public void ResetScrollPos()
|
{
|
if (_data.Count == 0 || !inited)
|
{
|
return;
|
}
|
switch (lockType) {
|
case EnhanceLockType.LockHorizonRight: {
|
mScrollRect.horizontalNormalizedPosition = 1;
|
}
|
break;
|
case EnhanceLockType.LockHorizonLeft: {
|
mScrollRect.horizontalNormalizedPosition = 0;
|
}
|
break;
|
case EnhanceLockType.LockVerticalTop: {
|
mScrollRect.verticalNormalizedPosition = 1;
|
}
|
break;
|
case EnhanceLockType.LockVerticalBottom: {
|
mScrollRect.verticalNormalizedPosition = 0;
|
m_Scorller.ScrollPosition = m_Scorller._ScrollSize;
|
}
|
break;
|
case EnhanceLockType.KeepHorizon: {
|
mScrollRect.horizontalNormalizedPosition = Mathf.Clamp01(lastContentSize * lastScrollPos / m_Scorller._ScrollSize);
|
}
|
break;
|
case EnhanceLockType.KeepVertical2: {
|
if(lastContentSize == m_Scorller._ScrollSize) {
|
mScrollRect.verticalNormalizedPosition = lastScrollPos;
|
m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;
|
return;
|
}
|
if (lastScrollPos == 1) {
|
mScrollRect.verticalNormalizedPosition = 1;
|
}
|
mScrollRect.verticalNormalizedPosition = Mathf.Clamp01(lastContentSize * lastScrollPos / m_Scorller._ScrollSize);
|
m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;
|
}
|
break;
|
case EnhanceLockType.KeepVertical:
|
{
|
if (lastContentSize == m_Scorller._ScrollSize)
|
{
|
mScrollRect.verticalNormalizedPosition = lastScrollPos;
|
m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;
|
return;
|
}
|
if (lastScrollPos == 1)
|
{
|
mScrollRect.verticalNormalizedPosition = 1;
|
}
|
mScrollRect.verticalNormalizedPosition = Mathf.Clamp01(1 - lastContentSize * (1 - lastScrollPos) / m_Scorller._ScrollSize);
|
m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;
|
}
|
break;
|
}
|
}
|
|
#endregion
|
}
|