Unity UGUIScrollRect 动态缩放格子大小,自动定位到中间的格子

Posted 萧然CS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity UGUIScrollRect 动态缩放格子大小,自动定位到中间的格子相关的知识,希望对你有一定的参考价值。


 实现效果:ScrollRect,格子动态缩放大小,滑动结束自动定位中间格子 

【Unity【Unity

使用说明:

目前只支持横向从左往右列表,需要设置ScrollRect仅横向滑动,ScrollViewExtras挂到ScrollRect组件所在节点,ScrollRect的格子锚点、中心点设置在左上角,Content,设置好Y坐标,运行时自动修改X坐标。

GridSpace:格子间距

IsSnap:是否开启自动定位

IsScale:是否开启自动缩放

ScaleCueve:缩放曲线

【Unity【Unity

【Unity【Unity

 效果演示:

关闭自动定位,关闭自动缩放:

【Unity【Unity

开启自动定位,关闭自动缩放:

 【Unity【Unity

关闭自动定位,开启自动缩放:

 【Unity【Unity

开启自动定位,开启自动缩放:

【Unity【Unity

实现原理:

  1. 动态缩放功能实现:Transform改变时,计算列表可视区域内所有格子与列表中心的偏移量,根据偏移量缩放格子。
  2. 自动定位功能实现:初始化计算每个格子的位置,滑动结束后,计算每个格子到列表中心的偏移量,偏移量最小的格子就是列表最中间的格子,再把它自动移动到列表中心的位置,实现定位。

【Unity【Unity

实现代码:

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

[RequireComponent(typeof(ScrollRect))]
public class ScrollViewExtras : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler

private enum SnapState

None,
Inertia,
Reverse,


public Action OnScrollStartDrag;
public Action<int> OnScrollEndDrag;
public Action<int> OnSelectGridChanged;

[SerializeField] private float gridSpace = 20;

[SerializeField] private bool isSnap;

[SerializeField] private bool isScale;

[SerializeField] private AnimationCurve scaleCurve = new AnimationCurve(new Keyframe(0,1),new Keyframe(1,0.5f));

//初始化不变字段

private ScrollRect scrollRect;
private RectTransform contentRectTrans;
private Vector2 scrollHalfSize; //列表尺寸

private Vector2 gridSize;
private List<RectTransform> gridList = new List<RectTransform>();
private List<Vector2> gridCenterList = new List<Vector2>();

private float snapDecelerate;
private const float snapReverseSpeed = 500;

private bool isInited = false;

//动态变化字段

private SnapState snapState = SnapState.None;

private int curSelectIndex;

//----------

private void Start()

Init();


private void Update()

if(isInited)

switch(snapState)

case SnapState.Inertia:
UpdateSnapInertia();
break;
case SnapState.Reverse:
UpdateSnapReverse();
break;
default:
break;


if(contentRectTrans.hasChanged)

if(isScale)
UpdateScale();
else
UpdateSelectGrid();




#region --- Drag Event

public void OnBeginDrag(PointerEventData eventData)

OnScrollStartDrag?.Invoke();
BreakSnap();

public void OnDrag(PointerEventData eventData)


public void OnEndDrag(PointerEventData eventData)

StartSnap();


#endregion

public void Init()

scrollRect = GetComponent<ScrollRect>();
if(!scrollRect.horizontal)
Debug.LogError("目前只支持横向从左往右列表");

contentRectTrans = scrollRect.content;
if(contentRectTrans.pivot.x > 0)
Debug.LogError("目前只支持横向从左往右列表");

//scrollCenter = scrollRect.viewport.rect.center;
scrollHalfSize = scrollRect.viewport.rect.size * 0.5f;

for(int i = 0; i < contentRectTrans.childCount; i++)

gridList.Add(contentRectTrans.GetChild(i) as RectTransform);

if(gridList.Count > 0)
gridSize = gridList[0].rect.size;

snapDecelerate = scrollRect.decelerationRate;
//if(snapDecelerate < 0.1f)
// snapDecelerate = 0.1f;

if(gridList.Count == 0)
return;

//第一个格子坐标
Vector2 gridInitPos = gridList[0].anchoredPosition;
gridInitPos.x = scrollHalfSize.x - gridSize.x * 0.5f;

//格子间隔
Vector2 gridOffset = Vector2.zero;
gridOffset.x = gridSize.x + gridSpace;

//计算画布尺寸
Vector2 contentSize = Unity 降低 Batch

编辑器中的游戏 UI 已缩放(Unity,仅限 Android)

Unity2D:缩放游戏对象而不缩放其子对象

Unity 大地图滑动与缩放

Unity 触屏缩放模型

使用 Unity 5 UI 进行捏合缩放