UGUI轮播1.0.0

要做一个轮播功能,以前也有写,但是感觉不通用,百度找的又有各种各样的问题,所以自己整理了一个

目前只支持左右一位位移,没有自己去写缓动,用的DoTween

暂定1.0版本吧,后面会继续优化

其实就是列表存储,后面根据目标位置信息,去做位移和缩放等行为

直接上代码吧:

/*******************************************************************************
* 版本声明:v1.0.0
* 类 名 称:UIRotationManager
* 创建日期:2020-05-19 15:52:49
* 作者名称:末零
* 功能描述:UGUI轮播
* 修改记录:
*           v1.0.0   完成左右一位的位移(多位目前测试会有bug)
*           当前全部显示,不能选择轮播物体显示个数
* 
******************************************************************************/

using System.Collections.Generic;
using UnityEngine;

using DG.Tweening;

namespace LastZero
{
    /// <summary>
    /// 状态枚举
    /// </summary>
    public enum RotationState
    {
        Rotating,
        Stop
    }

    /// <summary>
    /// 轮播
    /// </summary>
    public class UIRotationManager : MonoBehaviour
    {
        public int indexCenter = 0;//初始时,位于中间位置的对象ID
        public float cellWidth = 100;//宽度
        public float scaleMultiple = 1;//缩放倍数
        public float speed = 5;//轮播速度

        private List<UIRotationItem> items = new List<UIRotationItem>();//所有子物体(要轮播的)
        private List<int> relativePosition = new List<int>();//相对位置

        private int indexHalf;//轮播对象数量的中值
        private List<int> order = new List<int>();//顺序
        private RotationState state = RotationState.Stop;//状态

        private void Awake()
        {
            items.AddRange(transform.GetComponentsInChildren<UIRotationItem>());
        }

        private void Start()
        {
            Init();
        }

        private void Update()
        {
            if (Input.GetKeyDown(KeyCode.LeftArrow))
            {
                DoRotateItems(1);
            }
            if (Input.GetKeyDown(KeyCode.RightArrow))
            {
                DoRotateItems(-1);
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            indexHalf = (items.Count - 1) / 2;

            for (int i = 0; i < items.Count; i++)
            {
                int target = i - indexHalf + indexCenter;
                target = target < 0 ? target + items.Count : target >= items.Count ? target - items.Count : target;
                items[i] = transform.GetChild(target).GetComponent<UIRotationItem>();

                relativePosition.Add(i - indexHalf);
            }

            DoRotateItems();
        }

        /// <summary>
        /// 获取当前状态
        /// </summary>
        /// <returns></returns>
        public RotationState GetState()
        {
            return state;
        }

        /// <summary>
        /// 轮播
        /// </summary>
        /// <param name="value"></param>
        public void DoRotateItems(int value = 0)
        {
            if (state == RotationState.Rotating) return;
            
            order.Clear();

            for (int i = 0; i < items.Count; i++)
            {
                int target = i + value;

                if (target < 0)
                {
                    target += items.Count;
                }
                else if (target >= items.Count)
                {
                    target -= items.Count;
                }
                order.Add(target);

                if ((target == 0 && value > 0) || (target == items.Count - 1 && value < 0))
                {
                    int indexI = i;
                    int indexTarget = target;
                    items[i].transform.DOScale(0.01f, Mathf.Abs(value) / speed * 0.5f).OnComplete(() =>
                    {
                        items[indexI].LocalPositionX = relativePosition[indexTarget] * cellWidth * Mathf.Pow(scaleMultiple, Mathf.Abs(relativePosition[indexTarget]));
                        items[indexI].transform.DOScale(Mathf.Pow(scaleMultiple, Mathf.Abs(relativePosition[indexTarget])), Mathf.Abs(value) / speed * 0.5f).SetEase(Ease.Linear);
                    });
                }
                else
                {
                    items[i].transform.DOLocalMoveX(relativePosition[target] * cellWidth * Mathf.Pow(scaleMultiple, Mathf.Abs(relativePosition[target])), Mathf.Abs(value) / speed).SetEase(Ease.Linear);
                    items[i].transform.DOScale(Mathf.Pow(scaleMultiple, Mathf.Abs(relativePosition[target])), Mathf.Abs(value) / speed).OnComplete(() =>
                    {
                        state = RotationState.Stop;
                    }).SetEase(Ease.Linear);
                }  
            }
            StartCoroutine(CallBack(Mathf.Abs(value)));
            state = RotationState.Rotating;
        }

        /// <summary>
        /// 回调(单次轮播进行到一半时,重置List、改变SiblingIndex)
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        private System.Collections.IEnumerator CallBack(int time)
        {
            yield return new WaitForSeconds(time * 0.5f / speed);

            UIRotationItem[] newItems = new UIRotationItem[items.Count];
            for (int i = 0; i < items.Count; i++)
            {
                newItems[order[i]] = items[i];
            }
            items.Clear();
            items.AddRange(newItems);
            ChangeSiblingIndex();
        }

        /// <summary>
        /// 改变SiblingIndex
        /// </summary>
        private void ChangeSiblingIndex()
        {
            for (int i = 0; i < items.Count; i++)
            {
                int index;
                index = relativePosition[i]>=0? items.Count - 1 - relativePosition[i] * 2 : items.Count - 1 + relativePosition[i] * 2 + 1;
                items[i].SiblingIndex = index;
            }
        }
    }
}

Item其实只是提供了几个属性,没做什么实际功能

public float LocalPositionX
{
    get { return transform.localPosition.x; }
    set { transform.localPosition = new Vector3(value, transform.localPosition.y, transform.localPosition.z); }
}

public float LocalScale
{
    get { return transform.localScale.x; }
    set { transform.localScale = Vector3.one * value; }
}

public int SiblingIndex
{
    get { return transform.GetSiblingIndex(); }
    set { transform.SetSiblingIndex(value); }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

末零

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值