码迷,mamicode.com
首页 > 其他好文 > 详细

【小松教你手游开发】【系统模块开发】ngui做聊天系统

时间:2016-08-04 19:15:19      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:

用ngui做聊天系统有个简单的方法是用教程Exampl12里的TextList来做聊天系统。
但显然一个UILabel做的聊天系统拓展性不高,并且要做特殊点击事件会变得很麻烦。
 
所以我们还是用一个UIScrollView下挂一个UITable,把UILabel和其他东西封装成一个Prefab一个个加载到UITable来实现。
 
如果不考虑其他因素就是一个简单的UIScrollView相信大家都没什么问题。
 
不过项目中会有两个技术难点。
1.要实现图文混排
2.如果对话多的话(比如世界频道,每个玩家都可以发信息,很容易就一百条以上),肯定不能每个都实例化一个Prefab,所以UIScrollView要做循环加载。
 
 
1.关于图文混排在之前的文章中就讲到怎么实现
http://www.cnblogs.com/chrisfxs/p/5737607.html
 
所以本文主要讲的是第二点.循环加载
 
循环加载的意思就是,比如一个聊天系统,在可显示的范围内,用最少的Prefab,通过改里面的数值去显示不同数据,而不是每一个数据实例化一个Prefab。
 
在ngui的教程里就有教你怎么用ngui的UIScrollView里实现循环加载。
但是这里有一个前提是。它用的是UIScrollView下挂UIGrid,UIGrid下挂Prefab。且每个Prefab的高度一致。
这样可以准确的计算出最少需要多少个Prefab,现在滑动到哪个Prefab,且现在每个Prefab应该插入什么数据。
 
但是像聊天这样的系统,每个人发的每句话字数都不一样,也就是每个UILabel的高度不一样。这样导致了上面的计算都无法实现。
 
所以本来做好的UIScrollView的循环加载就需要调整。
 
首先是不用UIGrid用UITable。因为UITable不要求每一行的间距统一
 
接着就是写一个继承UIScrollView的类来实现循环加载。我这里叫CUIChatScrollView: UIScrollView
 
因为代码比较复杂,在最后的时候在一次过放上代码,这里先讲思路
 
 
 
首先按一般的循环加载我们要做的是知道这个UISCrollView最多同时要显示多少个Prefab,我们总共有多少数据。每个Prefab多高。当最上一块或最下一个滑出边框就把它移到另一边。
 
而由于现在高度不一,所以上面除了总共有多少数据是知道的其他都不能确定。
 
所以我们只能换种方式。
 
我们实例化足够的数,通过设定两个上线临界值来判断是否需要把Prefab移到另一边,而不通过边框计算。
通过索引index而不通过计算滑动位置与这个的比例来计算应该插入的数据的索引。
 
 
所以对于第一种可以做到的,最多同屏显示6条数据的话,我们只用实例化7个Prefab,这种最优方案我们没法使用。
我们只能预估一个值,实例化一个合适的数,比如每一个聊天语句只有一行的话,整个界面有多少条,然后再比这个数多一点。
 
 
在我的项目中上下最多显示3条,不过我这里也需要6条来实现循环加载。也就是实例化10个Prefab。
如果是文字只有一行的话我的像素是25,我的上下临界值设为250.
(这些数值都还可以再优化,我只是随便取了一些数)
 
 
在原来一般的循环加载逻辑下,实例化10个Prefab,当向下滑动时的Prefab超过下边框就移到另一边,向上一样。
 
而当前的Prefab应该插入什么数据不再通过计算当前点击position除于每个Prefab的高度interver来计算出index来插入数据。而是记录下index,如果把上面的Prefab移到下面就index++。如果下面的移到上面就index--。
而因为index作为索引如果从0开始,而最下面的index就是index加实例化的Prefab数,我的就是10.
 
 
而原本计算目标position的方式也不能用了。原本滑动到顶端把prefab移到低端通过最下面的prefab加高度interver就能知道。
现在最下面的要通过先把文字放到UILabel,通过NGUI的函数NGUIMath.CalculateRelativeWidgetBounds计算UILabel的宽高,加上最下面的Prefab的position来确定位置。
 
 
大概思路是这样
 
 
下面贴上代码
[csharp] view plain copy
 
 技术分享技术分享
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using System.Collections.Generic;  
  4.   
  5. public class CUIChatScrollView : UIScrollView  
  6. {  
  7.   
  8.     public delegate void OnMoveCallBack();  
  9.     /// <summary>  
  10.     /// 每次滑动结束的回调  
  11.     /// </summary>  
  12.     public OnMoveCallBack mOnMoveCallback;  
  13.   
  14.     public delegate void OnMoveNextPage(int pageindex);  
  15.     public OnMoveNextPage mOnMoveNextPage;  
  16.   
  17.     private float mTopOffSetValue = 250;  
  18.     private float mBottomOffSetValue = 250;  
  19.     /// <summary>  
  20.     /// 当前数据总数  
  21.     /// </summary>  
  22.     private int mTotalCount = 0;  
  23.     /// <summary>  
  24.     /// 子物体当前临时坐标  
  25.     /// </summary>  
  26.     private float mTempPosition = 0;  
  27.     /// <summary>  
  28.     /// 子物体当前临时相对坐标(与UIPanel偏移、DynamicComponentTran、自己本身坐标之和,如果UIpanel裁剪区域有偏移还需要加上UIPanel FinalClipRegion的偏移值(X或者Y))  
  29.     /// </summary>  
  30.     private float mBorderValue = 0;  
  31.     /// <summary>  
  32.     /// 当前显示出来的物体列表  
  33.     /// </summary>  
  34.     private List<CBaseComponent> mCurrentComList = new List<CBaseComponent>();  
  35.     /// <summary>  
  36.     /// 当前循环临时加载的列表(达到临界值需要移动的Components)  
  37.     /// </summary>  
  38.     private List<CBaseComponent> mTempComList = new List<CBaseComponent>();  
  39.     /// <summary>  
  40.     ///  挂载UIGrid的组件物体,是components父物体,UIPanel子物体  
  41.     /// </summary>  
  42.     private Transform DynamicComponentTran;  
  43.     /// <summary>  
  44.     /// 当前ScrollView依赖的UIPanel  
  45.     /// </summary>  
  46.     private UIPanel mUIPanel;  
  47.     /// <summary>  
  48.     /// UIPanel最终的绘制区域、坐标  
  49.     /// </summary>  
  50.     private Vector4 mPanelFinalClipRegion;  
  51.     /// <summary>  
  52.     /// 是否需要请求下一页数据(用于多数据分页加载情况)  
  53.     /// </summary>  
  54.     private bool bNeedReqNextPage;  
  55.     /// <summary>  
  56.     /// 每页的数量(用于分页)  
  57.     /// </summary>  
  58.     private int mPrePageNumber;  
  59.     /// <summary>  
  60.     /// 是否是排行榜模式  
  61.     /// </summary>  
  62.     private bool bIsRankModel;  
  63.     /// <summary>  
  64.     /// 当前自己的排名  
  65.     /// </summary>  
  66.     private int mCurrentMyRank;  
  67.     /// <summary>  
  68.     /// 缓存开关  
  69.     /// </summary>  
  70.     private Dictionary<int, bool> bHasRequestDic = new Dictionary<int, bool>();  
  71.     /// <summary>  
  72.     /// 用于比较的X坐标  
  73.     /// </summary>  
  74.     private float xPos;  
  75.     /// <summary>  
  76.     /// 用于比较的Y坐标  
  77.     /// </summary>  
  78.     private float yPos;  
  79.     /// <summary>  
  80.     /// 是否需要3D显示效果  
  81.     /// </summary>  
  82.     private bool bShow3DStyle = false;  
  83.     /// <summary>  
  84.     /// 居中的子物体  
  85.     /// </summary>  
  86.     public Transform mCenterTranform;  
  87.     /// <summary>  
  88.     /// 子物体的depath  
  89.     /// </summary>  
  90.     private UIPanel mTempUIPanel;  
  91.     /// <summary>  
  92.     ///  ScrollView 的UIPanel depath。  
  93.     /// </summary>  
  94.     private int mUIPanelDepth = 1;  
  95.   
  96.     private int m_Index = 0;  
  97.     private int m_maxShowNum = 0;  
  98.   
  99.     public void Init<T>(List<T> components, int maxShowNum, int totalNumber, Transform dyTransorm, Movement moveMent = Movement.Horizontal, bool needrequest = false, int prepagenum = 0, bool isrank = false, int myrank = 0, bool bshow3d = false) where T : CBaseComponent  
  100.     {  
  101.         m_Index = maxShowNum-1;  
  102.         m_maxShowNum = maxShowNum;  
  103.         mCurrentComList.Clear();  
  104.         for (int i = 0, length = components.Count; i < length; i++)  
  105.         {  
  106.             if (components[i] is CBaseComponent)  
  107.             {  
  108.                 mCurrentComList.Add(components[i]);  
  109.             }  
  110.         }  
  111.         //mCurrentComList = components as List<CBaseComponent>;  
  112.         DynamicComponentTran = dyTransorm;  
  113.         mTotalCount = totalNumber;  
  114.         movement = moveMent;  
  115.         mPanelFinalClipRegion = (mUIPanel ?? (mUIPanel = gameObject.GetComponent<UIPanel>())).finalClipRegion;  
  116.         mUIPanelDepth = mUIPanel.depth + 10;//子物体固定高出父物体深度10个单位  
  117.         //if (movement == Movement.Vertical)  
  118.         //    mOffSetValue = mPanelFinalClipRegion.w / 2 + mItemIntervalValue / 2f;  
  119.         //else if (moveMent == Movement.Horizontal)  
  120.         //    mOffSetValue = mPanelFinalClipRegion.z / 2 + mItemIntervalValue / 2f;  
  121.         bNeedReqNextPage = needrequest;  
  122.         mPrePageNumber = prepagenum;  
  123.         bIsRankModel = isrank;  
  124.         mCurrentMyRank = myrank;  
  125.         bHasRequestDic.Clear();  
  126.         bShow3DStyle = bshow3d;  
  127.         momentumAmount = 35f;  
  128.     }  
  129.   
  130.     public override void MoveRelative(Vector3 relative)  
  131.     {  
  132.         base.MoveRelative(relative);  
  133.         CheckScrollView(relative);  
  134.     }  
  135.   
  136.     public override void AdjustSpring(Vector3 relative)  
  137.     {  
  138.         base.AdjustSpring(relative);  
  139.         CheckScrollView(relative);  
  140.     }  
  141.   
  142.     private void CheckScrollView(Vector3 relative)  
  143.     {  
  144.         if (mCurrentComList == null || mCurrentComList.Count == 0)  
  145.             return;  
  146.   
  147.         if (movement == Movement.Horizontal)  
  148.         {  
  149.             xPos = relative.x;  
  150.             mCurrentComList.Sort(delegate (CBaseComponent a, CBaseComponent b) { return a.LocalPosition.x.CompareTo(b.LocalPosition.x); });  
  151.         }  
  152.         else if (movement == Movement.Vertical)  
  153.         {  
  154.             yPos = relative.y;  
  155.             mCurrentComList.Sort(delegate (CBaseComponent a, CBaseComponent b) { return b.LocalPosition.y.CompareTo(a.LocalPosition.y); });  
  156.         }  
  157.   
  158.         mTempComList.Clear();  
  159.   
  160.         if ((yPos > 0 && movement == Movement.Vertical) || (xPos < 0 && movement == Movement.Horizontal))  
  161.         {  
  162.             Transform temptran = mCurrentComList[mCurrentComList.Count - 1].ComTransform;  
  163.             if (movement == Movement.Horizontal)  
  164.                 mTempPosition = temptran.localPosition.x;  
  165.             else if (movement == Movement.Vertical)  
  166.                 mTempPosition = temptran.localPosition.y;  
  167.             mTempPosition = Mathf.Abs(mTempPosition);  
  168.   
  169.             if (true)  
  170.             {  
  171.                 for (int i = 0, j = mCurrentComList.Count; i < j; i++)  
  172.                 {  
  173.                     temptran = mCurrentComList[i].ComTransform;  
  174.                     if (movement == Movement.Horizontal)  
  175.                     {  
  176.                         mBorderValue = (temptran.localPosition.x*temptran.localScale.x + transform.localPosition.x + DynamicComponentTran.localPosition.x + Mathf.Abs(mPanelFinalClipRegion.x));  
  177.                         if (mBorderValue > -mTopOffSetValue)  
  178.                         {  
  179.                             break;  
  180.                         }  
  181.                     }  
  182.                     else if (movement == Movement.Vertical)  
  183.                     {  
  184.                         mBorderValue = (temptran.localPosition.y * temptran.localScale.y + transform.localPosition.y + DynamicComponentTran.localPosition.y + Mathf.Abs(mPanelFinalClipRegion.y));  
  185.                         if (mBorderValue < mTopOffSetValue)  
  186.                         {  
  187.                             break;  
  188.                         }  
  189.                     }  
  190.                     mTempComList.Add(mCurrentComList[i]);  
  191.   
  192.                 }  
  193.             }  
  194.             for (int i = 0, j = mTempComList.Count; i < j; i++)  
  195.             {  
  196.                 if (m_Index >= mTotalCount - 1) break;  
  197.                 m_Index++;  
  198.                 if (movement == Movement.Vertical)  
  199.                 {  
  200.                     float spriteHeight = NGUIMath.CalculateRelativeWidgetBounds(transform, mCurrentComList[mCurrentComList.Count - 1].ComTransform, true).size.y;  
  201.                     mTempComList[i].LocalPosition = new Vector3(0, -(spriteHeight +mTempPosition), 0);  
  202.                 }  
  203.                 //mTempComList[i].LocalPosition = new Vector3(0, -(mItemIntervalValue * (i + 1) + mTempPosition), 0);  
  204.                 mTempComList[i].InitData(m_Index);  
  205.             }  
  206.         }  
  207.         else if ((yPos < 0 && movement == Movement.Vertical) || (xPos > 0 && movement == Movement.Horizontal))  
  208.         {  
  209.             Transform temptran = mCurrentComList[0].ComTransform;  
  210.             if (movement == Movement.Horizontal)  
  211.                 mTempPosition = temptran.localPosition.x;  
  212.             else if (movement == Movement.Vertical)  
  213.                 mTempPosition = temptran.localPosition.y;  
  214.             mTempPosition = Mathf.Abs(mTempPosition);  
  215.   
  216.             if (true)  
  217.             {  
  218.                 for (int i = mCurrentComList.Count - 1; i >= 0; i--)  
  219.                 {  
  220.                     temptran = mCurrentComList[i].ComTransform;  
  221.                     if (movement == Movement.Horizontal)  
  222.                     {  
  223.                         mBorderValue = (temptran.localPosition.x + transform.localPosition.x + DynamicComponentTran.localPosition.x + Mathf.Abs(mPanelFinalClipRegion.x));  
  224.                         if (mBorderValue <mBottomOffSetValue)  
  225.                         {  
  226.                             break;  
  227.                         }  
  228.                     }  
  229.                     else if (movement == Movement.Vertical)  
  230.                     {  
  231.                         mBorderValue = (temptran.localPosition.y + transform.localPosition.y + DynamicComponentTran.localPosition.y + Mathf.Abs(mPanelFinalClipRegion.y));  
  232.                         if (mBorderValue > -mBottomOffSetValue)  
  233.                         {  
  234.                             break;  
  235.                         }  
  236.                     }  
  237.                     mTempComList.Add(mCurrentComList[i]);  
  238.                 }  
  239.             }  
  240.             for (int i = 0, j = mTempComList.Count; i < j; i++)  
  241.             {  
  242.                 if (m_Index <= m_maxShowNum-1) break;  
  243.   
  244.                 m_Index--;  
  245.   
  246.                 //mTempComList[i].LocalPosition = new Vector3(0, -(mTempPosition - mItemIntervalValue * (i + 1)), 0);  
  247.                 mTempComList[i].InitData(m_Index - m_maxShowNum+1);  
  248.   
  249.                 if (movement == Movement.Vertical)  
  250.                 {  
  251.                     float spriteHeight = NGUIMath.CalculateRelativeWidgetBounds(transform, mTempComList[i].ComTransform, true).size.y;  
  252.                     Vector3 newPosition;  
  253.                     if (i == 0)  
  254.                         newPosition = new Vector3(0, -(mTempPosition - spriteHeight), 0);  
  255.                     else  
  256.                         newPosition = new Vector3(0, -(Mathf.Abs(mTempComList[i - 1].LocalPosition.y) - spriteHeight), 0);  
  257.                     mTempComList[i].LocalPosition = newPosition;  
  258.                 }  
  259.             }  
  260.         }  
  261.         if (mOnMoveCallback != null)  
  262.         {  
  263.             mOnMoveCallback();  
  264.         }  
  265.     }  
  266.   
  267.   
  268. }  

【小松教你手游开发】【系统模块开发】ngui做聊天系统

标签:

原文地址:http://www.cnblogs.com/chrisfxs/p/5737800.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!