懒,是老毛病了,周末跑了半马,跑完也是一通累,好久没锻炼了。。也是懒的,有时都懒的写博客。。
最近看到项目中各种滑动列表框,本着要懒出水平来的原则,决定花点时间简单处理下(暂时未做列表太多时的优化):
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在中心计算的!
这样,就实现了最终偷懒的目的!

使用泛型简单封装NGUI的ScrollView实现滑动列表的更多相关文章

  1. .Net Core应用RabbitMQ,及简单封装

    首先,还是万分感谢大家能够抽空来阅读我的文章,万分感谢.今天我带来的是.Net Core中应用RabbitMQ,和简单封装.因为昨天的文章里说了今天要写,所以今天一定要写出来.小编翻阅了很多资料,想要 ...

  2. 孟老板 BaseAdapter封装 (一) 简单封装

    BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...

  3. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  4. FMDB简单封装和使用

    工具:火狐浏览器+SQLite Manager插件 ; Xcode; FMDB库; 效果: 项目地址: https://github.com/sven713/PackFMDB 主要参考这两篇博客: 1 ...

  5. Android--Retrofit+RxJava的简单封装(三)

    1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...

  6. okhttp3 get post 简单封装

    最近打算在新项目中使用 okhttp3, 简单封装了一下异步 get post 因为 CallBack 也是在子线程中执行,所以用到了 Handler public class MyOkHttpCli ...

  7. python网页请求urllib2模块简单封装代码

    这篇文章主要分享一个python网页请求模块urllib2模块的简单封装代码. 原文转自:http://www.jbxue.com/article/16585.html 对python网页请求模块ur ...

  8. 对pymysql的简单封装

    #coding=utf-8 #!/usr/bin/python import pymysql class MYSQL: """ 对pymysql的简单封装 "& ...

  9. iOS开发——UI篇OC篇&UITableView简单封装

    UITableView简单封装 UITableView时iOS开发中使用最多也是最重的一个UI空间,其实在App Store里面的%80以上的应用都用到了这个控件,所以就给大家介绍一下,前面的文章中也 ...

随机推荐

  1. Django生产环境的部署-Apache-mod_wsgi

    httpd.conf配置 ServerSignature On ServerTokens Full Define APACHE24 Apache2.4 Define SERVER_BASE_DIR & ...

  2. (转载)MVC + JQUERY + AJAX的几种方式

    MVC + JQUERY + AJAX的几种方式 // 传过去一个简单值,获取一个简单值 $.ajax({            type: "GET",         url: ...

  3. 隐私:网民最常用密码MD5解密

    国内知名网络安全商瑞星公司曾发布过一项针对密码强度的专业研究报告,这项研究中列举了中国网民和美国网民最常用的密码集.研究表明,全球互联网大部分用户在密码使用中都存在着种种疏漏,一些极其简单的密码被广泛 ...

  4. Bootstrap 轮播(Carousel)插件

    Bootstrap 轮播(Carousel)插件是一种灵活的响应式的向站点添加滑块的方式.除此之外,内容也是足够灵活的,可以是图像.内嵌框架.视频或者其他您想要放置的任何类型的内容. 如果您想要单独引 ...

  5. JSON数据与JavaScript对象转换

    使用JSON时,最基本的工作就是JSON数据与JavaScript对象之间的互相转换.如浏览器 从服务器端获得JSON数据,然后转换为JavaScript对象在网页输出. SON: JavaScrip ...

  6. 17.2.2 Replication Relay and Status Logs 复制Relay 和状态日志;

    17.2.2 Replication Relay and Status Logs 复制Relay 和状态日志: 17.2.2.1 The Slave Relay Log 17.2.2.2 Slave ...

  7. 【HDOJ】2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

    多重背包. #include <stdio.h> #include <string.h> ]; int n, m; void completePac(int p, int h) ...

  8. 【转】Xcode7.1环境下上架iOS App到AppStore 流程 (Part 三)

    原文网址:http://www.cnblogs.com/ChinaKingKong/p/4964745.html 前言部分 part三 部分主要讲解 Xcode关联绑定发布证书的配置.创建App信息. ...

  9. Centos6.4 设置开机自动以某个非root用户启动脚本

    开机自动运行脚本,可以将脚本的执行命令放在 /etc/rc.d/rc.local 文件中,但是这样开机自动运行这个脚本的用户默认为root. 如果想以某个非root用户运行脚本,可以使用如下命令: s ...

  10. [C# 网络编程系列]专题九:实现类似QQ的即时通信程序

    转自:http://www.cnblogs.com/zhili/archive/2012/09/23/2666987.html 引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例 ...