已经解决了滚动List和Combo框

Posted on 2013-03-01 14:09  neocsl  阅读(691)  评论(0编辑  收藏  举报

  至此已经解决了List和Combo。但还需要进一步的优化。另外源码中还有MobileMenuList和MobileMenuBar,MobileMenuInventory。

  将当前实现了的列表做一下分析再实现这种类,秉持一贯原则:会使用比掌握原理更为重要。原理仅仅是帮助我学会这件东西。我非常讨厌从造轮子做起。

 1. AntMobileMenuObject是Button,Label,List和Combo的父类。这里定义了其接受触碰。实现接口

interface AntITouchable;
function OnPick(ETouchType EventType, float X, float Y);

  接口声明Object被触碰的函数OnPick(...)

   2.AntMobileMenuObject将其实现,MobileMenuObject implements(AntITouchable)

  定义了bIsActive和bIsHighlighted根据ETouchType是否被激活。

  每一个Object都有自己对应的X,Y坐标。这里面定义了一个函数CheckBounds来辅助OnPick函数来检测边界。X>=left&&X<=Left+Width Y轴的道理相同Top和Height

  因为要实现List,还得检测是否是Swipe这种方式触摸方式。但这里是在MobileMenuScene检测。因为Object范围太小了。

 3.Object的思想是,自己处理渲染环节。MenuScene接受屏幕输入然后将swipe或是Touch传递过去。在他的内部foreach所有的MenuObjects数组。MenuObject的OnPick来处理对应的工作。

  使用一个辅助页面AntMobileMenuBase然后将其OnSceneTouch行为交给代理OnInputTouch,OnInputTouch做的动作,所有的主页面处理全交给辅助页面来检测屏幕情况。

  主页面打开的同时开启辅助页面AntMobileMenuScene的Opended函数内部开启OpenMenuScene(class'AntMobileMenuBase'),所以这时候所有的触摸行为是针对AntMobileMenuBase操作的。

var AntMenuSceneBase HelperScene;
HelperScene.OnInputTouch = OnSceneTouch;

  在OnSceneTouch中进行一大堆的操作,例如检测是Swipe还是Touch。遍历Objects然后调用每个MenuObjects的OnPick接口,当然每个接口的功能在自己的类内部实现。

  CheckSwipe的方法实现很简单。

if(EventType==Touch_Began)
StartTouchLocation.x=TouchX;
bswipe=false;

if(EventType==Touch_Moved)
CurrentTouchLocation.x=TouchX;
checkswipe();

function checkswipe()
VSize(StartTouchLocation-CurrentTouchLoaction)>SwipeTolerance

  遍历的每个MenuObjects.OnPick(...)

4.Button的功能部分

  关于Button的OnPick接口实现,仍然使用了代理OnClick函数,完全可以在不同的表单中自定义,这就是对外的执行动作接口API。

  这个函数的实现在Combo中是ToggleList。在List的中Cancel Button用来取消Combo。Button的内容比较简单,以后我会使用枪械选择表单。

  在AntMobileMenuButton的上层是label,这个label用来显示所有外框。

5.Label渲染部分

  这一部分可以让我更方便的定义自己需要制作的表单。后边实现List的时候能修改滑动的方向。

  Images[0]和[1]可以自由的填充需要的图片,在InitMenuObject初始化这些内容。RenderObject中设置图片的透明度,以及字体内容,如果图片没有设置就填充DrawRect绘制矩形区域。画矩形区域的话有漂亮的边界显示。程序功底好的话就抛弃画师自己动手吧。

  DrawCaption是必须填充的一个地方,这里可以绘制语言描述,需要填写什么内容。

6.List是我们的最终目标

  他可以实现炫目的《无尽之剑》滚动效果,没有源码看也没有关系,google总是能找到问题解决的线索。

  List在最上面有自己的刊头,在左侧有一个退出按钮(尽管我现在还不能确定这是不是list自己画的)

  这里的功能非常完善,退出Cancel,列表的高度,列表的惯性,还有一些沙盒参数。

  在InitMenuObject中初始化列表的区域,同时初始化Cancel的区域和功能。Cancel.OnClick=HandleCancel;

  List是MenuObject的子类,这里实现RenderObject方法,来绘制List。这个函数可是实现滚动菜单的关键哦!Listen to me carefully

  用矩形绘制背景""计算当前世界时间""如果Items.length>0就开始继续绘制(以后我要在这里加上自己需要填充的图片,或者是给每个图片重新写一个类,他们占据的位置,他们具有的信息)

  float ScrollInertia;   //是不滚动时候的移动量,例如装在上边了然后被撞下来的量 

if(Items[0].top>Top+TitileBarHeight)
{
    ScrollInertia=Top+TitileBarHeight-Items[0].Top;
    ScrollDelta=ScrollInertia*DeltaTime*snapFactor;
}

  第二种情况是在不超过下部

if(items[Items.length-1].top+Itemheight<Top+ItemHeight)
{
    ScrollInertia=(Top+Height)-(Items[Items.length-1].top+ItemHeight);
    ScrollDelta=ScrollInertia*DeltaTime*SnapFactor;
}

  第三种情况是ScrollDelta=ScrollInertia*DeltaTime;

  渲染每个列表:以后在该位置改变绘制的横纵和是否用图片来显示。

for(i=0; i < Items.Length; i++)
      {
         //强制设置列表项的大小以防方位改变。
         Items[i].Left = left;
         Items[i].Top += bActive ? ScrollAmount : ScrollDelta;
         Items[i].Width = Width;
         Items[i].Height = ItemHeight;
         
         //仅当部分列表项可见时渲染该项。
         if(Items[i].Top + ItemHeight > Top && Items[i].Top < Top + Height)
         {
            Items[i].RenderObject(Canvas,DeltaTime);
         }
      }

  添加物品栏,物品栏以后会进行拓展AddItem。例如武器栏会变成有武器图片和参数信息内容。

  在AddItem中定义各种图片和文字信息:

NewItem=new(Outer) class'AntMobileMenuButton';

  RemoveItem(int Idx);

7.Combo对List的初始化及使用

List中有非常大的代码量,但是很多都是沙盒代码。在外部学会使用即可,Combo中队List有打开以及插入Item。

一个初始化按钮用于打开一个列表
var instanced AntMobileMenuButton Label;
var instanced AntMobileMenuList list;

var array<string>Items;  //用于插入武器的名字及图片列表

  在InitMenuObject中初始化需要的内容,

  List.InitMenuObject(PlayerInput,Scene,ScreenWidth,ScreenHeight,bIsFirstInitialization);

  List有自己的OnChange代理

8.Combo也需要在实例中初始化

  下来是一个实例运用,他初始化了两个Combo,一个是Object,一个是Item。选定一种将会在表单中显示List中的变量,这其实提供了两个方向,一个是list的生成,一个是Label的接口

  Items序列来添加每个内容,同样Image也可体用类似的方式添加。

  在初始化表单的时候有一些工作

 

9 总结:

  使用的是AntMobileMenuButton,以下是按钮初始化的内容

 Begin Object class=UDNMobileMenuButton name=CancelButton
      Tag="Cancel"
      Width=64
      Height=32
      Caption="Cancel"
      TextFont=Font'EngineFonts.SmallFont'
      CaptionColors(0)=(r=1.0,g=1.0,b=1.0,a=1.0)
      CaptionColors(1)=(r=0.0,g=0.0,b=0.0,a=1.0)
      Images(0)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
      Images(1)=Texture2D'UDNExampleUI.Menus.T_MenuUI'
      ImagesUVs(0)=(bCustomCoords=true,U=0,V=896,UL=256,VL=128)
      ImagesUVs(1)=(bCustomCoords=true,U=0,V=896,UL=256,VL=128)
   End Object
   Cancel=CancelButton

  列表初始化的过程AntMobileMenuList,以下是列表初始化示例:

Begin Object class=UDNMobileMenuList name=List0
      Tag="Combo_ItemsList"
   End Object
   List=List0

  在列表栏中一个变量

 1. var instanced AntMobileMenuList list;

  然后在初始化InitMenuObject中添加列表,我制作一个武器栏列表,里面有各种武器的图片以及参数。

  继承AntMobileMenuList开辟一个AntWeaponShopMenu和AntWeaponItemMenu;

     在他们的InitMenuObject中foreach List补充图片和文字信息。

  var array<AntWeapon> CurrentWeapn;

  foreach AntWeapon(CurrentWeapon)

    {

             List.AddItem(CurrentWeapon);
    }

 2. 在AntMobileMenuList中实现AddItem函数

var instanced array<UDNMobileMenuButton> Items;

  function AddItem(AntWeapon Item)

{

  local AntMobileButton NewItem;

     NewItem.Caption=Item.caption;

   NewItem.Image=Item.Caption;

  Items.AddItem(NewItem);
}

  事已至此,概念上的东西讲完了。我该let's make our hands dirty!