Unity UGUI 效果 之 多页翻页,多页任意翻页的简单效果实现(示例演示为动态加载多图片实现翻页预览效果)

 

 

Unity UGUI 效果 之 多页翻页,多页任意翻页的简单效果实现(示例演示为动态加载多图片实现翻页预览效果)

 

目录

Unity UGUI 效果 之 多页翻页,多页任意翻页的简单效果实现(示例演示为动态加载多图片实现翻页预览效果)

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

六、关键代码

七、参考工程


 

一、简单介绍

UGUI,是Unity自带的 GUI 系统,有别于 NGUI;使用 UGUI 也能制作出比较酷炫的效果 。

本节介绍,使用 UGUI 通过代码实现多页翻页的效果,示例是以动态加载图片为例实现的多页翻页效果。

 

二、实现原理

1、通过展示的总的动态图片个书,每页每页展示图片的数量,分为若干页

2、Button实现前后翻页,Toggle 实现任意翻页

3、关键的逻辑代码是当前页时,代码实现展示的内容

 

三、注意事项

1、在计算分页总页数的时候,注意整除和右余数的时候,总页数是不一样的

2、前后翻页和任意翻页都要互相更新显示

3、代码 toggle.isOn 的时候,是不会触发对应的监听时间函数,请注意

4、多说一句,在加载图片展示的时候,最好不要一张一张边加载,边展示,这样很有可能会程序崩溃;多图多的话,分批多次加载,一批加载完,展示一批

5、图片加载的路径(pageIconPath = @"D:\Tmp\Images"),是我本机的图片位置,代码中记得更改为自己的图片路径

 

四、效果预览

 

五、实现步骤

1、打开 Unity ,新建空工程

 

2、在场景中布局 UGUI ,PageItem 和 MultiPageToggleItem 会作为预制体,用于动态加载

 

3、在工程中新建脚本,编辑脚本,实现相关逻辑代码

 

4、把脚本对应挂载,并赋值

 

5、运行场景,效果如上

 

六、关键代码

1、MultiPageShowWrapper.cs

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

public class MultiPageShowWrapper : MonoBehaviour
{
    #region 常量

    // Page Icon 加载路径
    const string pageIconPath = @"D:\Tmp\Images";

    // PageItem Resources 加载路径
    const string PageItemPath = @"PageItem";

    // MultiPageToggleItem Resources 加载路径
    const string MultiPageToggleItemPath = @"MultiPageToggleItem";

    // 每页展示 icon 的数量
    const int ShowPageIconItemCountPerPage = 10;
    #endregion

    #region 字段
    // 生成显示放置 PageItem 的父物体
    public Transform PageGrid_Image;
    // 生成显示放置 MultiPageToggleItem 的父物体
    public Transform PageToggleGroup;
    // 左翻页按钮
    public Button LeftPage_Button;
    // 右翻页按钮
    public Button RightPage_Button;
    // 当前页/总页显示文本
    public Text PageCount_Text;



    // PageItem 物体
    GameObject mPageItem;
    // MultiPageToggleItem 物体
    GameObject mMultiPageToggleItem;

    // Page ICon 图片路径的列表
    private List<string> mPageIconList = new List<string>();
    


    private int currentPage = 0;
    private int totalPage = 0;
    private int currentIntiateItem = 0;
    private int PageIconListCount = 0;

    #endregion

    #region 方法



    #region 其他视情况而定的方法 协程加载指定路径的图片

    
    private List<Texture2D> mPageIconTextureList = new List<Texture2D>();
    int loadIndex = 0;
    bool isLoadedEnd = false;
    void InitLoadIconTexture2d()
    {
        mPageIconList = GetWindiowsPCPicturesPath.GetPictutresPathsInTheFilePath(pageIconPath);

        for (int i = 0; i < mPageIconList.Count; i++)
        {
            loadIndex++;
            GetTexture(mPageIconList[i], (texture2D) =>
            {
                loadIndex--;
                mPageIconTextureList.Add(texture2D);
            });
        }
    }
    void Start()
    {
        InitLoadIconTexture2d();
    }


    void Update() {
        if (mPageIconTextureList.Count>0 && loadIndex <=0 && isLoadedEnd == false)
        {
            isLoadedEnd = true;
            StartCoroutine(ShowPageIconList(mPageIconTextureList));
        }
    }

    /// <summary>
    /// 请求图片
    /// </summary>
    /// <param name="url">图片地址,like 'http://www.my-server.com/image.png '</param>
    /// <param name="action">请求发起后处理回调结果的委托,处理请求结果的图片</param>
    /// <returns></returns>
    public void GetTexture(string url, Action<Texture2D> actionResult)
    {
        StartCoroutine(_GetTexture(url, actionResult));
    }

    /// <summary>
    /// 请求图片
    /// </summary>
    /// <param name="url">图片地址,like 'http://www.my-server.com/image.png '</param>
    /// <param name="action">请求发起后处理回调结果的委托,处理请求结果的图片</param>
    /// <returns></returns>
    IEnumerator _GetTexture(string url, Action<Texture2D> actionResult)
    {
        UnityWebRequest uwr = new UnityWebRequest(url);
        DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
        uwr.downloadHandler = downloadTexture;
        yield return uwr.SendWebRequest();
        Texture2D t = null;
        if (!(uwr.isNetworkError || uwr.isHttpError))
        {
            t = downloadTexture.texture;
        }
        else
        {
            Debug.Log("下载失败,请检查网络,或者下载地址是否正确 ");
        }

        if (actionResult != null)
        {
            actionResult(t);
        }
    }

    #endregion

    /// <summary>
    /// 加載 PageItem
    /// </summary>
    /// <returns></returns>
    private GameObject LoadAppItem()
    {
        GameObject tmp = Resources.Load<GameObject>(PageItemPath);
        if (tmp == null)
        {
            Debug.LogError("AppItem Load Failure!! AppItemPath may be Error.");
            return null;
        }

        return tmp;
    }

    /// <summary>
    /// 加載 MultiPageToggleItem
    /// </summary>
    /// <returns></returns>
    private GameObject LoadMultiPageToggleItem()
    {
        GameObject tmp = Resources.Load<GameObject>(MultiPageToggleItemPath);
        if (tmp == null)
        {
            Debug.LogError("AppItem Load Failure!! AppCountToggleItemPath may be Error.");
            return null;
        }

        return tmp;
    }

    /// <summary>
    /// 展示 Page Icon 列表
    /// 注意 有考虑到数据动态的怎加或减少的情况
    /// </summary>
    /// <param name="pageIconTextureList"></param>
    /// <returns></returns>
    private IEnumerator ShowPageIconList(List<Texture2D> pageIconTextureList)
    {
        yield return new WaitForEndOfFrame();
        PageIconListCount = pageIconTextureList.Count;
        mPageIconTextureList = pageIconTextureList;

        #region 当前页数和总页数        

        // 设置初始当前页为 1
        currentPage = 1;
        // 判断总数量是否整除每页数量 (有余则总页数+1,整除则不用)
        totalPage = (int)(PageIconListCount / ShowPageIconItemCountPerPage) + (((PageIconListCount % ShowPageIconItemCountPerPage) == 0) ? 0 : 1);

        #endregion

        #region 底部任意切换页数的UI Toggel 显示生成

        // Page Toggle  (底部任意切换页数的UI Toggel 显示生成)
        HideMultiPageToggleItems();
        if (PageToggleGroup.childCount >= totalPage)
        {
            for (int i = 0; i < totalPage; i++)
            {
                MultiPageToggleItem multiPageToggleItem = PageToggleGroup.GetChild(i).GetComponent<MultiPageToggleItem>();
                SetMultiPageToggleItemData(i, multiPageToggleItem);
                multiPageToggleItem.gameObject.SetActive(true);
            }


        }
        else
        {

            for (int i = 0; i < PageToggleGroup.childCount; i++)
            {
                MultiPageToggleItem multiPageToggleItem = PageToggleGroup.GetChild(i).GetComponent<MultiPageToggleItem>();
                SetMultiPageToggleItemData(i, multiPageToggleItem);
                multiPageToggleItem.gameObject.SetActive(true);
            }

            // 之前生成不够数量的 multiPageToggleItem 则生成
            for (int i = PageToggleGroup.childCount; i < totalPage; i++)
            {
                MultiPageToggleItem multiPageToggleItem = GameObject.Instantiate(mMultiPageToggleItem).GetComponent<MultiPageToggleItem>();
                SetMultiPageToggleItemData(i, multiPageToggleItem);
            }
        }

        #endregion

        #region Page Icon 的展示

        // Page Item (Page Icon 的展示(原理同上类似))
        currentIntiateItem = PageGrid_Image.childCount;

        if (PageIconListCount < ShowPageIconItemCountPerPage)
        {
            // 隱藏所有,保障多餘的不會顯示
            HidePageItems();
        }

        // 展示已有的不必重新生成的對象(currentIntiateItem 不會超過ShowAppItemCountPerPage)
        for (int i = 0; i < currentIntiateItem; i++)
        {
            if (PageIconListCount < currentIntiateItem)
            {
                if (i == PageIconListCount)
                {
                    break;
                }
            }

            PageItem pageItem = PageGrid_Image.GetChild(i).GetComponent<PageItem>();
            pageItem.gameObject.SetActive(true);
            SetPageItemData(i, pageIconTextureList, pageItem);
        }

        // App總數大於生成的 生成的小於 ShowAppItemCountPerPage 個
        // 1、App總數大於 ShowAppItemCountPerPage
        // 2、App總數小於等於 ShowAppItemCountPerPage
        if (PageIconListCount > currentIntiateItem)
        {
            if (ShowPageIconItemCountPerPage < PageIconListCount)
            {
                for (int i = currentIntiateItem; i < ShowPageIconItemCountPerPage; i++)
                {
                    PageItem pageItem = Instantiate(mPageItem).GetComponent<PageItem>();
                    SetPageItemData(i, pageIconTextureList, pageItem);

                }
            }
            else
            {
                for (int i = currentIntiateItem; i < PageIconListCount; i++)
                {
                    PageItem pageItem = Instantiate(mPageItem).GetComponent<PageItem>();
                    SetPageItemData(i, pageIconTextureList, pageItem);

                }
            }
        }

        #endregion

        #region 页数和翻页按钮的更新
        //更新頁碼
        PageCount_Text.text = currentPage + "/" + totalPage;
        // 最前頁,把左翻頁隱藏
        LeftPage_Button.gameObject.SetActive(false);
        // 只有一页,右翻页也隐藏
        if (totalPage == 1)
        {
            RightPage_Button.gameObject.SetActive(false);
        }

        #endregion
    }


    #region 左右翻页操作数据显示

    /// <summary>
    /// 向前(左)翻頁
    /// </summary>
    private void LeftPageEvent()
    {

        // 最前一頁,不能左翻頁        
        if ((currentPage) == 1)
        {
            return;
        }
        else
        {
            // 向左翻頁 右翻頁若隱藏即可顯示
            if (RightPage_Button.gameObject.activeSelf == false)
            {
                RightPage_Button.gameObject.SetActive(true);
            }



            currentPage = currentPage - 1;
            // Toggle 更新 (这里不会主动调用 toggle 事件,所以放心不用重复操作数据)           
            PageToggleGroup.GetChild(currentPage - 1).GetComponent<MultiPageToggleItem>().SetToggleIsOn(true);

            // 最前頁,把左翻頁隱藏
            if (currentPage == 1)
            {

                LeftPage_Button.gameObject.SetActive(false);
            }

            // 刷新展示
            int startInt = ((currentPage - 1) * ShowPageIconItemCountPerPage);

            for (int i = 0; i < ShowPageIconItemCountPerPage; i++)
            {
                PageItem pageItem = PageGrid_Image.GetChild(i).GetComponent<PageItem>();
                pageItem.gameObject.SetActive(true);
                SetPageItemData(startInt + i, mPageIconTextureList, pageItem);
            }



        }

        //更新頁碼
        PageCount_Text.text = currentPage + "/" + totalPage;

    }


    /// <summary>
    /// 向后(右)翻頁
    /// </summary>
    private void RightPageEvent()
    {

        // 最后一頁,不能右翻頁        
        if ((currentPage) == totalPage)
        {
            return;
        }
        else
        {



            // 向右翻頁 左翻頁若隱藏即可顯示
            if (LeftPage_Button.gameObject.activeSelf == false)
            {
                LeftPage_Button.gameObject.SetActive(true);
            }


            currentPage = currentPage + 1;
            // Toggle 更新 (这里不会主动调用 toggle 事件)            
            PageToggleGroup.GetChild(currentPage - 1).GetComponent<MultiPageToggleItem>().SetToggleIsOn(true);

            int startInt = ((currentPage - 1) * ShowPageIconItemCountPerPage);
            // 翻到最后一頁(可能不是10個,要計算展示個數)
            if (currentPage == (totalPage))
            {
                // 隱藏所有,保障多餘的不會顯示
                HidePageItems();

                int endInt = PageIconListCount - startInt;
                for (int i = 0; i < endInt; i++)
                {
                    PageItem pageItem = PageGrid_Image.GetChild(i).GetComponent<PageItem>();
                    pageItem.gameObject.SetActive(true);
                    SetPageItemData(startInt + i, mPageIconTextureList, pageItem);
                }

                // 把右翻頁隱藏
                RightPage_Button.gameObject.SetActive(false);
            }
            else
            { // 翻到不是最后一頁(10個展示即可)


                for (int i = 0; i < ShowPageIconItemCountPerPage; i++)
                {
                    PageItem pageItem = PageGrid_Image.GetChild(i).GetComponent<PageItem>();
                    pageItem.gameObject.SetActive(true);
                    SetPageItemData(startInt + i, mPageIconTextureList, pageItem);
                }
            }



        }


        //更新頁碼
        PageCount_Text.text = currentPage + "/" + totalPage;
    }

    #endregion


    #region Toggle 翻页数据(这里有底部(子) MultiPageToggleItem 发送消息调用)

    /// <summary>
    /// Toggle翻页
    /// </summary>
    /// <param name="page"></param>
    public void ToggelPageEvent(int page)
    {
        if (currentPage == page)
        {
            return;
        }
        currentPage = page;


        // 最前頁,把左翻頁隱藏
        if (currentPage == 1)
        {

            LeftPage_Button.gameObject.SetActive(false);
        }
        else
        {
            LeftPage_Button.gameObject.SetActive(true);
        }
        if (currentPage == totalPage)
        {
            // 把右翻頁隱藏
            RightPage_Button.gameObject.SetActive(false);
        }
        else
        {
            RightPage_Button.gameObject.SetActive(true);
        }



        int startInt = ((currentPage - 1) * ShowPageIconItemCountPerPage);
        // 翻到最后一頁(可能不是10個,要計算展示個數)
        if (currentPage == (totalPage))
        {
            // 隱藏所有,保障多餘的不會顯示
            HidePageItems();

            int endInt = PageIconListCount - startInt;
            for (int i = 0; i < endInt; i++)
            {
                PageItem pageItem = PageGrid_Image.GetChild(i).GetComponent<PageItem>();
                pageItem.gameObject.SetActive(true);
                SetPageItemData(startInt + i, mPageIconTextureList, pageItem);
            }


        }
        else
        { // 翻到不是最后一頁(10個展示即可)


            for (int i = 0; i < ShowPageIconItemCountPerPage; i++)
            {
                PageItem pageItem = PageGrid_Image.GetChild(i).GetComponent<PageItem>();
                pageItem.gameObject.SetActive(true);
                SetPageItemData(startInt + i, mPageIconTextureList, pageItem);
            }
        }

        //更新頁碼
        PageCount_Text.text = currentPage + "/" + totalPage;
    }

    #endregion

    /// <summary>
    /// 设置生成的 pageItem 的数据
    /// </summary>
    /// <param name="i"></param>
    /// <param name="pageIconlist"></param>
    /// <param name="pageItem"></param>
    private void SetPageItemData(int i, List<Texture2D> pageIconlist, PageItem pageItem)
    {
        pageItem.transform.SetParent(PageGrid_Image, false);
        pageItem.transform.localScale = Vector3.one;
        pageItem.IconTexture = pageIconlist[i];
       
    }

    /// <summary>
    /// 设置 MultiPageToggleItem 实体数据信息
    /// </summary>
    /// <param name="i"></param>
    /// <param name="multiPageToggleItem"></param>
    private void SetMultiPageToggleItemData(int i, MultiPageToggleItem multiPageToggleItem)
    {
        multiPageToggleItem.transform.SetParent(PageToggleGroup, false);
        multiPageToggleItem.transform.localScale = Vector3.one;
        multiPageToggleItem.Page = i + 1;
        multiPageToggleItem.SetToggleGroup(PageToggleGroup.GetComponent<ToggleGroup>());

        // 为了默认第一个 toggle 是 isOn 显示的(预制体要提前 false)
        if (i != 0)
        {
            multiPageToggleItem.SetToggleIsOn(false);
        }
        else
        {
            multiPageToggleItem.SetToggleIsOn(true);
        }
    }

    /// <summary>
    /// 隐藏 PageToggleGroup 下所有 MultiPageToggleItem 实体
    /// </summary>
    private void HideMultiPageToggleItems()
    {
        for (int i = 0; i < PageToggleGroup.childCount; i++)
        {
            PageToggleGroup.GetChild(i).gameObject.SetActive(false);
        }
    }

    /// <summary>
    /// 隐藏 PageGrid_Image 下所有 PageItem 实体
    /// </summary>
    private void HidePageItems()
    {
        for (int i = 0; i < PageGrid_Image.childCount; i++)
        {
            PageGrid_Image.GetChild(i).gameObject.SetActive(false);
        }
    }

    #endregion

    #region Unity回调

    /// <summary>
    /// Awake this instance.
    /// </summary>
    void Awake()
    {

        // 下載 AppItem
        mPageItem = LoadAppItem();
        mMultiPageToggleItem = LoadMultiPageToggleItem();

        // 綁定左右翻页的监听事件
        LeftPage_Button.onClick.AddListener(LeftPageEvent);
        RightPage_Button.onClick.AddListener(RightPageEvent);

       
    }

    

    private void OnEnable()
    {
        //StartCoroutine(ShowPageIconList( GetWindiowsPCPicturesPath.GetPictutresPathsInTheFilePath(pageIconPath)));
    }

    #endregion




}

 

2、PageItem.cs

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

public class PageItem : MonoBehaviour
{
    public RawImage Icon_RawImage;

    // 字段
    private Texture2D iconTexture;
    private string iconpath;

    // 属性
    public Texture2D IconTexture { get => iconTexture;
        set {
            iconTexture = value;

            if (Icon_RawImage != null)
            {
                Icon_RawImage.texture = iconTexture;
            }
        }
    }
    public string Iconpath { get => iconpath; set {

            iconpath = value;
            GetTexture(iconpath,(texture2d)=> {
                IconTexture = texture2d;
            });
        }
    }



    #region 其他视情况而定的方法 协程加载指定路径的图片 (注意:动态多图加载,这种方式很有可能会让程序奔溃)

    /// <summary>
    /// 请求图片
    /// </summary>
    /// <param name="url">图片地址,like 'http://www.my-server.com/image.png '</param>
    /// <param name="action">请求发起后处理回调结果的委托,处理请求结果的图片</param>
    /// <returns></returns>
    public void GetTexture(string url, Action<Texture2D> actionResult)
    {
        StartCoroutine(_GetTexture(url, actionResult));
    }

    /// <summary>
    /// 请求图片
    /// </summary>
    /// <param name="url">图片地址,like 'http://www.my-server.com/image.png '</param>
    /// <param name="action">请求发起后处理回调结果的委托,处理请求结果的图片</param>
    /// <returns></returns>
    IEnumerator _GetTexture(string url, Action<Texture2D> actionResult)
    {
        UnityWebRequest uwr = new UnityWebRequest(url);
        DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
        uwr.downloadHandler = downloadTexture;
        yield return uwr.SendWebRequest();
        Texture2D t = null;
        if (!(uwr.isNetworkError || uwr.isHttpError))
        {
            t = downloadTexture.texture;
        }
        else
        {
            Debug.Log("下载失败,请检查网络,或者下载地址是否正确 ");
        }

        if (actionResult != null)
        {
            actionResult(t);
        }
    }

    #endregion

}

 

3、MultiPageToggleItem.cs


using UnityEngine;
using UnityEngine.UI;

public class MultiPageToggleItem : MonoBehaviour
{
    public Toggle MultiPage_Toggle;

    private int page;

    public int Page { get => page; set => page = value; }

    // Start is called before the first frame update
    void Start()
    {
        // 绑定事件
        MultiPage_Toggle.onValueChanged.AddListener((isOn) => {
            if (isOn == true)
            {
                Debug.Log("发送消息 ToggelPageEvent " + Page);
                SendMessageUpwards("ToggelPageEvent", Page);
            }
        });
    }

    /// <summary>
    /// 设置 ToggleGroup
    /// </summary>
    /// <param name="toggleGroup"></param>
    public void SetToggleGroup(ToggleGroup toggleGroup)
    {
        MultiPage_Toggle.group = toggleGroup;
    }

    /// <summary>
    /// 设置 isON
    /// </summary>
    /// <param name="isOn"></param>
    public void SetToggleIsOn(bool isOn)
    {
        MultiPage_Toggle.isOn = isOn;
    }

}

 

4、GetWindiowsPCPicturesPath.cs



using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;

using UnityEngine;

public class GetWindiowsPCPicturesPath {

    public static void DebugPaths() {
        List<string> filePaths = GetPictutresPathsInTheFilePath(@"D:\Tmp\Images");
        for (int i = 0; i < filePaths.Count; i++)
        {
            Debug.Log(filePaths[i]);
        }  
    }

    /// <summary>
    /// win 中获取指定文件夹下的图片,不包括子文件夹的图片
    /// </summary>
    /// <param name="path"></param>
    /// <returns>图片路径集合列表</returns>
    public static List<string> GetPictutresPathsInTheFilePath(string filePath)
    {
        List<string> filePaths = new List<string>();
        string imgtype = "*.BMP|*.JPG|*.GIF|*.PNG";
        string[] ImageType = imgtype.Split('|');
        for (int i = 0; i < ImageType.Length; i++)
        {
            //获取指定文件夹下所有的图片路径  
            string[] dirs = Directory.GetFiles(filePath, ImageType[i]);
            for (int j = 0; j < dirs.Length; j++)
            {
                filePaths.Add(dirs[j]);
            }
        }

        return filePaths;
    }
}

 

七、参考工程

下载地址:https://download.csdn.net/download/u014361280/12639147

 

猜你喜欢

转载自blog.csdn.net/u014361280/article/details/107445358