unity scrollRect 按页翻页实现

参考
https://blog.csdn.net/liu_sanad/article/details/81131894
https://github.com/Hperigo/Unity-ScrollRectController

两个的实现都多少有点问题,已经在评论贴指出
以下为我根据两个帖子综合了一下写出来的

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

[RequireComponent(typeof(ScrollRect))]
public class ScrollPageTool : UIBehaviour, IEndDragHandler, IBeginDragHandler
{
    
    

    public RectTransform scrollTransformRect; //content
    public RectTransform baseRect; //子控件
    public float spacing = 0;//间距
    public int durationFrame = 10;

    public AnimationCurve curve = AnimationCurve.Linear(0f, 0f, 1f, 1f);

    int targetIndex = 0;
    Vector2 baseRectSize;

    public enum eAxis
    {
    
    
        Horizontal,
        Vertical
    }
    public eAxis mAxis = eAxis.Vertical;

    public float mScale = 1;

    //TODO
    //public enum eDirection
    //{
    
    
    //    Normal = 1,
    //    Backwards = -1
    //}
    //public eDirection mDirection = eDirection.Normal;

    protected override void Awake()
    {
    
    
        baseRectSize = new Vector2(baseRect.rect.width, baseRect.rect.height);
        SetPositionFromIndex(0, false);
    }

    // 开始拖动
    public void OnBeginDrag(PointerEventData eventData)
    {
    
    
        StopAllCoroutines();
    }

    // 结束拖动
    public void OnEndDrag(PointerEventData eventData)
    {
    
    
        targetIndex = GetCurrentPositionIndex();
        StartCoroutine(SnapRect());
    }

    private IEnumerator SnapRect()
    {
    
    
        float timer = 0f;
        float speed = Mathf.Max(0.01f, (float)1 / durationFrame);

        int axis = (int)mAxis;
        float oldPosition = scrollTransformRect.anchoredPosition[axis];
        float targetPosition = GetPositionFromIndex(targetIndex)[axis];
        Vector2 targetVector = new Vector2();
        while (timer < 1f)
        {
    
    
            float pos = Mathf.Lerp(oldPosition, targetPosition, curve.Evaluate(timer));
            timer += speed;
            targetVector[axis] = pos;
            scrollTransformRect.anchoredPosition = targetVector;
            yield return new WaitForEndOfFrame();
        }
        targetVector[axis] = targetPosition;
        scrollTransformRect.anchoredPosition = targetVector;
    }

    // 根据index 设置 position
    void SetPositionFromIndex(int i, bool animate = true)
    {
    
    
        StopAllCoroutines();
        int max = scrollTransformRect.gameObject.transform.childCount - 1;
        targetIndex = Mathf.Clamp(i, 0, max);
        if (!animate)
        {
    
    
            var pos = GetPositionFromIndex(i);
            scrollTransformRect.anchoredPosition = pos;
        }
        else
        {
    
    
            StartCoroutine(SnapRect());
        }
    }

    //根据index 获得 position
    Vector2 GetPositionFromIndex(int i)
    {
    
    
        int axis = (int)mAxis;
        Vector2 v = new Vector2(0f, 0f);

        int plus = eAxis.Horizontal == mAxis ? -1 : 1;
        v[axis] = (baseRectSize[axis] + spacing) * i * plus;
        return v;
    }

    //获取当前的 index
    int GetCurrentPositionIndex()
    {
    
    
        float item = GetOffset();
        if (eAxis.Horizontal == mAxis && 0 < item) return 0;
        if (eAxis.Vertical == mAxis && 0 > item) return 0;

        //int value = Mathf.RoundToInt(item);

        float abs_item = Mathf.Abs(item);
        int value = 0;
        float deci = abs_item % 1;
        if (targetIndex < abs_item)
        {
    
    
            value = Mathf.FloorToInt(abs_item);
            if (deci > 0.2) value++;
        }
        else
        {
    
    
            value = Mathf.CeilToInt(abs_item);
            if (deci < 0.6) value--;
        }
        int max = scrollTransformRect.gameObject.transform.childCount - 1;
        value = Mathf.Clamp(value, 0, max);
        return value;
    }

    //获取offset
    float GetOffset()
    {
    
    
        int axis = (int)mAxis;
        var anchorPos = scrollTransformRect.anchoredPosition[axis];
        float offset = anchorPos / (baseRectSize[axis] + spacing);
        return offset;
    }

    //脚本重置
    ScrollRect scrollRect;
    protected override void Reset()
    {
    
    
        base.Reset();

        if (scrollRect == null)
            scrollRect = GetComponent<ScrollRect>();
        scrollRect.inertia = false;

        if (scrollRect.movementType == ScrollRect.MovementType.Elastic)
        {
    
    
            Debug.LogError("ScrollRectController does not work with Elastic movement type, chage it to Clamped or Unrestricted");
        }
    }

}

猜你喜欢

转载自blog.csdn.net/aila852/article/details/111468209
今日推荐