zoukankan      html  css  js  c++  java
  • 使用泛型简单封装NGUI的ScrollView实现滑动列表

    懒,是老毛病了,周末跑了半马,跑完也是一通累,好久没锻炼了。。也是懒的,有时都懒的写博客。。
    最近看到项目中各种滑动列表框,本着要懒出水平来的原则,决定花点时间简单处理下(暂时未做列表太多时的优化):
    1、首先分析共性方面的东西:
    逻辑上,都有个基础Item类及对应的管理类ItemManager
    显示上,都是显示某个基本对象ViewItem,并且都需要管理者UIScrollView(封装为ViewManager)

    2、根据初步的分析结果,进行抽象,这里直接使用泛型处理:
    (这里直接使用了原有的Json插件及部分项目中需求的设计:int类型的key)
    1)先说下逻辑层(基础)
    A.首先是Item类:
    存储单个基础的各种信息,此处未使用struct,因为不引用的情况下会导致后期对item的很多更新管理、状态改变造成不便。设计如下:
    using UnityEngine;
    using LitJson;

    public abstract class Item
    {
      public int ID;

      public Item()
      {
        
      }

      public abstract void Init(JsonData _data);
    }

    B.其次是对应的管理类ItemManager:
    using UnityEngine;
    using LitJson;
    using System;
    using System.Collections.Generic;

    public abstract class ItemManager<T> where T : Item, new()
    {
      public IList<T> ItemLst = new List<T>();
      public T GetItemByID(int _id)
      {
        for(int i = 0; i < ItemLst.Count; i++)
        {
          if(ItemLst[i].ID == _id)
          {
            return ItemLst[i];
          }
        }
        return null;
      }

      public virtual void Init(JsonData _jsonData, Action<IList<T>> _callback = null)
      {
        ItemLst.Clear(); //刷新
        if(_jsonData == null || _jsonData.Equals(""))
        {

        }
        else
        {
          for(int i = 0; i < _jsonData.Count; i++)
          {
            JsonData tJson = _jsonData[i];

            T tItem = new T();
            tItem.Init(tJson);
            ItemLst.Add(tItem);
          }
          if(_callback != null) //回调
          {
            _callback(ItemLst);
          }
        }
      }
    }
    2)其次再来说一下显示层View
    A.首先单个的ViewItem单元,负责自身的初始化、显示、交互(继承时,各自去实现、管理)等:
    using UnityEngine;
    using System.Collections;

    public abstract class ViewItem<T> : MonoBehaviour where T : Item
    {
      protected T item;

      public virtual void Init(T _item)
      {
        item = _item;


      }
    }

    B.对应的是显示的控制:
    using UnityEngine;
    using System.Collections.Generic;

    public abstract class ViewManager<T, V> : MonoBehaviour
    where T : Item
    where V : ViewItem<T>
    {
      [SerializeField]
      protected UIScrollView scrollView;
      [SerializeField]
      protected UIGrid uiGridObj;
      private GameObject father;
      [SerializeField]
      private V viewItemPrefab;

      void Start()
      {
        father = uiGridObj.gameObject;

      }

      public void RefreshShow()
      {
        scrollView.gameObject.SetActive(false);
        scrollView.gameObject.SetActive(true);
        uiGridObj.repositionNow = true;
      }

      public virtual void ShowInfo(IList<T> _lst)
      {
        foreach(var item in cacheMap)
        {
          item.Value.gameObject.SetActive(false);
        }
        for(int i = 0; i < _lst.Count; i++)
        {
          var item = _lst[i];
          if(!cacheMap.ContainsKey(item.ID))
          {
            GameObject tItem = NGUITools.AddChild(father, viewItemPrefab.gameObject);

            V tViewItem = tItem.GetComponent<V>();
            tViewItem.Init(item);

            cacheMap.Add(item.ID, tViewItem);
          }
          else
          {
            cacheMap[item.ID].Init(item);

          }
          cacheMap[item.ID].gameObject.SetActive(true);
          uiGridObj.AddChild(cacheMap[item.ID].transform);
          cacheMap[item.ID].transform.localScale = Vector3.one;
        }

        RefreshShow();
      }
      protected void deleteItem(int _id)
      {
        foreach(var kv in cacheMap)
        {
          if(kv.Key == _id)
          {
            kv.Value.gameObject.SetActive(false);
            break;
          }
        }
        uiGridObj.repositionNow = true;
      }
      protected Dictionary<int, V> cacheMap = new Dictionary<int, V>();
    }

    因为在使用NGUI的Grid布局时CellSnap的方式(不明白是自己使用的方式存在错误还是本身的问题?还望有经验的朋友指教一下),需要自己进行计算实现,这样我们需要自己重写ShowInfo方法,比如:
    using UnityEngine;
    using System.Collections.Generic;

    public class CellViewManager : ViewManager<IconInfo, IconViewItem>
    {
      public static CellViewManager m_pIns = null;
      void Awake()
      {
        m_pIns = this;

        scrollviewPanel = scrollView.GetComponent<NGUIPanel>();
      }

      private NGUIPanel scrollviewPanel;

      public override void ShowMailInfo(IList<IconInfo> _lst)
      {
        base.ShowMailInfo(_lst);

        if(uiGridObj.arrangement == UIGrid.Arrangement.CellSnap)
        {
          int tX = 0;
          int tY = 0;
          foreach(var item in cacheMap)
          {
            if(item.Value.gameObject.activeSelf)
            {
              float tWidth = uiGridObj.cellWidth * tX;
              if(tWidth + uiGridObj.cellWidth / 2 > scrollviewPanel.width)
              {
                tWidth = 0;
                tX = 1;
                tY--;
              }
              else
              {
                tX++;
              }
              item.Value.transform.localPosition = new Vector3(tWidth, tY * uiGridObj.cellHeight, 0);
            }
          }

          RefreshShow();
        }
      }
    }
    这里计算边界是根据ViewItem的widget在中心计算的!
    这样,就实现了最终偷懒的目的!

  • 相关阅读:
    子组 正则表达式
    正则表达式
    马云北大演讲完整版:真心话,什么才是阿里的核心竞争力?-2014-03-20
    形象化的spring 依赖注入原理
    程序员的六层境界
    apache配置运行zendframework 2
    php编写简单的页面跳转功能
    php随机验证码
    没啥说的
    PHP流程控制语句下
  • 原文地址:https://www.cnblogs.com/wayland/p/5082639.html
Copyright © 2011-2022 走看看