AppCan文档中心-今日头条案例文档
 
下载文档

今日头条案例文档
更新时间:2016-06-13

简介

说明

该文档主要结合实际案例(仿”今日头条”应用)来介绍uexNBListView插件在实际项目中的应用。注意阅读该文档之前需熟读“uexNBListView插件API文档”及“自定义布局指引文档”。

UI展示


代码下载

点击下载

实现原理

框架介绍

该应用中有四个tab页分别为“首页”,“视频”,“话题”和“我”,它们通过底部的按钮点击切换。其中“首页”,“视频”和“话题”页都包含头部的导航条可左右滑动切换页面。而“我”tab页只有单独的一个界面。于是该应用设计为三个容器(分别对应前三个tab页,每个容器中包含两个列表,这两个列表之间通过左右滑动切换)和一个列表(对应“我”tab页)。在底部导航栏点击之后,处理容器或列表的显示或者隐藏来实现tab页的切换效果。

实现方式

容器的创建

该应用中需要用到左右滑动切换的效果,因此需要使用到容器。容器需要先创建,然后在打开列表时将列表添加进容器中。具体代码如下:

  1. window.uexOnload = function(type){
  2. var jsonStr = {
  3. id : 0, //容器id
  4. x : 0, //容器位置x坐标
  5. y : top, //容器位置y坐标
  6. w : screen.availWidth, //容器位置w宽度
  7. h : height //容器位置h高度
  8. };
  9. uexWindow.createPluginViewContainer(JSON.stringify(jsonStr));
  10. uexWindow.cbCreatePluginViewContainer = function(opId, dataType, data) {
  11. if(data == "success"){
  12. //创建成功之后,可以向该容器中添加列表视图
  13. addListView(opId);
  14. }
  15. };
  16. }
  17. function addListView(containerId){
  18. openListView("listView1", containerId, 0);
  19. openListView("listView2", containerId, 1);
  20. }
  21. function openListView(listViewId, containerId, containerIndex){
  22. //该示例只说明容器和添加视图的流程,具体在应用中uexNBListView插件的open方法需要
  23. //在initLayout的回调方法之后调用。
  24. var params = {
  25. listViewId:listViewId,
  26. left: 0,//(必选) 左间距
  27. top: 0,//(必选) 上间距
  28. width:window.screen.width,//(必选) 宽
  29. height:height,//(必选) 高
  30. openType:2,//(可选) 打开方式,0-webView,1-window,2-容器
  31. containerID:containerId,
  32. containerIndex:containerIndex,
  33. swipeMode:3,//(可选) 侧滑模式,0-右滑,1-左滑,2-左右滑,3-不能滑。默认3
  34. refreshMode:3,//(可选) 刷新模式,0-无,1-下拉,2-上拉,3-上拉下拉。默认3
  35. refreshTimeout:5000//(可选)刷新超时时间,单位毫秒。在refreshMode非等于0有效,默认为3000
  36. }
  37. uexNBListView.open(JSON.stringify(params));
  38. }

上例中的列表Id为listView1listView2的两个列表可通过左右滑动切换。

列表的创建

定义布局样式

在创建列表之前,需要先调研整个列表中有几种类型的布局,每种类型的布局哪些数据是需要动态更新的。
例如“首页”tab页中,就有四种布局,分别为:

1.纯文本不带图片的,如下:

2.文字加单张图片,图片在文字右侧,如下:

3.文字加单张图片,图片在文字之间,如下:

4.文字加三张图片,图片在文字之间,如下:

虽然该列表中会包含四种样式的布局,但并不代表就一定要定义四种样式,相似的布局可以合并,通过控件的visible属性可以控制某个控件的显示和隐藏,展现不同的效果。
例如,第一种和第三种布局即可以合并,第三种布局中把三张图片的布局隐藏掉即是第一种布局显示的效果。

布局定好之后,需要确定布局中哪些数据是需要动态变化的,例如第一种布局中的黑色文字大标题,每一条新闻大标题必然是不同的。而右下角带“X”号的图标,每一条新闻的图标都一样,则不需要动态更新。
需要动态更新的数据,则要参考“uexNBListView插件API文档”中的”数据载入方式”定义完整数据变量名称,在接口传入数据时,数据与变量一一对应。

布局代码如下:
(1).layout_index_item1.xml
该布局对应第一和第三种布局,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <root layoutId = "index-item1" layoutType = "${type}">
  3. <linearlayout id = "content" width = "-1" height = "-2" background = "#ffffff" onClick = "onItemClick" padding= "30 20">
  4. <text id = "title" width = "-1" height = "-2" text="${title}" textSize = "20" textColor = "#000000"/>
  5. <linearlayout id = "newsPic" orientation = "horizontal" width = "-1" height = "-2" visible = "${isHasPic}">
  6. <!--该元素表示标题下面的图片,isHasPic为0即显示时,即为第三种布局,为1隐藏时为第一种布局-->
  7. <img id = "newsPic1" weight ="1" width="-2" height="-2" src="${picPath1}" scale = "1" scaleType = "centerCrop"/>
  8. <img id = "newsPic2" weight ="1" width="-2" height="-2" src="${picPath2}" margin = "10 0 0 0" scale = "1" scaleType = "centerCrop"/>
  9. <img id = "newsPic3" weight ="1" width="-2" height="-2" src="${picPath3}" margin = "10 0 0 0" scale = "1" scaleType = "centerCrop"/>
  10. </linearlayout>
  11. <relativelayout width = "-1" height = "-2" gravity = "centerY">
  12. <img id = "mark" width = "75" height = "75" src = "${markImg}" visible ="${markVisible}" float = "left|centerY"/>
  13. <text id = "sourceType" width = "-2" height = "-2" text="${source}" textSize = "13" textColor = "#999999" relation = "rightOf,mark" margin = "10 0 0 0" float = "centerY"/>
  14. <text id = "comment" width = "-2" height = "-2" text="${comment}" textSize = "13" textColor = "#999999" relation = "rightOf,sourceType" margin = "10 0 0 0" float = "centerY"/>
  15. <text id = "time" width = "-2" height = "-2" text="${time}" textSize = "13" textColor = "#999999" relation = "rightOf,comment" margin = "10 0 0 0" float = "centerY"/>
  16. <img id = "delete" width = "75" height = "75" src = "res://img/del.png" float = "right|centerY" onClick = "onDeleteClick"/>
  17. </relativelayout>
  18. </linearlayout>
  19. </root>

(2).layout_index_item2.xml
该布局对应第二种布局,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <root layoutId = "index-item2">
  3. <!--该布局为右边有一小图样式布局-->
  4. <linearlayout id = "content" width = "-1" height = "-2" onClick = "onItemClick" background = "#ffffff" orientation = "horizontal" gravity = "centerY" padding= "30 20">
  5. <linearlayout width = "-2" height = "-2" weight = "1">
  6. <text id = "title" width = "-1" height = "-2" text="${title}" textSize = "20" textColor = "#000000"/>
  7. <relativelayout width = "-1" height = "-2" gravity = "centerY">
  8. <img id = "mark" width = "75" height = "75" src = "${markImg}" visible ="${markVisible}" float = "left|centerY"/>
  9. <text id = "sourceType" width = "-2" height = "-2" text="${source}" textSize = "13" textColor = "#999999" relation = "rightOf,mark" margin = "10 0 0 0" float = "centerY"/>
  10. <text id = "comment" width = "-2" height = "-2" text="${comment}" textSize = "13" textColor = "#999999" relation = "rightOf,sourceType" margin = "10 0 0 0" float = "centerY"/>
  11. <text id = "time" width = "-2" height = "-2" text="${time}" textSize = "13" textColor = "#999999" relation = "rightOf,comment" margin = "10 0 0 0" float = "centerY"/>
  12. <img id = "delete" width = "75" height = "75" src = "res://img/del.png" float = "right|centerY" onClick = "onDeleteClick"/>
  13. </relativelayout>
  14. </linearlayout>
  15. <img id = "newsPic" width="300" height="-2" src="${picPath}" />
  16. </linearlayout>
  17. </root>

(3).layout_index_item3.xml
该布局对应第三种布局,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <root layoutId = "index-item3">
  3. <!--该布局为有一个大标题和一张大图样式布局-->
  4. <linearlayout id = "content" width = "-1" height = "-2" background = "#ffffff" onClick = "onItemClick" padding= "30 20">
  5. <text id = "title" width = "-1" height = "-2" text="${title}" textSize = "20" textColor = "#000000"/>
  6. <img id = "newsPic" width="-2" height="-2" src="${picPath}" />
  7. <relativelayout width = "-1" height = "-2" gravity = "centerY">
  8. <img id = "mark" width = "75" height = "75" src = "${markImg}" visible ="${markVisible}" float = "left|centerY"/>
  9. <text id = "sourceType" width = "-2" height = "-2" text="${source}" textSize = "13" textColor = "#999999" relation = "rightOf,mark" margin = "10 0 0 0" float = "centerY"/>
  10. <text id = "comment" width = "-2" height = "-2" text="${comment}" textSize = "13" textColor = "#999999" relation = "rightOf,sourceType" margin = "10 0 0 0" float = "centerY"/>
  11. <text id = "time" width = "-2" height = "-2" text="${time}" textSize = "13" textColor = "#999999" relation = "rightOf,comment" margin = "10 0 0 0" float = "centerY"/>
  12. <img id = "delete" width = "75" height = "75" src = "res://img/del.png" float = "right|centerY" onClick = "onDeleteClick"/>
  13. </relativelayout>
  14. </linearlayout>
  15. </root>

初始化布局

定义好布局文件之后,调用插件的initLayout接口,如下:

  1. var params = {
  2. listViewId:id,
  3. layout:{
  4. center:["res://layout_index_item1.xml",
  5. "res://layout_index_item2.xml",
  6. "res://layout_index_item3.xml"]
  7. }
  8. }
  9. uexNBListView.initLayout(JSON.stringify(params));

其中center关键字表示主布局数组,数组元素为布局文件的存放路径,只支持本地文件。

设置列表数据

initLayout的回调方法cbInitLayout之后可调用设置数据方法setItems。代码如下:

  1. uexNBListView.cbInitLayout = function(data){
  2. var data = JSON.parse(data);
  3. if(data.errorCode == 0){
  4. //初始化成功
  5. setIndexItem1(data.listViewId);
  6. }
  7. }
  8. function setIndexItem1(id){
  9. var params = {
  10. listViewId:id,
  11. dataList:[
  12. {
  13. center:{
  14. "type":"index-item1",
  15. "title":"习近平在阿盟总部演讲 谈中国中东政策",
  16. "isHasPic":1,
  17. "markImg":"res://img/top.png",
  18. "markVisible":0,
  19. "source":"专题",
  20. "comment":"648评论",
  21. "time":"17分钟前"
  22. }
  23. },
  24. {
  25. center:{
  26. "layoutId":"index-item2",
  27. "title":"福建7名贪官结拜兄弟对抗组织 被称葫芦娃组合",
  28. "markImg":"res://img/hot.png",
  29. "markVisible":0,
  30. "source":"中国经济网",
  31. "comment":"2962评论",
  32. "time":"",
  33. "picPath":"res://img/news/news1.png"
  34. }
  35. },
  36. {
  37. center:{
  38. "layoutId":"index-item3",
  39. "title":"全国迎最冷周末 多地低温破极值",
  40. "picPath":"res://img/news/news2.png",
  41. "markImg":"res://img/hot.png",
  42. "markVisible":0,
  43. "source":"专题",
  44. "comment":"4502评论",
  45. "time":"37分钟前"
  46. }
  47. },
  48. {
  49. center:{
  50. "type":"index-item1",
  51. "title":"习近平在阿盟总部演讲 谈中国中东政策",
  52. "isHasPic":1,
  53. "markImg":"res://img/top.png",
  54. "markVisible":0,
  55. "source":"专题",
  56. "comment":"648评论",
  57. "time":"17分钟前"
  58. }
  59. },
  60. {
  61. center:{
  62. "type":"index-item1",
  63. "title":"日本车站便当能甩中国高铁盒饭几条大街?",
  64. "isHasPic":0,
  65. "picPath1":"res://img/news/news3.png",
  66. "picPath2":"res://img/news/news4.png",
  67. "picPath3":"res://img/news/news5.png",
  68. "markImg":"res://img/hot.png",
  69. "markVisible":1,
  70. "source":"日本旅游购物美...",
  71. "comment":"754评论",
  72. "time":"20分钟前"
  73. }
  74. }
  75. ]
  76. }
  77. uexNBListView.setItems(JSON.stringify(params));
  78. }

需要注意的是dataList的主数据中的键值是与布局文件中定义的变量值对应的,同时布局文件中定义为形如${XXX}样式的属性变量,必须在接口数据中传入对应的值,否则显示异常。

打开列表

数据设置完成之后,在setItems的回调方法cbSetItems中调用打开列表视图方法open,如下:

  1. uexNBListView.cbSetItems = function(data){
  2. var data = JSON.parse(data);
  3. if(data.errorCode == 0){
  4. //初始化成功
  5. openListView(data.listViewId,0,0);
  6. }
  7. }

其中openListView方法同上文中容器的创建示例点击查看,其中容器id为0的容器需要提前创建成功,否则会打开失败。调用open方法之后,若已经设置过数据,列表会直接显示,若没有设置过数据,则列表不显示。

显示效果如下:

列表数据的更新

列表数据的更新有以下几种方法:
1.重置列表数据,通过setItems方法实现;
2.更新列表中某一个item中的某一项数据,通过update方法实现;
3.向列表的某一位置添加一个item,通过insert方法实现;
4.从列表中删除一个item,通过delete方法实现。

具体可参考源码示例及uexNBListView插件API文档。