FairyGUI个人学习手册——只有重点(2)

3D内容装载器

动态载入骨骼动画的,用的少,略。

文本

实例属性

在这里插入图片描述
文本为单行,不会自动换行,就算有换行符也被忽略。
字体大小:如果使用位图字体,要先设置“允许动态改变字号”。
颜色:位图字体同上,“~~~~颜色”。
自动大小:

  • 自动宽度和高度:文本不自动换行,宽度和高度都增长到容纳全部文本。
  • 自动高度:到达宽度后自动换行,高度增长到容纳全部文本。
  • 自动收缩:到达固定宽度后自动缩小,让所有文本全部显示。
  • 显示省略号:文本使用固定宽度和高度排版,如果文本超出范围,在剪裁文本的同时在末尾显示省略号。
  • 无:文本使用固定宽和高,不自动换行。
    描边:文本的描边效果,数值不能过大,否则会比较奇怪。编辑器效果仅供参考。
    投影:简化的描边效果,描边是所有方向,投影只有一个方向。两者共用一个颜色设置。

文本模板

在编辑器中放置一个文本控件,比如文本为“金钱:{jin=100}金{yin=200}银”,然后勾选“使用文本模板”就好。这样编辑器显示“”“金钱:100金200银”,可以通过以下代码动态更新数值

 aTextField.SetVar("jin", "500").SetVar("yin", "500").FlushVars();

也可批量设置:

   Dictionary<string, string> values;
    values["jin"] = "500";
    values["yin"] = "500";
    //注意,这种方式不需要再调用FlushVars
    aTextField.templateVars = values

启用文本模板功能,不用设置开关,直接调用SetVar,想要关闭文本模板的时候:

aTextField.templateVars = null;

富文本

和普通文本的区别:

  • 富文本支持交互
  • 富文本支持连接和图文混排
  • 富文本支持HTML语法。

输入文本

实例属性

详细设置:

  • 最大长度:输入最大字符数。
  • 密码:勾选后输入字符将显示成*。
  • 输入限制:限制用户输入字符,在Unity上参考正则表达式语法。例如限制只能输入数字的表达式是:“[0-9]”。
  • 键盘类型:
  • 提示文字:

字体

系统字体

当前系统中安装的字体,需要注意:
1.本机存在的字体其他电脑上未必有,效果预期会不一样。
2.编辑器和游戏引擎可能无法设别部分字体的名字。

TTF字体

将字体文件拖入编辑器,成为字体资源,后缀名为ttf/ttc/otf的文件。无论字体是否设置未导出,它都不会被发布。UI包发布后,引用此字体的文本元件字体名称是该字体的资源名字。比如:一个文本元件,字体设置为B包的a资源,发布后,它的字体就是a,而不是ui://B/a。
使用者需要手动把字体放到游戏引擎里面去,建立字体映射。
Unity的话就放在Resources文件夹或者打AB包,具体操作如下:

  //如果afont是放在Resources的子目录下
  FontManager.RegisterFont(new DynamicFont("afont",
   Resources.Load("path/to/font"));

  //如果afont打成了AB
  DynamicFont font = new DynamicFont();
  font.name = "afont";
  font.nativeFont = fontLoadFromAB;
  FontManager.RegisterFont(font);

TTF字体资源的属性窗口,有以下内容需要注意:
系列:字体名称,只读。
采样字体大小:渲染方式“SDFAA”才有意义,其他默认16。
渲染方式:

  • Smooth 抗锯齿字体渲染。
  • Hinted Smooth 带有微调的抗锯齿字体渲染。
  • SDFAA 使用SDF技术渲染文字。
    斜体样式:渲染SDFAA时才显示,斜体时文字倾斜角度。有效值15-60。
    粗体分量:同上,用粗体的量。有效值-3-3。

位图字体

位图设置界面介绍:

  • 图片:略
  • 字符:略
  • 偏移X:水平方向上该字符的偏移,负数左,正数右。
  • 偏移Y:垂直方向上该字符的偏移,负数上,正数下,因为文字排版基线对齐,可能整行都发生下移。
  • 占位:一般来说,字符的水平占位宽度就是图片的宽度决定。如果不是0,设置好多就是好多。
  • 字体大小:字体字号,勾允许动态改变字号才有效。
  • 默认占位:统一设置所有字符占位。
  • 允许动态改变字号:略。
  • 允许动态改变颜色:略。
  • 纹理集:如果是BMFont导入,字符图片都在一张贴图上,这里对应贴图资源。

全局字体

设置好后,文本元件的字体属性留空的,默认使用该字体。
运行时设置:

    //Droid Sans Fallback是安卓上支持中文的默认字体
    UIConfig.defaultFont = 'Droid Sans Fallback'; 

TextMeshPro支持

Untiy中的TextMeshPro,它用的SDF渲染文字,实际使用中特点体现在可无限放大并保持清晰,几乎没有开销就可实现描边,发光,抗锯齿。FGUI内置支持使用TextMeshPro插件。
步骤如下:
1.导入ttf/ttc/otf文件。
2.设置字体为SDFAA,字体大小根据项目需求来定,越大渲染效果越好,一张贴图容纳的文字越少。一般30-90。
3.给文本设置字体。
设置好了文本中的属性栏会变化。
Unity中的设置:
1.安装了TextMeshPro。
2.在Unity的Scripting Define Symbols里增加FAIRYGUI_TMPRO。
3.ttf文件拖进去。
4.ttf文件创建一个TextMeshPro FontAsset。通常创建出来的Asset名字为“XXX SDF”,把名字改成XXX,和FGUI里面资源同名。
5.配置这个资源的Sampling Point Size与FGUI里面采样字体一致。
编辑器的显示效果和Unity里完全一致,不一致就是参数不对。
AB包载入

 //假设fontAsset已经从ab载入
  TMP_FontAsset fontAsset;
  TMPFont font = new TMPFont();
  font.name = 'afont'; //这个名字要和编辑器里字体资源的名字一致
  font.fontAsset = fontAsset;
  FontManager.RegisterFont(font);

绑定多个元件。

普通组

编辑时有效辅助设计,打包发布后就不在了,运行时无法访问。
作用:整体移动,整体深度调整,整体复制粘贴,组内部随意调整各个元件深度,组大小改变时组员同时变化。

高级组

具有普通组的所有功能,且发布后仍然保留,运行时也可以访问。
其作用为:
1.可以设置可见性。
2.设置属性控制。支持:显示控制,位置控制,大小控制。
3.设置关联。
4.设置布局。
重点说一下属性面板中的布局

  • 无:没有布局。没有布局的高级组是不会自动计算包围的,为了提高运行性能,没有布局的一般只用来做显隐用途。
  • 水平布局:组内的元件按照他们在容器中的显示顺序水平依次排列,他们之间的间隔由列距指定。当组的宽度改变时,每个元件都按比例增大,然后重新排列,列距保持不变。当组内的元件自身的宽度改变时,组自动按规则重新排列。
  • 垂直布局:组件的元件按照他们在容器中的显示顺序垂直依次排列,他们之间的间隔由行距指定。当组的高度改变时,每个元件都按比例增大,然后重新排列,行距保持不变。当组内的元件自身的高度改变时,组自动按规则重新排列。

排除隐藏的对象:勾选之后,隐藏对象不会参与排列。
禁用自动计算包围:一般高级组的范围是自动计算包围的,高级组大小由组内元件决定。勾了可以自由指定大小,不受组内元件影响。使用实例:动态创建高级组,设定大小,无论往组里添加多少元件,这些元件都会自动伸缩且严格按布局排列。
仅伸缩指定索引元件:高级组中所有元件均匀拉伸。可以指定只有一个元件变化,其他不变。这里可以指定一个元件的索引实现需求。

组件

组件是FairyGUI中的一个基础容器。可以包含多个基础显示对象,也可包组件

组件属性

尺寸:宽和高。
最小/最大尺寸:尺寸限制。修改此处不会修改当前宽高,即使超出。
轴心:旋转、缩放、倾斜变换的轴心点。
同时作为锚点:略。
初始名字:在编辑器中被实例化时,自动设置组件的名称就是用这个名字。
溢出处理:超出组件区域外的内容处理。不能动态修改。

  • 可见:超出部分依然可见。
  • 隐藏:超出部分不可见,相当于用了一个遮罩。
  • 垂直滚动/水平滚动/自由滚动:FGUI中任何普通组件,设置了滚动功能就可以实现滚动。
    边缘:设定组件四周的留空。一般用在“隐藏”和“滚动”。边缘虚化只能在Unity用。
    自定义遮罩:略。
    。。。。

其他属性

自定义属性:组件被拖到其他组件中去,检查器上能设置的属性一般是固定的。例如一个按钮,我们可以改变它的标题、图标、是否选中等,这些都是编辑器提供的固定属性。但如果我在按钮中放置了额外的文本或者装载器,而且需要设定他们在实例化后的属性时,就需要用自定义属性,将组件的子元件甚至更深层次的元件的属性暴露出来。
在自定义属性旁点击编辑弹出窗口。

  • 元件名称:元件的名称,可以用.来向下层级移动。
  • 属性类型:目前支持两种:文本和图标。
  • 备注:略。
    拖进其他组件就可以看到其他组件上出现自定义的属性了。仅限编辑器,运行时GetChild就可以。
    自定义数据,FGUI不做解析,按原样发布,运行时可以获取:
 aComponent.baseUserData;

设计图功能

设定一个组件设计图,设计图显示在舞台上,可以设置显示在组件内容的底层或者上层。不会发布到包中。

点击穿透

越前面的元件先被点到,所以多个组件重叠,勾选这个之后前面的组件空白处也就是没有元件的地方可以被穿透,点击事件可以打到下一层的。
需要注意的是:图片和普通文本是不能被点击,如果一个只含图片和文本的组件设置了点击穿透,那整个组件就是完全穿透了。

点击测试

需要用到不规则区域点击测试。

  • 组件内拖一个图形,选多边形,然后用其勾画出不规则区域形状,最后点击测试属性里面选这个图形元件。
  • 如果不规则形状带洞,那就用像素检测。
    首先准备一张包含不规则区域的图片,该图中不透明的像素代表接受点击的区域,透明是穿透的区域。
    需要注意:用于像素检测的这张图只能和组件放同一个包,不用用装载器。

遮罩

矩形遮罩:组件溢出处理设为隐藏或滚动,就成了。超出组件的区域都不可见,效率最高。
自定义遮罩:设置组件中图片或图形为遮罩,一般用的模板测试技术。图形就内力可见,外面不可。图片就透明可见,不透明不可见。
注意:Unity对用了自定义遮罩的组件进行设置时,需要额外设置。
反向遮罩:就和普通遮罩相反。

扩展

可以将组件扩展成一个编辑器中存在的的组件,只要选好之后就可以拥有该扩展的属性和行为特性。FairyGUI中的扩展是以名称约定。比如一个按钮,可以带标题和图标,也就是文本和装载器,我们放到组件中之后要把他们的名字设置为title和icon(保证名字一定为这两个)。
将这个制作好的组件放入另一个组件中,就会发现其具有按钮的属性,并且设置标题和图标时会自动显示在按钮上的对应元件上。
扩展赋予了组件行为,在按钮上就是处理鼠标或触摸事件,按下时改变状态等等。这部分还是通过“名称约定”来工作。

渲染顺序

渲染顺序就是在同一个父元件下安排的顺序,越大越往后渲染,显示在前面。FGUI中也可以使用sortingOrder,不过少用效率差。

滚动容器

滚动条显示:

  • 默认:使用全局设置,编辑器在主菜单“文件->项目属性->预览设置”里设置,运行时用UIConfig.defaultScrollBarDisplay设置。
  • 可见:滚动条一直显示。
  • 滚动时显示:表示滚动条只有在滚动时才会显示。
  • 隐藏:一直不可见。
    边缘回弹效果:字面意思。
    触摸滚动效果:字面意思。
    滚动条组件:设置滚动条资源。一般不需要设置,全局有一个设置,在主菜单“文件->项目属性->默认值”里。如果你要使用不同于全局设置的滚动条资源,那么在这里设置。
    定位:
    下拉/上拉刷新组件:设置上拉刷新或下拉刷新时需要显示的组件。
    将垂直滚动条显示在左边:
    仅在内容溢出时才显示滚动条:字面意思,不过这个和上面的“隐藏”不一样,这个占位都没得。
    滚动位置自动贴近元件:滚动结束后,保证滚动位置刚好处于任意元件的上边缘(或左边缘)。
    页面模式:以视口大小为页面大小,每次滚动的距离是一页。一般在移动平台上使用,PC上较少,拖动滚动条进行滚动操作与这个模式冲突
    禁用惯性:
    禁用剪裁:
    禁用裁剪边缘:
    浮动显示:勾了滚动条不占据视口位置,而是直接覆盖在视口上。

控制器

基本作用:分页,按钮状态,属性变化。

控制器设计

控制器动作

属性控制

显示控制:这个元件只有在控制器的该页面才显示。可以实现两个控制器控制一个元件显示,可以选择“与”“或”关系。
需要注意的时:
1.显示控制不适用元件本身的可见属性,两者独立,是否可见是“与”逻辑结果。
2.当元件不可见时,不会被容器的显示列表剔除,但FairyGUI底层会处理,使其不占用渲染资源。不受控制器干扰的显示列表保证了任何时候都可以通过GetChild访问到需要的元件。
3.屏蔽显示控制器。
位置控制:元件不同页面中具有不同坐标。可以支持动画效果。位置控制和关联系统的关系——关联系统中的动作都会应用到所有页面保存的坐标中。
大小控制:该元件在不同页面中具有不同的宽和高和Scale值。
颜色控制:该元件在不同控制器页面中具有不同的颜色。
外观控制:该元件在不同控制器页面具有不同的透明度、变灰、旋转和不可触摸属性。
文本控制:该元件在不同控制器页面具有不同文本。
图标控制: ~~~~不同图标。
动画控制: ~~~~不同的动画相关设置。
字体大小控制:~~~~不同字体大小。

和按钮的联动

按钮可以跟控制器进行连接:

  • 普通按钮:点击跳转指定页面。
  • 单选按钮:切换到指定页面,按钮选中,反之则不选中。
    这个特性用来实现单选组,主要思路就是然三个单选按钮分别链接控制器的三个页面。程序中,获取或设置按钮选中,用控制器的selectedIndex或selectedPage就可。
  • 复选按钮:

和列表的联动

当列表发生改变,控制器跳转相同索引页面。

和分页滚动的联动

滚动发生翻页时,控制器跳转。

和下拉框的联动

下拉框选择变化,控制器页面跳转。

关联系统

自动布局的核心,不仅可以定义元件和容器之间的关系,还可以定义两个元件之间的关系。

设置关联

具体看官方吧,只能意会。

Relation

动态添加关联。

//组件设置右—>右的关联
aObject.AddRelation(GRoot.inst, RelationType.Right_Right);
//组件设置满屏大小
aObject.SetSize(GRoot.inst.width, GRoot.inst.height);
aObject.AddRelation(GRoot.inst, RelationType.Size);
//删除指定关联和所有管理
aObject.RemoveRelation(targetObject, RelationType.Size);
aObject.relations.ClearFor(targetObject);

注意下组件变为满屏大小需要自己完成,也就是SetSize,关联不能完成这个任务,关联不管元件当前大小,只管目标变化时保持两者大小差别。

按钮

列表

列表属性

列表布局:

  • 单列:每行一个item,竖向排列
  • 单行:每列一个item,横向排列
  • 横向流动:item横向依次排列,到底视口右侧边缘或到达指定的列数,自动换行继续排列。
  • 竖向流动:item竖向依次排列,到底视口底部边缘或到达指定的行数,返回顶部开启新的一列继续排列。
  • 分页:视口宽度x视口高度作为单页大小,横向排列各个页面。每页中,item横向依次排列,到底视口右侧边缘或到达指定的列数,自动换行继续排列。当新的一行超出视口高度或到达指定的行数,则进入下一页。注意,分页只是列表的排列方式,不代表列表就是按页滚动。分页滚动需要在滚动属性里设置。

一些API

GTextField

动态创建:

 GTextField aTextField = new GTextField(); //LayaAir平台用new GBasicTextField
    aTextField.SetSize(100,100);
    aTextField.text = "Hello World";

动态改变文本样式:

 TextFormat tf = aTextField.textFormat;
    tf.color = ...;
    tf.size = ...;
    tf.font = ...;
    aTextField.textFormat = tf; //或者 aTextField.ApplyFormat();

GRichTexField

富文本支持动态创建:

GRichTextField aRichTextField = new GRichTextField();
    aRichTextField.SetSize(100,100);
    aRichTextField.text = "<a href='xxx'>Hello World</a>";

监听富文本中链接点击(这个事件是冒泡的,在它的父元件或者更高一级父级都可以监听):

  aRichTextField.onClickLink.Add(onClickLink);

GTextInput

输入文本在文本改变时有通知事件:

aTextInput.onChanged.Add(onChanged);

在获得焦点和失去焦点时的通知事件:

    aTextInput.onFocusIn.Add(onFocusIn);
    aTextInput.onFocusOut.Add(onFocusOut);

主动设置焦点:

aTextInput.RequestFocus();

GGroup

组不是容器,没有把组内元件存入的列表,所以当你需要遍历组内元件时,你需要遍历容器组件的所有子元件,测试他们的group属性:

   GGroup aGroup = gcom.GetChild("groupName").asGroup;
    int cnt = gcom.numChildren;
    for(int i=0;i<cnt;i++)
    {
        if(gcom.GetChildAt(i).group==aGroup)
            Debug.Log("get result");
    }

没有布局的高级组不会自动计算包围大小,运行时也就不会自动改变大小,无论组内元素怎么变动,组的大小都不变,非要改用GGroup.EnsureBoundsCorrect。

GComponent

动态创建:

    GComponent gcom = new GComponent();
    gcom.SetSize(100,100);
    GRoot.inst.AddChild(gcom);

动态创建的组件是空组件,可以作为其他组件的容器。动态创建的组件默认是点击穿透的。

    //设置组件点击不穿透。
    gcom.opaque = true;

创建UI库中组件:

    GComponent gcom = UIPackage.CreateObject("包名","组件名").asCom;
    GRoot.inst.AddChild(gcom);

显示列表是一个树状的结构组织。

.numChildren //容器中子物体树
.AddChild/AddChildAt//添加元件,前者加到队尾,后者指定位置。
.RemoveChild/RemoveChildAt/RemoveChildren//删除元件,记得删除后并不会销毁还是需要人为手动销毁。
.GetChild/GetChildAt //获取元件引用
.GetChildIndex //获得元件索引
.SetChildIndex //设置索引

可以绑定一个类为组件的扩展类。先编写一个扩展类:

  public class MyComponent : GComponent
    {
        GObject msgObj;

        //如果你有需要访问容器内容的初始化工作,必须在这个方法里,而不是在构造函数里。各个SDK的函数原型的参数可能略有差别,请以代码提示为准。在Cocos2dx/CocosCreator里,方法的名字是onConstruct,且不带参数
        override protected void ConstructFromXML(XML xml)
        {
            base.ConstructFromXML(xml);
            
            //在这里继续你的初始化
            msgObj = GetChild("msg");
        }

        public void ShowMessage(string msg)
        {
            msgObj.text = msg;
        }
    }

随后注册扩展类,注意,必须在组件构建前注册,通常就是在Awake中。如果注册不成功,很大可能就是注册晚于创建,小可能是URL错误,可以打印URL排查。

 UIObjectFactory.SetPackageItemExtension("ui://包名/组件A”, typeof(MyComponent));

这样组件就绑定了一个实现类。以后所有组件A创建出来的对象都是该类型的了,还可以为该类型调价API。

    MyComponent gcom = (MyComponent)UIPackage.CreateObject(“包名“, ”组件A”);
    gcom.ShowMessage("Hello world");

如果组件A只是普通组件,没有定义“扩展”,那么积累就是GComponent。

ScrollPane

    ScrollPane scrollPane =  aComponent.scrollPane;
    //设置滚动位置为100像素
    scrollPane.posX = 100;

    //滚动到中间位置,带动画过程
    scrollPane.SetPercX(0.5f, true);

当你增删子组件,移动子组件位置或调整子组件大小,容器是会自动更新滚动区域的,不用调任何API。该刷新发生在本帧绘制之前。立刻访问子元件正确坐标,调用EnsureBoundsCorrect让GComponent立刻重排。且重复调用不会有额外性能消耗。
常用API:

viewWidth/viewHeight //视图宽高
contentWidth/contentHeight //内容宽高
percX/percY/SetPercX/SetPercY //获取或设置滚动位置,0-1
currentPageX/currentPageY/setCurrentPageX/setCurrentPageY //页面模式时,设置或获取页面索引
ScrollLeft/ScrollRight/ScrollUp/ScrollDown //向指定方向滚动N*scrollStep
ScrollToView //调整滚动位置,让指定元件出现在视口内。
touchEffect//开关触摸滚动。
scrollStep //
bounceBackEffect //开关回弹
mouseWheelEnabled //开关鼠标滚动
ecelerationRate //减速
CancelDragging //当滚动面板处于拖拽滚动状态或即将进入拖拽状态时,可以调用此方法停止或禁止本次拖拽。

监听滚动改变时的事件:

scrollPane.onScroll.Add(onScroll);
scrollPane.onScrollEnd.Add(onScrollEnd);
scrollPane.onPullDownRelease.Add(onPullDownRelease);
scrollPane.onPullUpRelease.Add(onPullUpRelease);

Controller

 Controller c1 = aComponent.GetController("c1");
    //通过索引设置控制器的活动页面
    c1.selectedIndex = 1;
    //如果希望改变控制器时不触发Change事件
    c1.setSelectedIndex(1);
    //也可以使用页面的名称设置
    c1.selectedPage = "page_name";
    //获得控制器当前的活动页面
    Debug.Log(c1.selectedIndex);
    //改变时通知事件
     c1.onChanged.Add(onChanged); 
     //改变页面,链接的属性控制带有缓动,获得缓动结束
     aObject.OnGearStop.Add(OnGearStop);
    //禁止所有控制器引起的缓动
    GearBase.disableAllTweenEffect = true; 
    c1.selectedIndex = 1;
    //记住要复原
    GearBase.disableAllTweenEffect = false;
    //以下操作非必要
    button.relatedcontroller = aController;
    button.relatedPageId = aController.GetPageId(1);
    //GearXXX对象是控制器和属性之间的连接。0-显示控制,1-位置控制,2-大小控制,
    // 3-外观控制,4-颜色控制,5-动画控制,6-文字控制,7-图标控制
    GearDisplay gearDisplay = obj.GetGear(0);
    gearDisplay.controller = obj.parent.GetController("c1");
    //注意这里是页面的id,不是索引或者名称。可以通过Controller.GetPageIdByName转换。
    gearDisplay.pages = new string[] { ... }; 
    GearXY gearXY = obj.GetGear(1);
    gearXY.tweenConfig.duration = 0.5f;

GButton

设置带标题或者图标的按钮,甚至都不用强制对象为GButton类型,用GObject就行。

    GObject obj = gcom.GetChild("n1");
    obj.text = "hello";
    obj.icon = "ui://包名/图片名";

模拟出发点击

    //模拟触发点击,只会有一个触发的表现,以及改变按钮状态,不会触发侦听按钮的点击事件。
    button.FireClick(true);
    //如果同时要触发点击事件,需要额外调用:(仅Unity/Cry示例,其他平台自己研究)
    button.onClick.Call();

GComboBox

动态设置下拉列表项目:

    GComboBox combo = gcom.GetChild("n1").asComboBox;
    //items是列表项目标题的数组。
    combo.items = new string[] { "Item 1", "Item 2", ...};
    //values是可选的,代表每个列表项目的value。
    combo.values = new string[] { "value1", "value2", ...};
    //获得当前选中项的索引
    Debug.Log(combo.selectedIndex);
    //获得当前选中项的value。
    Debug.Log(combo.value);
    //设置选中项,通过索引
    combo.selectedIndex = 1;
    //设置选中项,通过value
    combo.value = "value1";
    //下拉框选择改变时的事件
    combo.onChanged.Add(onChanged);
    //点击空白处弹出框自动关闭,获取这个关闭通知
    combo.dropdown.onRemoveFromStage.Add(onPopupClosed);
    //手动关弹出框
    GRoot.inst.HidePopup();

GList

管理列表内容

GList是GComponent派生类的,列表增删改之后自动排列和刷新。不要自行设置item的位置,也不要设置sortingOrder去控制item深度。除了,垂直布局指挥自动设置item的y坐标,如果要item有一个水平位移效果,可以去改item的x。水平同理。
这个排列和刷新发生在本帧绘制之前,如果需要立刻访问item的正确坐标,那么可以调用EnsureBoundsCorrect通知GList立刻重排。

实际应用中,列表的内容会被频繁更新。性能消耗大,所以GList内建有对象池。使用对象池后显示列表管理方法:

  • AddItemFromPool:从池中取出或新建一个对象,添加进列表。不用参数,就用列表的“项目资源”设置;也可以指定一个URL,创建指定的对象。
  • GetFromPool:取出或者新建对象。
  • ReturnToPool:将对象返回池中。
  • RemoveChildToPool:删除一个item,并返回对象池中。
  • RemoveChildToPoolAt:删除一个指定位置的item,并将对象返回池里。
  • RemoveChildrenToPool:删除一个范围内的item,或者全部删除,并将删除的对象都返回池里。

AddItemFromPool = GetFromPool +AddChild,RemoveChildToPool = RemoveChild + ReturnToPool。
注意使用对象池的时候从哪儿拿的就放回那儿去,不要只拿不放或者是放不拿。否则容易造成内存溢出或者内存泄漏。
溢出和销毁时两回事,当你吧item从里列表移除时,如果以后不再使用,那就销毁。如果还要用,就保存其引用。如果放入池中,就别再销毁item。

使用回调函数修改列表

当添加大量item时,除了使用循环方式AddChile或AddItemFromPool外,还可以使用一种回调方式。步骤如下:声明一个回调函数:

    void RenderListItem(int index, GObject obj)
    {
        GButton button = obj.asButton;
        button.title = ""+index;
    }

设置这个函数为列表渲染函数:

 aList.itemRenderer = RenderListItem;

最后设置项目总数,这样列表就会调整当前里列表容器的对象数量,然后调用回调函数渲染item。

   //创建100个对象,注意这里不能使用numChildren,numChildren是只读的。
    aList.numItems = 100;

如果新设置的对象小于当前的对象,那多出来的item就放回池中。这样生成的列表,当你需要更新某个item,自行调用RenderListitem就可以了。

列表自动大小

GList提供ResizenToFit,在填充完列表数据后调用,列表大小就会修改到合适大小,容纳指定的item数量。如果不指定,则扩展到显示所有item。
点击item触发事件:

ist.onClickItem.Add(onClickItem);

虚拟列表*

当列表item数量特别多时,每一条项目创建实体很耗时间。FGUI内置虚拟机制,只为显示范围内的item创建实体对象,并通过动态设置数据的方式实现大容量列表。
启用虚拟列表条件:

  • 定义itemRenderer
  • 开启滚动。
  • 设置好列表“项目资源”。可以编辑器设置,可以GList.defaultitem设置。
    完成之后aList.SetVirtual();开启虚拟功能,只能开不能关
    虚拟列表性能和itemRenderer中的逻辑相关,尽量简化。不要在里面new东西。在该列表中,Item时复用的,当一个item需要刷新时,itemRenderer就会被调,所以在itemRenderer使用Add添加事件监听,不要用临时函数:
 void EventCallback()
    {
    }
    EventCallback0 callback = EventCallback;
    void OnRenderItem(int index, GObject obj)
    {
        GButton btn = obj.asCom.GetChild("btn").asButton;
        //错误!,临时函数会造成添加多次回调。Lua里使用“function() end”类似。
        btn.onClick.Add(()=> { });
        //可以,同一个方法只会添加一次。但直接使用方法名会生成几十B的GC。
        btn.onClick.Add(EventCallback);
        //正确,callback是缓存的代理实例,不会产生GC。
        btn.onClick.Add(callback);
        //正确,使用Set设置可以保证不会重复添加。
        btn.onClick.Set(callback);
        //错误!,不能对ITEM使用onClick.Set,你需要用GList.onClickItem
        obj.onClick.Set(EventCallback);
    }

在虚拟列表中,item索引和像是对象索引是不同的:

    //转换项目索引为显示对象索引。
    int childIndex = aList.ItemIndexToChildIndex(1)
    //转换显示对象索引为项目索引。
    int itemIndex = aList.ChildIndexToItemIndex(1);

如果需要访问屏外对象。先将列表滚动到目标位置,再获取显示对象的索引。

    //这里要注意,因为我们要立即访问新滚动位置的对象,所以第二个参数scrollItToView不能为true,即不使用动画效果
    aList.ScrollToView(500)//转换到显示对象索引
    int index = aList.ItemIndexToChildIndex(500);
    //这就是你要的第500个对象
    GObject obj = aList.GetChildAt(index);

虚拟列表的本质是数据和渲染分离,需要删除或修改列表时,先修改数据再刷新列表。
刷新虚拟列表的方式有两种:

  • 使用numItems重新设置数量。
  • GList.RefreshVirtualList。
    不允许用用Add和Remove来增删。清空列表就是numItems=0。
    虚拟列表支持可变大小的item:
  • 在itemRenderer的内部使用width、height或SetSize改变item的大小。
  • item建立对内部元件的关联,然后在itemRenderer里修改内容触发内部元件的改变,从而自动改变item高度。例如item建立了一个对内部某个可变高度文本的高高关联,这样当文本改变时,item的高度自动改变。
    除此之外的方式不要用来改变item大小,否则排列错乱。

循环列表

必须时虚拟列表,aList.SetVirtualAndLoop()。文章来源地址https://uudwc.com/A/8paB

原文地址:https://blog.csdn.net/qq_43685296/article/details/127728683

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月13日 01:34
下一篇 2023年06月13日 01:34