
这是本教程的第2部分,显示了在Appcelerator / Axway Titanium中如何动态设置文本块的尺寸以及如何处理复合视图的延迟渲染的几种技术。 在本教程的第1部分中,我们研究了使用“ postlayout”事件计算出文本的行高后,动态调整文本块的大小。 该应用程序示例是ScrollView中的图块列表,其中包括图像和文本块。 在本部分的教程中,我们将研究如何延迟所有图块的渲染,然后在加载并渲染所有图块之后在ScrollView上平滑淡入淡出。
本文假定您具有如何使用钛和合金的基本知识。 该示例项目是使用OS X 10.12.6(带有XCode 8.3.3)上的Ti SDK 6.2.2开发的,并在iOS 10.3和Android 4和6上进行了测试。
在此提醒您,此示例显示了屏幕的外观:

如果图像是远程的,并且文本(甚至图像的位置)是通过例如REST接口作为远程数据提供的,则在加载数据时会有延迟。 如果在加载数据之前渲染ScrollView,我们将有很多空白。 即使我们选择预加载数据,但如果要渲染的瓦片很多,由于图形开销,渲染的时间也会有所延迟。 请记住,我们选择了一个非常简单的示例,但在现实世界中,图块的布局可能要比这复杂得多(例如,标题,日期,图标以及其他人知道什么,以及图片和文字摘要)。 一种可能的方法是渲染带有其文本的图块,然后让图像逐一加载(有时开发人员在每个图像上使用加载微调器,尽管我不赞成这种方法,因为当有图像时屏幕变得太忙了)加载多个图像)。 我们选择先加载并渲染ScrollView中的所有图块,然后再逐渐将其淡入淡出,从而创建一个平滑,无缝的过渡。
我不会实际编程REST接口并远程下载数据,因为这不是本教程的重点,因此将模拟超时的数据加载延迟。 我们还将向我们的itemTile.js控制器添加一个回调,以便可以在加载完成时通知父视图。
itemTile.xml:
//我们使用填充框在图片和文字周围创建边距或填充
itemTile.js:
var onRenderedCallback = $ .args.onRenderedCallback,
textLoaded = false,
imageLoaded = false;
//选择一个范围内的随机超时值进行模拟
//更改文本和图像的加载时间
var timeout1Duration = 1000 *(1 + Math.random()* 3);
var timeout2Duration = 1000 *(1 + Math.random()* 1);
setTimeout(function(){
$ .imageView.image = $ .args.imagePath
'';
imageLoaded = true;
如果(textLoaded && onRenderedCallback){
onRenderedCallback();
}
},timeout1Duration);
setTimeout(function(){
$ .textLabel.text = $ .args.text
'';
textLoaded = true;
如果(imageLoaded && onRenderedCallback){
onRenderedCallback();
}
},timeout2Duration);
.....等等
我们正在模拟一种竞争状态,其中要加载多个数据,而我们不知道哪个数据会先完成。 这在异步Web调用中很典型。 在这个简单的示例中,文本加载的速度很可能比图像要快,但是在更复杂的示例中,我们可能拥有各种各样的数据,甚至可能加载的图像不止一个。 因此,从上面的代码中我们可以看到,只有在两个数据都加载后才调用“ onRenderedCallback ”回调。 调用此函数后,我们可以在父视图中更新ScrollView。 另外,我们添加了一个加载微调器(ActivityIndicator)来覆盖图块的加载和渲染,并将ScrollView的不透明度设置为0,准备淡入。
example.xml:
<ActivityIndicator id =“ activityIndicator” message =“正在加载…” /
example.js: var Animation = require('alloy / animation'),
numberOfTilesRendered = 0,
FADE_DURATION = 500;
函数onRenderedCallback(){
numberOfTilesRendered ++;
如果(numberOfTilesRendered === items.length){
fadeScrollViewOn();
$ .activityIndicator.hide();
}
}
函数fadeScrollViewOn(){
Animation.fadeIn($。scrollView,FADE_DURATION,function(){
$ .scrollView.opacity = 1.0;
});
}
.....等等
回想一下“ items”是我们的数据数组,因此在每个图块的回调中,它会检查所有图块是否都已回调,如果是,则隐藏加载微调器(ActivityIndicator),并使用标准Alloy动画包在ScrollView上淡入淡出(请注意,在动画结束时将ScrollView的不透明度设置为1,因为如果在设置动画时不这样做,则属性可能会以意想不到的方式表现出来)。
现在,在实际操作中,对于图像,您将侦听已加载远程图像时触发的“加载”事件。 如:
itemTile.js: $ .imageView.addEventListener('load',function(_evt){
imageLoaded = true;
如果(textLoaded && onRenderedCallback){
onRenderedCallback();
}
});
$ .imageView.image = $ .args.imagePath
'';
最后值得一提的是另一种更先进的技术,它可以使用变量观察器来监视众多比赛条件和数据负载。 变量观察器寻找变量值的变化,并在实现后允许采取行动。 我在库文件variableWatcher.js中使用了Ian Serlin的一些代码。 同样,在像我们这样的简单示例中,使用变量监视程序无法获得任何好处,但是对于同时进行许多异步数据加载的更为复杂的情况,它可能很有用。 在这种情况下,我们的代码是:
itemTile.js var VariableWatcher = require('variableWatcher'),
//“已加载”是我们要关注的对象变量
已加载= {
图片:假,
文字:假
};
函数checkIfReadyToRender(){
如果(loaded.image && loading.text){
VariableWatcher.unwatch(loaded,'image');
VariableWatcher.unwatch(loaded,'text');
如果(onRenderedCallback){
onRenderedCallback();
}
}
}
VariableWatcher.watch(loaded,'image',checkIfReadyToRender);
VariableWatcher.watch(loaded,'text',checkIfReadyToRender);
setTimeout(function(){
$ .imageView.image = $ .args.imagePath
'';
loading.image = true;
},timeout1Duration);
setTimeout(function(){
$ .textLabel.text = $ .args.text
'';
loading.text = true;
},timeout2Duration);
您可以在GitHub上看到完整的项目,并在本教程的第1部分和第2部分中探讨了3种不同技术的示例。
S Simon Buckingham是一位设计师,UX专家,动画师,创意和技术总监以及开发人员,拥有20多年的经验。 他使用Titanium制作跨平台的iOS / Android移动应用程序已有5年以上。 西蒙(Simon) 在英国伦敦 经营自己的公司 Icecandy Entertainment 。 您可以在 simonbuckingham.me上 找到有关他的数字职业的更多信息 。