MarkupGrid是BrightScript里面的一个控件,在电视端这个控件可以起到很大作用。
它是一个通用的网格节点,可用于显示排列到2D网格中的一组项目。每个网格项的内容是itemComponentName字段指定的XML组件的对象,XML组件的对象用于显示网格数据模型中每个项目的数据。利用这个控件我们可以实现网格布局的很多种内容。
MarkupGrid节点中的列数是固定的,行数根据需要而变化,以显示网格数据模型中的所有项目。网格中的项目从左到右填充每一行,然后从上到下填充。例如,如果网格数据包含8个项目并且列数设置为3,则项目1,2和3将位于第一行中。第4,5和6项将在第二行。第三行将在最左边的两列中包含项目7和8,在右列中包含空白空间。
接下来我们使用实现这个布局的方式来了解这个控件。
我们首先要实现的布局长这样:
首先在.xml文件里面创建MarkupGrid:
<MarkupGridid="searchVideoMarkupGrid"/>
然后在brs文件里面对其进行内容的控制
m.searchVideoMarkupGrid = m.top.findNode("SimpleGridItem")
m.searchVideoMarkupGrid.itemComponentName = "SimpleGridItem"
m.searchVideoMarkupGrid.numRows= 3
m.searchVideoMarkupGrid.numColumns = 3
m.searchVideoMarkupGrid.vertFocusAnimationStyle = "fixedFocus"
m.searchVideoMarkupGrid.itemSize = [100 , 100 ]
m.searchVideoMarkupGrid.rowHeights = [120, 120]
m.searchVideoMarkupGrid.itemSpacing = [20, 20]
m.searchVideoMarkupGrid.content = getGridData()
这里的几个参数很好理解。最开始是把m.searchVideoMarkupGrid和刚才定义的控件绑定起来。第二个参数刚才提到过,是列表中每一项的内容。然后的numRows代表我们有3行数据,numColumns代表有3列数据,我们制作的就是一个三行三列的列表。之后的vertFocusAnimationStyle代表列表的存在方式,默认方式为可以无限循环向上下滚动的列表,这里设置的是非无限滚动。下面的几个数据设置则代表了每一项的大小和每一项之间的间隔。最后一句代表绑定内容。这里新建一个方法叫getGridData,在里面进行简单的内容绑定。
function getGridData() as object
data = CreateObject("roSGNode", "ContentNode")
for i = 1 to 11
dataItem = data.CreateChild("SimpleGridItemData")
dataItem.labelText = "Grid item" + stri(i)
end for
return data
end function
这里我们看到首先定义方法,然后就有一个CreateObject方法和两个参数,这个方法代表新建一个对象,对象类型就是contentNode类型的,新建这个对象的方法就是用的roSGNode,代表我们可以调用所有roSGNode的方法对这个对象进行操作。然后是一个for循环,循环中给data添加了六个子类对象,子对象都是SimpleGridItemData类型的。每个SimpleGridItemData类型的子对象里面都有个labelText。因此,这里我们创建一个SimpleGridItemData类。
新建一个xml文件,并且命名为SimpleGridItemData。
<?xml version="1.0" encoding="utf-8" ?>
<component name="SimpleGridItemData" extends="ContentNode">
<interface>
<field id="labelText" type="string" />
</interface>
</component>
这个文件内容很简单,就是调用接口新建了一个叫labelText的属性。,也就是说刚才的代码里面,每一个dataItem都是属于这个类型的,不同之处在于每一个dataItem的labelText不同。
然后再回到
m.searchVideoMarkupGrid.itemComponentName = "SimpleGridItem"
这段代码。这段代码的意思是MarkupGrid中的每一项都是SimpleGridItem格式的子项。因此我们再新建一个xml,命名为SimpleGridItem
<?xml version="1.0" encoding="utf-8" ?>
<component name="SimpleGridItem" extends="Group">
<interface>
<field id="itemContent" type="node" onChange="itemContentChanged"/>
</interface>
<children>
<LayoutGroup>
<Label id="itemText"/>
</LayoutGroup>
</children>
</component>
可以看到这里面定义了一个Label,然后给了个属性叫itemContent,这个属性是MarkupGrid内部的自带属性,因此可以直接给它一个监听的方法itemContentChanged。
接下来在这个item对应的brs文件中加入
function itemContentChanged()
itemData = m.top.itemContent
m.itemText.text = itemData.labelText
end function
function init()
m.itemText = m.top.findNode("itemText")
end function
init是主方法,itemContentChanged就是当前面那个itemContent发生变化的时候,这个方法就会调用,把itemContent的labelText放到上面的label里面。然后回到上面的逻辑。
m.searchVideoMarkupGrid.content = getGridData()
在这段代码里面content内容发生了变化,因此MarkupGrid的内部属性itemContent发生变化,调用了它的方法itemContentChanged,然后就把内容放到了定义的label里面。而data里面有11个数据,因此会出现有11项的一个列表。那么刚才不是说三行三列吗?这个三行三列代表最高可见行列数。首先列表是纵向排列,因此三列是固定的,而最多在屏幕上会显示出三行。如果一行高度太高就不会一页显示三行了。这时候一个三行三列的列表就显示出来了,下面还有有两个多出来的部分。
其实这里可以直接手动写入SimpleGridItemData的数据而不用新建xml去增加内容和工作量。只是为了动态绑定数据还是这样分开更轻松。
未完待续。