首页 > 其他分享 >滑动列表近大远小吸附功能

滑动列表近大远小吸附功能

时间:2022-12-20 18:33:39浏览次数:39  
标签:近大远 scrollRectType ScrollRectType scrollRect float 列表 curPage 滑动 public

using HiplayGame;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
 
/// <summary>
/// 自动吸附的滑动列表
/// </summary>
[RequireComponent(typeof(ScrollRect))]
public class ScrollRect_AutoAdsorption : UIBase
{
    [Header("滑动列表类型")]
    public ScrollRectType scrollRectType;
    [Header("能否滑动多页")]
    public bool canMultiPageSlide;
    [Header("是否使用动态缩放")]
    public bool useDynamicScale;
    [HideInInspector]
    public float scaleCoe = 0.25f;
    [Header("横向滑动系数")]
    public float h_lerp = 0.2f;
    [Header("纵向滑动系数")]
    public float v_lerp = 0.2f;

    int totalPage;//总页数
    int curPage;//当前页
    float[] eachPageNormalizedPos;//每页坐标
 
    ScrollRect scrollRect;//滑动区域
    RectTransform content;//Content
    RectTransform viewport;//viewport
    GridLayoutGroup layout;//布局
 
    private void Awake()
    {
        scrollRect = GetComponent<ScrollRect>();
        content = scrollRect.content;
        viewport = scrollRect.viewport;
        layout = content.GetComponent<GridLayoutGroup>();
        if (layout == null)
        {
            Debug.LogError("Content下找不到GridLayoutGroup组件");
        }
 
        layout.constraint = scrollRectType == ScrollRectType.Horizontal
            ? GridLayoutGroup.Constraint.FixedRowCount
            : GridLayoutGroup.Constraint.FixedColumnCount;
        layout.constraintCount = 1;
        scrollRect.horizontal = scrollRectType == ScrollRectType.Horizontal;
        scrollRect.vertical = scrollRectType == ScrollRectType.Vertical;
        Init();
    }
 
    /// <summary>
    /// 初始化
    /// </summary>
    public void Init()
    {
        curPage = 1;
        SetButtonState();
        totalPage = content.childCount;
 
        //计算每页的归一化坐标
        eachPageNormalizedPos = new float[totalPage];
        if (scrollRectType == ScrollRectType.Horizontal)
        {
            float tempNormalizedPos = 0;
            for (int i = 0; i < eachPageNormalizedPos.Length; i++)
            {
                eachPageNormalizedPos[i] = tempNormalizedPos;
                tempNormalizedPos += 1f / (totalPage - 1);
            }
        }
        else if (scrollRectType == ScrollRectType.Vertical)
        {
            float tempNormalizedPos = 1;
            for (int i = 0; i < eachPageNormalizedPos.Length; i++)
            {
                eachPageNormalizedPos[i] = tempNormalizedPos;
                tempNormalizedPos -= 1f / (totalPage - 1);
            }
        }
 
        //设置Content
        content.sizeDelta = scrollRectType == ScrollRectType.Horizontal
            ? new Vector2((totalPage - 1) * (layout.cellSize.x + layout.spacing.x), viewport.rect.height)
            : new Vector2(0, viewport.rect.height + (totalPage - 1) * (layout.cellSize.y + layout.spacing.y));
 
        scrollRect.horizontalNormalizedPosition = 0;
        scrollRect.verticalNormalizedPosition = 1;
    }
 
    bool inDrag;//是否在拖拽中
    float beginDragPos;//开始拖拽的位置
    float endDragPos;//结束拖拽的位置
 
    public void OnBeginDrag()
    {
        inDrag = true;
 
        beginDragPos = scrollRectType == ScrollRectType.Horizontal
            ? Input.mousePosition.x
            : Input.mousePosition.y;
    }
 
    public void OnEndDrag()
    {
        inDrag = false;
 
        endDragPos = scrollRectType == ScrollRectType.Horizontal
            ? Input.mousePosition.x
            : Input.mousePosition.y;
        float curNormalizedPos = scrollRectType == ScrollRectType.Horizontal
            ? scrollRect.horizontalNormalizedPosition
            : scrollRect.verticalNormalizedPosition;
 
        float offset = endDragPos - beginDragPos;
        //多页滑动
        if (canMultiPageSlide)
        {
            curPage = FindNearlyPage(curNormalizedPos);
            SetButtonState();
        }
        //单页滑动
        else
        {
            int nearlyPage = FindNearlyPage(curNormalizedPos);
            if (nearlyPage != curPage)
            {
                if (offset > 0)
                {
                    curPage = scrollRectType == ScrollRectType.Horizontal
                        ? curPage - 1 < 1 ? 1 : curPage - 1
                        : curPage + 1 > totalPage ? curPage : curPage + 1;
                    SetButtonState();
                }
                else if (offset < 0)
                {
                    curPage = scrollRectType == ScrollRectType.Horizontal
                        ? curPage + 1 > totalPage ? curPage : curPage + 1
                        : curPage - 1 < 1 ? 1 : curPage - 1;
                    SetButtonState();
                }
            }
        }
    }
 
    private void Update()
    {
        if (layout == null) return;
 
        if (!inDrag)
        {
            scrollRect.normalizedPosition = scrollRectType == ScrollRectType.Horizontal
                ? new Vector2(Mathf.Lerp(scrollRect.horizontalNormalizedPosition, eachPageNormalizedPos[curPage - 1], h_lerp), 0)
                : new Vector2(0, Mathf.Lerp(scrollRect.verticalNormalizedPosition, eachPageNormalizedPos[curPage - 1], v_lerp));
        }
 
        if (useDynamicScale)
        {
            UpdateScale();
        }
    }

    private void SetButtonState()
    {
        if (curPage == 1)
        {
            SendMessageUpwards("SetLeftButtonState",false);
            SendMessageUpwards("SetRightButtonState",true);
        }
        else if(curPage == totalPage)
        {
            SendMessageUpwards("SetLeftButtonState",true);
            SendMessageUpwards("SetRightButtonState",false);
        }
        else
        {
            SendMessageUpwards("SetLeftButtonState",true);
            SendMessageUpwards("SetRightButtonState",true);
        }
    }

    /// <summary>
    /// 更新缩放
    /// </summary>
    void UpdateScale()
    {
        Vector2 centerPos = transform.position;
 
        //得到所有项
        GameObject[] items = new GameObject[content.childCount];
        for (int i = 0; i < items.Length; i++)
        {
            items[i] = content.GetChild(i).gameObject;
        }
 
        foreach (var item in items)
        {
            Vector2 itemPos = item.transform.position;
            if (Mathf.Abs(itemPos.x - centerPos.x) <= 390f)
            {
                var offsetX = 1 - Mathf.Abs(itemPos.x - centerPos.x)/390f * scaleCoe;
                item.LocalScale(offsetX);

                if (Mathf.Abs(offsetX - 1f) < 0.05f)
                {
                    SetActive(item, true, "Image1");
                    SetActive(item, false, "Image2");
                    SetActive(item, false,"BlackMask");
                }
                else
                {
                    SetActive(item, false, "Image1");
                    SetActive(item, true, "Image2");
                    SetActive(item, true,"BlackMask");
                }
            }
        }
    }
 
    /// <summary>
    /// 查找最近的页
    /// </summary>
    int FindNearlyPage(float curNormalizedPos)
    {
        int tempPage = 1;
        float tempMinOffset = Mathf.Abs(curNormalizedPos - eachPageNormalizedPos[0]);
        for (int i = 1; i <= totalPage; i++)
        {
            float tempOffset = Mathf.Abs(curNormalizedPos - eachPageNormalizedPos[i - 1]);
            if (tempOffset < tempMinOffset)
            {
                tempMinOffset = tempOffset;
                tempPage = i;
            }
        }
        return tempPage;
    }
 
    #region interface
 
    /// <summary>
    /// 设置页数
    /// </summary>
    public void SetPage(int page)
    {
        curPage = page;
        SetButtonState();
    }

    public int GetPage()
    {
        return curPage;
    }

    #endregion
}
 
/// <summary>
/// 滑动列表类型
/// </summary>
public enum ScrollRectType
{
    Horizontal,
    Vertical,
}
 
#if UNITY_EDITOR
 
/// <summary>
/// 自动吸附的滑动列表Inspector扩展
/// </summary>
[UnityEditor.CustomEditor(typeof(ScrollRect_AutoAdsorption))]
public class ScrollRect_AutoAdsorption_Editor : UnityEditor.Editor
{
    ScrollRect_AutoAdsorption t;
 
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
 
        t = target as ScrollRect_AutoAdsorption;
 
        if (t.useDynamicScale)
        {
            t.scaleCoe = UnityEditor.EditorGUILayout.FloatField("缩放系数", t.scaleCoe);
        }
    }
}
 
#endif

 

复写滑动列表的拖拽方法

public class AutoScrollRect : ScrollRect
{
    private ScrollRect_AutoAdsorption autoAdsorption;
    protected void Awake()
    {
        autoAdsorption = GetComponent<ScrollRect_AutoAdsorption>();
    }

    public override void OnBeginDrag(PointerEventData eventData)
    {
        autoAdsorption.OnBeginDrag();
        base.OnBeginDrag(eventData);
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        TimerManager.Add(0.1f, id =>
        {
            autoAdsorption.OnEndDrag();
        });
        base.OnEndDrag(eventData);
    }
    
}

  

标签:近大远,scrollRectType,ScrollRectType,scrollRect,float,列表,curPage,滑动,public
From: https://www.cnblogs.com/txfd/p/16994862.html

相关文章

  • 7-33 学生列表2 (20 分)
    7-33学生列表2(20分)编写学生类,包含学号no、姓名name、成绩score,提供必要的构造函数、toString函数和equals/hashcode函数,其中,toString函数的格式为“no:xxxname:xxxsc......
  • [编程基础] Python列表解析总结
    dates:2020-06-2614:29:00+0800tags:-编程基础-Python在本教程中,我们将学习使用Python列表解析(listcomprehensions)相关知识1使用介绍列表解析是一种基......
  • 基于.NetCore开发博客项目 StarBlog - (23) 文章列表接口分页、过滤、搜索、排序
    前言上一篇留的坑,火速补上。在之前的第6篇中,已经有初步介绍,本文做一些补充,已经搞定这部分的同学可以快速跳过,基于.NetCore开发博客项目StarBlog-(6)页面开发之博客文......
  • Python学习笔记--列表来啦!
    列表的定义格式示例:列表的下标索引(千万别超出范围!!!)示例:正向和反向取出嵌套列表的元素:(二维数组)列表的常用的操作方法查找某元素的下标示例:修改元素插入......
  • php 滑动图片验证生成
    1.话不多说,直接干货,喜欢的希望大家一键三连<?phpnamespaceApp\Model;classVerifyImage{//浮层坐标数组protected$tailoringArray=[];//浮层......
  • 30python中列表-字典-字符串-三目运算符
    好文手敲下,每天码代码~加油三目运算符a=1b=2#a+b不大于3执行后面的else语句b-a=1print(a+bifa+b>3elseb-a)一、列表1.1列表的定义​ 白话来讲:放数......
  • 如何获取 Visual Studio 项目中的 nuget 包引用列表,以及在 npm 包的引用列表
    nuget1、在VisualStudio中打开对应的解决方案;2、打开程序包管理控制台;3、执行命令:Get-Package|Select-Object-Property{$_.Id+","+$_.Version}4、即可得到以......
  • win11和win10的快捷键列表
    win11特有的快捷键win键就是图案是windows图标的那个按键作用快捷键打开快速设置,win11是展开音量,wifi,蓝牙的设置项,win10也可以用win+a打开通知中心和日历......
  • [编程基础] Python列表解析总结
    在本教程中,我们将学习使用Python列表解析(listcomprehensions)相关知识文章目录​​1使用介绍​​​​1.1Python列表解析转换列表​​​​1.2从摄氏度计算华氏温度​​......
  • redis底层数据结构之压缩列表(ziplist)
    压缩列表(ziplist)压缩列表(ziplist)是redis为了节约内存而开发的,由连续内存块组成的顺序型数据结构,适用于长度较小的值存取的效率高,内存占用小,但由于内存是连续的,在修......