Unity自带UI组件ScrollView可以创建一个滑动区域,制作一些横屏和竖屏的滑动效果非常方便。

 

效果展示:

unity UI 滑动旋转菜单 unity滑动翻页_Image

 

 

组件简介

unity UI 滑动旋转菜单 unity滑动翻页_Mask_02


ScrollView

滚动窗口,可以勾选横向滑动或者竖向滑动、是否需要窗口蒙版Viewport等。

Viewport
窗口蒙版,限定可以看到的窗口区域,带有一个Image作为Mask。在调整时想看到未遮挡的效果,取消勾选Image或者Mask即可。

Content
需要滑动显示的页面,可以作为多个展示物体的父物体,并挂载Layout Group自动调整布局。

ScrollBar
滚动条,在Scrollview里取消勾选的方向的ScrollBar可以删除,未取消勾选可以分别移除Image组件来达到隐藏滚动条的效果(记得还有Handle)。可以通过修改ScrollBar.value实现跳转。

 

 

实践分析

如果直接使用的话,实际滑动中经常会出现下面的情况:

  1. 屏幕中出现上下两张不完整的图片的情况,并且一些细微的滑动也会造成窗口的滚动,不美观
  2. 想要完整的看一张图片 / 想把图片放到屏幕中间需要自己手动一点一点的滑动调整,不方便

 

需求总结

  1. 不要出现屏幕中有两张图片的割裂情况
  2. 不要出现手指误触导致的画面滑动

说什么废话!
直接说“翻页吸附效果”、“整页翻”不就好了???

 

问题分析

每次滑动完毕,都要根据滑动幅度(距离)来判断此次滑动会不会触发翻页的效果。
如果会,就翻页;反之,回到原来的位置。

 

解决方案

  1. 为每个页面分区间,计算每个页面的ScrollBar.value
  2. 获得每次滑动的距离
  3. 根据距离判断是否翻页(优化:设定滑动长度占屏幕长度的百分比,解决多种分辨率设备的适配)
    3.1. 若距离大于翻页所需值,翻页
    3.2 反之,返回原页面
  4. 若需翻页,根据滑动值正负判断翻页方向,注意第一页和最后一页的情况

代码如下:

public class SwitchPage : MonoBehaviour
{
    private const float SMOOTH_TIME = 10f;

    public Scrollbar scrollBar;
    public int pageNum = 5; // 总共的图片数
    public float minScrollDisPercent = 0.2f;

    float minScrollDis; // 最小翻页需要挪动的距离


    float point;               // 每个区间的中点value加值

    bool turnPage = false;
    float targetValue = 0f;
    float speed = 0f;

    int currentPage;
    int targetPage;
    float startX;
    float endX;


    private void Awake()
    {
        point = 1.0f / (pageNum - 1);

		// 根据设备分辨率的不同来计算在不同的设备上翻页所需要滑动的距离
        minScrollDis = Screen.currentResolution.width * minScrollDisPercent;

        currentPage = 0;
    }


    // Update is called once per frame
    void Update()
    {
        if (turnPage)
        {
            if (Mathf.Abs(scrollBar.value - targetValue) < 0.01f)
            {
                scrollBar.value = targetValue;
                turnPage = false;
                return;
            }
            scrollBar.value = Mathf.SmoothDamp(scrollBar.value, targetValue, ref speed, Time.deltaTime * SMOOTH_TIME);            
        }

    }



    public void DragStart()
    {
        turnPage = false;
        startX = Input.mousePosition.x;
    }


    public void DragEnd()
    {
        endX = Input.mousePosition.x;
        float deltaX = startX - endX;

        // 如果滑动距大于设定值,左右翻页
        if (Mathf.Abs(deltaX) > minScrollDis)
        {
            if (deltaX > 0)
            {
                targetPage = Mathf.Min(pageNum - 1, currentPage + 1);
            }
            else
            {
                targetPage = Mathf.Max(0, currentPage - 1);
            }
            // 更新currentPage
            currentPage = targetPage;
        }
        // 否则,返回原页
        else
        {
            targetPage = currentPage;
        }

        targetValue = point * targetPage;

        speed = 0f;
        turnPage = true;
    }
}

区间的相关计算可以通过画一张图并拖动scrollbar,观察它值的变化来理解。

 

参考文章
Unity实现滑页效果(UGUI)官方API - ScrollView