unity UGUI滑动菜单栏吸附效果

思路:
1 计算图片从一张移动到第二张的距离==图片的大小+图片之间的间距
2 获取content的X的位置
3 计算滑动时的的图片的index(图片放大的index)=X/距离
4 位置之间的平滑用Dotween处理

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

public class LeftAndRightInfiniteImageSroll: MonoBehaviour
{
    public RectTransform content;   //滑动内容
    public ScrollRect scrollRect;

    private ContentSizeFitter contentSizeFitter;
    private HorizontalLayoutGroup horizontalLayoutGroup;

    private List<RectTransform> ShowImageList = new List<RectTransform>();     //存储循环显示的Image

    private RectTransform scrollRectTransform;

    private float startPoitios;           //记录开始的位置     
    private float curretPosition;         //当前的位置信息
    private float scrollRectLeft;         //滑动的参照点
    private float imgeSize = 100;         //图片的大小

    public float leftLimitXOffset = 200;
    public float imageMoveDuration = 0.2f;  //图片自动归为的时间
    public float imageMaxSize = 1.2f;
    public float imageMinSize = 0.8f;


    public int indeximage;             //当前图片的索引
    private int imageSizeIndex;        //图片变大的索引

    [Header("显示图片index")] public string ImageShowIndexText = "ShowImageID";

    [HideInInspector] private int count = 20;  //显示显示的个数

    private void Awake()
    {
        InitCompent();
    }

    void Start()
    {
        InitContentList();
        Invoke("EnablEdcompent", .1f);
    }

    private void Update()
    {
        ImageAutoPos(imageSizeIndex);
    }
    //克隆
    public void InitContentList()
    {
        foreach (RectTransform rectTransform in content)
        {
            //显示index
            rectTransform.transform.Find(ImageShowIndexText).GetComponent<Text>().text = ShowImageList.Count + "";
            rectTransform.localScale = new Vector3(imageMinSize, imageMinSize,imageMinSize);
            SetImageSize();

            indeximage++;
            ShowImageList.Add(rectTransform);
        }
    }

    public void InitCompent()
    {
        contentSizeFitter = content.GetComponent<ContentSizeFitter>();
        horizontalLayoutGroup = content.GetComponent<HorizontalLayoutGroup>();
        scrollRect = scrollRect.GetComponent<ScrollRect>();
        //左边的边界
        scrollRectLeft = scrollRect.transform.TransformPoint(Vector3.zero).x;
        //  scrollRectLeft = scrollRectTransform.anchoredPosition.x;
        scrollRectTransform = scrollRect.GetComponent<RectTransform>();

        scrollRect.onValueChanged.AddListener((data) => { infiniteScroll(data); });
    }

    public void EnablEdcompent()
    {
        horizontalLayoutGroup.enabled = false;
        contentSizeFitter.enabled = false;
    }

    //无限滑动
    public void infiniteScroll(Vector2 data)
    {
        computeIndex();
        SetImageSize();
        //  float Left = content.transform.TransformPoint(ShowImageList[0].localPosition.x + ImgeSize, ShowImageList[0].localPosition.y, 0).x;
        float Left = ShowImageList[0].position.x + imgeSize;
        curretPosition = content.GetComponent<RectTransform>().anchoredPosition.x;
        float offsetX = curretPosition - startPoitios;

        if (offsetX < 0)
        {
            if (indeximage + 1 <= count)
            {
                startPoitios = curretPosition;
              //  Debug.LogError("A:" + (Left + ImgeSize) + "B:" + scrollRectLeft);
                if (Left + imgeSize+ leftLimitXOffset <= scrollRectLeft)
                {
                    ShowImageList[0].transform.SetAsLastSibling();
                    ShowImageList[0].anchoredPosition =
                    new Vector3(ShowImageList[ShowImageList.Count - 1].anchoredPosition.x + horizontalLayoutGroup.spacing + imgeSize, ShowImageList[0].anchoredPosition.y, 0);

                    ShowText(0, indeximage);

                    indeximage++;
                    for (int i = 0; i < ShowImageList.Count; i++)
                    {
                        ShowImageList[i] = content.transform.GetChild(i).GetComponent<RectTransform>();
                    }
                    content.GetComponent<RectTransform>().sizeDelta += new Vector2(horizontalLayoutGroup.spacing + imgeSize, 0);
                }
            }
        }
        else
        {
          
            //   Vector3 scrollRectAnchorRight = new Vector3(scrollRectTransform.rect.width + horizontalLayoutGroup.spacing, 0, 0f);
            //float scrollRectRight = scrollRect.transform.TransformPoint(scrollRectAnchorRight).x;
            float scrollRectRight = scrollRectLeft + scrollRectTransform.rect.width + horizontalLayoutGroup.spacing;
            Vector3 childUpRight = new Vector3(ShowImageList[ShowImageList.Count - 1].anchoredPosition.x, ShowImageList[ShowImageList.Count - 1].anchoredPosition.y, 0f);
            float childRight = content.transform.TransformPoint(childUpRight).x;
            if (childRight >= scrollRectRight + imgeSize)
            {
                if (indeximage - ShowImageList.Count == 0)
                {
                    return;
                }
                ShowImageList[ShowImageList.Count - 1].SetAsFirstSibling();
                indeximage--;

                ShowText(ShowImageList.Count - 1, indeximage - ShowImageList.Count);

                ShowImageList[ShowImageList.Count - 1].anchoredPosition = new Vector2(ShowImageList[0].anchoredPosition.x - horizontalLayoutGroup.spacing - imgeSize, ShowImageList[ShowImageList.Count - 1].anchoredPosition.y);
                for (int i = 0; i < ShowImageList.Count; i++)
                {
                    ShowImageList[i] = content.transform.GetChild(i).GetComponent<RectTransform>();
                }
                content.GetComponent<RectTransform>().sizeDelta -= new Vector2(horizontalLayoutGroup.spacing + imgeSize, 0);
            }
        }

        startPoitios = curretPosition;

    }

    /// <summary>
    /// 显示文字
    /// </summary>
    /// <param name="imageIndex"></param>
    /// <param name="ShowIndex"></param>
    public virtual void ShowText(int imageIndex, int ShowIndex)
    {
        ShowImageList[imageIndex].Find(ImageShowIndexText).GetComponent<Text>().text = ShowIndex + "";
    }

    /// <summary>
    /// 计算图片变大的index
    /// </summary>
    private void computeIndex()
    {
        imageSizeIndex = Mathf.RoundToInt(content.anchoredPosition.x / -(imgeSize + horizontalLayoutGroup.spacing));
    //    Debug.Log("图片变大:"+ imageSizeIndex+"Content.X:"+ content.anchoredPosition.x);
    }

    /// <summary>
    /// 设置图片的属性
    /// </summary>
    /// <param name="imageIndex">(无限滚动的)图片的索引</param>
    private void SetImageSize()
    {
        for (int i = 0; i < ShowImageList.Count; i++)
        {
            if (ShowImageList[i].transform.Find(ImageShowIndexText).GetComponent<Text>().text==imageSizeIndex.ToString())
            {
                ShowImageList[i].localScale = new Vector2(imageMaxSize, imageMaxSize);
            }
            else
            {
                ShowImageList[i].localScale = new Vector2(imageMinSize, imageMinSize); 
            }
        }
    }

    /// <summary>
    ///  图片自动归位
    /// </summary>
    /// <param name="ShowTextIndex">显示当前图片的索引</param>
    private void ImageAutoPos(int ShowTextIndex)
    {
        if (Input.GetMouseButtonUp(0))
        {
             content.transform.DOLocalMoveX(-imageSizeIndex *(imgeSize + horizontalLayoutGroup.spacing), imageMoveDuration);
        }
    }
    private void OnDisable()
    {
        indeximage = 0;
        if (horizontalLayoutGroup != null)
            horizontalLayoutGroup.enabled = true;
        if (contentSizeFitter != null)
            contentSizeFitter.enabled = true;
    }
}
image.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容

  • 生活总归不易,看我们用什么样的心态去面对。 感觉已经持续有一段时间,整个人处于低谷状态,具体不知道因为什么。因为工...
    刘云杰阅读 326评论 0 0
  • 这不过是秋季,自然的萧条和蛰伏,街道上只剩下微风。一年一年亦是如此,人们还记得自己伙伴和仇人的样子。一年一年亦是如...
    何老蔡阅读 231评论 0 0
  • 垃圾,只是放错了位置的宝。 ————前言 错误一 ——要么在沉默中爆发,要么在沉默中死亡。 沉默,是一个人的喧嚣;...
    陈贰九阅读 870评论 0 11
  • 到北京啦! 这次的时间特别gang其实空气我特喜欢,我觉得很舒服!虽然有点干燥,但特别的干净!还有厕所是我喜欢的宽...
    厦门整理师张桂华阅读 95评论 0 0
  • 虞美人•春风 烟云逐影瑶台舞,一水堪留住?柳丝轻剪称心怀,犹是裹香向晚,染桃腮。 呢侬对燕和庭树,也与春花叙。画堂...
    水兰_93bf阅读 196评论 0 4