
tab选项卡示例教程-基于subnview模式的原生tab(含底部凸起大图标)
方案比较说明
关于tab bar选项卡,目前已经有多种实现方案,最常见的有div方案的和双webview方案的。
div方案
div方案的选项卡是普通的实现方案,所有都放在一个页面中执行,页面压力可想而知,在手机上会出现卡顿现象。SPA仅适用于非常简单的dom和非常少的页面;
双webview方案
双webview方案的实现思路就是一个包含tab bar 的父webview + n个对应tab的子webview。在5+App的manifest可以配置双Webview首页,可以让tab父页和第一个子tab的子页同时启动。
但Webview的渲染速度不如nview快,Webview太多对内存吃的太多,崩溃和白屏的概率就会增加。此模式也不是最优。
而下面我们介绍的这种方案,让显示速度,占用内存,性能消耗都达到了一种更优的状态!
基于subnview的原生tab选项卡方案
HBuilder8.8起提供了subnview,subnview顾名思义就是子原生view,也就是把一个全屏Webview的一部分区域切出来,渲染工作交给原生引擎渲染,不走Webview渲染。
此方案设计思路简单来说就是把首页的底部区域变成subnview,交给5+的原生引擎渲染,也就是说是要nview来绘制底部tab。
manifest里配置的首页作为第一个tab选项卡窗口,同时为这个Webview配置subnview,在这个subnview里编写nview的描述,就可以创建一个原生的选项卡,这个选项卡的绘制由5+引擎原生完成,在首页Webview渲染之前就由原生层渲染好了。
其余tab项子窗口在首页plus ready后创建,并同时监听tab点击。
原生view控件制作的tab,还可以轻松实现tab中部凸起大图标的效果,这种效果在双Webview模式下不好实现。
可见基于subnview的原生tab选项卡方案渲染更快、内存更少,并且自定义效果也更丰富。
当然也有一些缺点就是有点复杂,对于学习纯HTML5的程序员而言,首先需要学习subnview这些HTML5+独有的技术。
但nview真的是非常值得学习的技术,掌握nview后,你做出来的App体验绝对和原生一样好。
最新方案优化说明
经过一段时间的实践,发现原生tab选项卡方案存在部分问题,已修复如下问题:
- 添加输入框并点击之后webview窗口发生变化,出现白条
- 添加titleNView会造成某些tab点击失效
- 添加titleNView安卓上会出现遮盖子webview的现象
- 设置应用为沉浸式,安卓上中间图标会有下移现象
另外上文提到过webview太多对内存会吃太多,nview创建太多同样存在内存吃紧的问题,原来的方案中为了层次分明和便于监听点击事件总共创建了有6个nview,这与本示例的初衷相悖,所以现在缩减为两个nview。分别是:1.中间凸起图标nview 2.底部选项卡nview。
下面来详细说明此方案(最新方案)的实现方法。
示例效果说明
本示例实现的效果是 使用nativeObj绘制原生view控件类型的底部选项卡 + 底部中央悬浮球图标 + webview模式的选项卡窗口,适用于5+app 和流应用环境,通常应用于app 首页;
效果图展示

实现步骤
1.配置底部选项卡
应用首页配置底部选项卡可以直接在manifest.json 中找到 plus 节点,在里面创建如下示例:
以下给出一个tab的示例,完整示例请下载附件中demo查看。
"launchwebview": { //首页webview窗口
"bottom": "0px",
"background": "#fff",
"subNViews": [ //subNViews节点下配置你的tab (此处只给出一个tab配置示例)
{
"id": "tabBar",
"styles": {
"bottom": "0px",
"left": "0",
"height": "50px",
"width": "100%",
"backgroundColor": "#fff"
},
"tags": [
{
"tag": "font",
"id": "indexIcon",
"text": "\ue500",
"position": {
"top": "4px",
"left": "0",
"width": "25%",
"height": "24px"
},
"textStyles": {
"fontSrc": "_www/fonts/mui.ttf",
"align": "center",
"size": "24px"
}
}, {
"tag": "font",
"id": "indexText",
"text": "首页",
"position": {
"top": "23px",
"left": "0",
"width": "25%",
"height": "24px"
},
"textStyles": {
"align": "center",
"size": "10px"
}
}
]
}
]
}
注意:
1.此处配置tab建议直接配置n个tab 对应n个tag而不是nview控件,尽量少的为webview添加nview控件,nview控件在提供原生渲染能力的同时也会消耗内存。
2.配置需要自己计算图标和文字的显示位置,以上只给出一个示例,具体详情方法可参考附件文件或者HTML5+ API 窗口原生子View控件样式WebviewSubNViewStyles
2.定义tab窗口
将入口页也就是首页作为第一个tab窗口页面,这样做就只需创建3个子webview,相比把tab窗口都作为子webview,占用内存更少,消耗性能也优化更多,而且创建子webview需要等待plusReady事件触发执行,在一些低端机上,子窗口出现会有明显延迟,所以很明显,相比之下直接将首页作为第一个tab窗口页面的方法更优!
首页显示了,接下来是在首页plusReady事件中创建其余tab选项卡对应的窗口,通过webviewObj.append()方法,添加为当前 webview 的 子 webview,方式类似 Hello MUI 实例中 tab bar选项卡 -> 底部选项卡-webview模式
var self = plus.webview.currentWebview();
// 初始化首页tab窗口为首次显示
var temp = {};
temp[self.id] = "true";
mui.extend(aniShow, temp);
// 初始化首个tab 按钮,(此方法为自定义方法,详情见上传的附件中)
toggleNview(self.getStyle().subNViews[0], 0);
// 初始化其余tab窗口
for(var i = 0, len = subpages.length; i < len; i++) {
if(!plus.webview.getWebviewById(subpages[i])) {
// 创建子webview
var sub = plus.webview.create(subpages[i], subpages[i], subpage_style);
// 隐藏子窗口
sub.hide();
// 添加为当前webview 的子 webview ------此步骤很重要
self.append(sub);
}
}
3.底部选项卡添加事件监听
目前底部已经生成四个选项卡,鉴于最新方案已更改为以subnview中创建tag的方式生成选项卡的原因,实现方法为在view控件上添加点击事件监听,然后通过判断点击位置实现tab切换。
部分代码如下:
/**
* 根据判断view控件点击位置判断切换的tab
*/
nview.addEventListener('click', function(e) {
var clientX = e.clientX;
if(clientX > 0 && clientX <= parseInt(pageW * 0.25)) {
currIndex = 0;
} else if(clientX > parseInt(pageW * 0.25) && clientX <= parseInt(pageW * 0.45)) {
currIndex = 1;
} else if(clientX > parseInt(pageW * 0.45) && clientX <= parseInt(pageW * 0.8)) {
currIndex = 2;
} else {
currIndex = 3;
}
// 匹配对应tab窗口
if(currIndex > 0) {
targetPage = plus.webview.getWebviewById(subpages[currIndex - 1]);
} else {
targetPage = plus.webview.currentWebview();
}
if(targetPage == activePage) {
return;
}
if(currIndex !== 3) {
//底部选项卡切换
util.toggleNview(currIndex);
// 子页面切换
util.changeSubpage(targetPage, activePage, aniShow);
//更新当前活跃的页面
activePage = targetPage;
} else {
//第四个tab 打开新窗口
plus.webview.open('html/new-webview.html', 'new', {}, 'slide-in-right', 200);
}
});
说明:点击事件中包含tab选项卡以及tab窗口切换,详情见附件
到这里其实绘制底部选项卡和webview模式的子页面,并且给选项卡添加了监听事件,已经初步完成。
但是小伙伴们还想在这样的模式下给底部中央一个凸起的悬浮大图标,可以怎么做呢,其实原理是一样的,也可以在manifest.json中配置,但是考虑到水平中央的图标涉及屏幕分辨率动态计算目前放在首页plusReady事件中配置,也给开发者一种可以手动绘制view控件的方法,如果你想在非首页采用这种方法呢。
4.利用nativeObj绘制凸起图标参考 HTML 5+ API plus.nativeObj.View
实现步骤如下:
1.首页plusReady事件中创建实例对象,最新方案中将背景nview和图标nview整合到了一起。
示例如下:
// 设置水平居中位置
var leftPos = Math.ceil((window.innerWidth - 60) / 2);
/**
* 简单封装了绘制原生view控件方法 drawNative()
* 绘制内容支持font(文本,字体图标),图片img , 矩形区域rect
*
*/
function drawNative(id, styles, tags) {
var view = new plus.nativeObj.View(id, styles, tags);
return view
}
/**
* drawNativeIcon 绘制带边框的半圆,
* 实现原理:
* id为bg的tag 创建带边框的圆
* id为bg2的tag 创建白色矩形遮住圆下半部分,只显示凸起带边框部分
* id为iconBg的红色背景图
* id为icon的字体图标
* 注意创建先后顺序,创建越晚的层级越高
*/
var drawNativeIcon = util.drawNative('icon', {
bottom: '5px',
left: leftPos + 'px',
width: '60px',
height: '60px'
}, [{
tag: 'rect',
id: 'bg',
position: {
top: '1px',
left: '0px',
width: '100%',
height: '100%'
},
rectStyles: {
color: '#fff',
radius: '50%',
borderColor: '#ccc',
borderWidth: '1px'
}
}, {
tag: 'rect',
id: 'bg2',
position: {
bottom: '-0.5px',
left: '0px',
width: '100%',
height: '45px'
},
rectStyles: {
color: '#fff'
}
}, {
tag: 'rect',
id: 'iconBg',
position: {
top: '5px',
left: '5px',
width: '50px',
height: '50px'
},
rectStyles: {
color: '#d74b28',
radius: '50%'
}
}, {
tag: 'font',
id: 'icon',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
position: {
top: '0px',
left: '5px',
width: '50px',
height: '100%'
},
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align: 'center',
color: '#fff',
size: '30px'
}
}]);
// 添加到当前父webview中,------此步骤很重要
self.append(drawNativeIcon);
2.view控件添加监听事件
//自定义监听图标点击事件
drawNativeIcon.addEventListener('click', function(e) {
mui.alert('你点击了图标,你在此可以打开摄像头或者新窗口等自定义点击事件。','悬浮球点击事件');
});
原生view控件使用说明
- 以上描述创建并绘制原生view控件有两种方法:
a.如果是首页应用,可以在manifest.json文件中相应节点配置,渲染快,配置方法简单
b.通过new plus.nativeObj.View(),创建View实例对象,然后将该实例对象append到当前窗口(plus.webview.currentWebview) - 这两种方法都需要开发者在首页plusReady事件中去针对view控件添加监听事件,比如切换对应窗口这种。
- view控件支持绘制类型:图片、矩形区域、文本(包括字体图标)
- 字体图标比如该悬浮球字体,来自iconfont.cn 阿里巴巴字体库,字体一般为Unicode(16进制)码:'\e600',但是配置的时候,需要填写为"\ue600"才能被原生层正确解析
- 参考 HTML 5+ API plus.nativeObj.View
该示例补充说明
- 中央悬浮大图标都是通过字体加纯色背景实现
- 其背后带边线半球区域也是通过两个矩形区域的view控件叠加拼成的,具体实现方法可以在附件中查看
- 本示例字体文件分别采用mui字体文件和阿里巴巴字体库
- 第四个选项卡点击打开新窗口,为示例教程,开发者可自行定义
- 屏幕旋转后,需手动重绘nview,参考nview的api。虽复杂也可以实现。也可以在manifest里禁用掉旋转。
扩展链接
字体图标绘制原生view控件
如何更新通过nativeObj.View创建的view控件教程
下载附件中的文件,直接解压真机运行即可体验
方案比较说明
关于tab bar选项卡,目前已经有多种实现方案,最常见的有div方案的和双webview方案的。
div方案
div方案的选项卡是普通的实现方案,所有都放在一个页面中执行,页面压力可想而知,在手机上会出现卡顿现象。SPA仅适用于非常简单的dom和非常少的页面;
双webview方案
双webview方案的实现思路就是一个包含tab bar 的父webview + n个对应tab的子webview。在5+App的manifest可以配置双Webview首页,可以让tab父页和第一个子tab的子页同时启动。
但Webview的渲染速度不如nview快,Webview太多对内存吃的太多,崩溃和白屏的概率就会增加。此模式也不是最优。
而下面我们介绍的这种方案,让显示速度,占用内存,性能消耗都达到了一种更优的状态!
基于subnview的原生tab选项卡方案
HBuilder8.8起提供了subnview,subnview顾名思义就是子原生view,也就是把一个全屏Webview的一部分区域切出来,渲染工作交给原生引擎渲染,不走Webview渲染。
此方案设计思路简单来说就是把首页的底部区域变成subnview,交给5+的原生引擎渲染,也就是说是要nview来绘制底部tab。
manifest里配置的首页作为第一个tab选项卡窗口,同时为这个Webview配置subnview,在这个subnview里编写nview的描述,就可以创建一个原生的选项卡,这个选项卡的绘制由5+引擎原生完成,在首页Webview渲染之前就由原生层渲染好了。
其余tab项子窗口在首页plus ready后创建,并同时监听tab点击。
原生view控件制作的tab,还可以轻松实现tab中部凸起大图标的效果,这种效果在双Webview模式下不好实现。
可见基于subnview的原生tab选项卡方案渲染更快、内存更少,并且自定义效果也更丰富。
当然也有一些缺点就是有点复杂,对于学习纯HTML5的程序员而言,首先需要学习subnview这些HTML5+独有的技术。
但nview真的是非常值得学习的技术,掌握nview后,你做出来的App体验绝对和原生一样好。
最新方案优化说明
经过一段时间的实践,发现原生tab选项卡方案存在部分问题,已修复如下问题:
- 添加输入框并点击之后webview窗口发生变化,出现白条
- 添加titleNView会造成某些tab点击失效
- 添加titleNView安卓上会出现遮盖子webview的现象
- 设置应用为沉浸式,安卓上中间图标会有下移现象
另外上文提到过webview太多对内存会吃太多,nview创建太多同样存在内存吃紧的问题,原来的方案中为了层次分明和便于监听点击事件总共创建了有6个nview,这与本示例的初衷相悖,所以现在缩减为两个nview。分别是:1.中间凸起图标nview 2.底部选项卡nview。
下面来详细说明此方案(最新方案)的实现方法。
示例效果说明
本示例实现的效果是 使用nativeObj绘制原生view控件类型的底部选项卡 + 底部中央悬浮球图标 + webview模式的选项卡窗口,适用于5+app 和流应用环境,通常应用于app 首页;
效果图展示
实现步骤
1.配置底部选项卡
应用首页配置底部选项卡可以直接在manifest.json 中找到 plus 节点,在里面创建如下示例:
以下给出一个tab的示例,完整示例请下载附件中demo查看。
"launchwebview": { //首页webview窗口
"bottom": "0px",
"background": "#fff",
"subNViews": [ //subNViews节点下配置你的tab (此处只给出一个tab配置示例)
{
"id": "tabBar",
"styles": {
"bottom": "0px",
"left": "0",
"height": "50px",
"width": "100%",
"backgroundColor": "#fff"
},
"tags": [
{
"tag": "font",
"id": "indexIcon",
"text": "\ue500",
"position": {
"top": "4px",
"left": "0",
"width": "25%",
"height": "24px"
},
"textStyles": {
"fontSrc": "_www/fonts/mui.ttf",
"align": "center",
"size": "24px"
}
}, {
"tag": "font",
"id": "indexText",
"text": "首页",
"position": {
"top": "23px",
"left": "0",
"width": "25%",
"height": "24px"
},
"textStyles": {
"align": "center",
"size": "10px"
}
}
]
}
]
}
注意:
1.此处配置tab建议直接配置n个tab 对应n个tag而不是nview控件,尽量少的为webview添加nview控件,nview控件在提供原生渲染能力的同时也会消耗内存。
2.配置需要自己计算图标和文字的显示位置,以上只给出一个示例,具体详情方法可参考附件文件或者HTML5+ API 窗口原生子View控件样式WebviewSubNViewStyles
2.定义tab窗口
将入口页也就是首页作为第一个tab窗口页面,这样做就只需创建3个子webview,相比把tab窗口都作为子webview,占用内存更少,消耗性能也优化更多,而且创建子webview需要等待plusReady事件触发执行,在一些低端机上,子窗口出现会有明显延迟,所以很明显,相比之下直接将首页作为第一个tab窗口页面的方法更优!
首页显示了,接下来是在首页plusReady事件中创建其余tab选项卡对应的窗口,通过webviewObj.append()方法,添加为当前 webview 的 子 webview,方式类似 Hello MUI 实例中 tab bar选项卡 -> 底部选项卡-webview模式
var self = plus.webview.currentWebview();
// 初始化首页tab窗口为首次显示
var temp = {};
temp[self.id] = "true";
mui.extend(aniShow, temp);
// 初始化首个tab 按钮,(此方法为自定义方法,详情见上传的附件中)
toggleNview(self.getStyle().subNViews[0], 0);
// 初始化其余tab窗口
for(var i = 0, len = subpages.length; i < len; i++) {
if(!plus.webview.getWebviewById(subpages[i])) {
// 创建子webview
var sub = plus.webview.create(subpages[i], subpages[i], subpage_style);
// 隐藏子窗口
sub.hide();
// 添加为当前webview 的子 webview ------此步骤很重要
self.append(sub);
}
}
3.底部选项卡添加事件监听
目前底部已经生成四个选项卡,鉴于最新方案已更改为以subnview中创建tag的方式生成选项卡的原因,实现方法为在view控件上添加点击事件监听,然后通过判断点击位置实现tab切换。
部分代码如下:
/**
* 根据判断view控件点击位置判断切换的tab
*/
nview.addEventListener('click', function(e) {
var clientX = e.clientX;
if(clientX > 0 && clientX <= parseInt(pageW * 0.25)) {
currIndex = 0;
} else if(clientX > parseInt(pageW * 0.25) && clientX <= parseInt(pageW * 0.45)) {
currIndex = 1;
} else if(clientX > parseInt(pageW * 0.45) && clientX <= parseInt(pageW * 0.8)) {
currIndex = 2;
} else {
currIndex = 3;
}
// 匹配对应tab窗口
if(currIndex > 0) {
targetPage = plus.webview.getWebviewById(subpages[currIndex - 1]);
} else {
targetPage = plus.webview.currentWebview();
}
if(targetPage == activePage) {
return;
}
if(currIndex !== 3) {
//底部选项卡切换
util.toggleNview(currIndex);
// 子页面切换
util.changeSubpage(targetPage, activePage, aniShow);
//更新当前活跃的页面
activePage = targetPage;
} else {
//第四个tab 打开新窗口
plus.webview.open('html/new-webview.html', 'new', {}, 'slide-in-right', 200);
}
});
说明:点击事件中包含tab选项卡以及tab窗口切换,详情见附件
到这里其实绘制底部选项卡和webview模式的子页面,并且给选项卡添加了监听事件,已经初步完成。
但是小伙伴们还想在这样的模式下给底部中央一个凸起的悬浮大图标,可以怎么做呢,其实原理是一样的,也可以在manifest.json中配置,但是考虑到水平中央的图标涉及屏幕分辨率动态计算目前放在首页plusReady事件中配置,也给开发者一种可以手动绘制view控件的方法,如果你想在非首页采用这种方法呢。
4.利用nativeObj绘制凸起图标参考 HTML 5+ API plus.nativeObj.View
实现步骤如下:
1.首页plusReady事件中创建实例对象,最新方案中将背景nview和图标nview整合到了一起。
示例如下:
// 设置水平居中位置
var leftPos = Math.ceil((window.innerWidth - 60) / 2);
/**
* 简单封装了绘制原生view控件方法 drawNative()
* 绘制内容支持font(文本,字体图标),图片img , 矩形区域rect
*
*/
function drawNative(id, styles, tags) {
var view = new plus.nativeObj.View(id, styles, tags);
return view
}
/**
* drawNativeIcon 绘制带边框的半圆,
* 实现原理:
* id为bg的tag 创建带边框的圆
* id为bg2的tag 创建白色矩形遮住圆下半部分,只显示凸起带边框部分
* id为iconBg的红色背景图
* id为icon的字体图标
* 注意创建先后顺序,创建越晚的层级越高
*/
var drawNativeIcon = util.drawNative('icon', {
bottom: '5px',
left: leftPos + 'px',
width: '60px',
height: '60px'
}, [{
tag: 'rect',
id: 'bg',
position: {
top: '1px',
left: '0px',
width: '100%',
height: '100%'
},
rectStyles: {
color: '#fff',
radius: '50%',
borderColor: '#ccc',
borderWidth: '1px'
}
}, {
tag: 'rect',
id: 'bg2',
position: {
bottom: '-0.5px',
left: '0px',
width: '100%',
height: '45px'
},
rectStyles: {
color: '#fff'
}
}, {
tag: 'rect',
id: 'iconBg',
position: {
top: '5px',
left: '5px',
width: '50px',
height: '50px'
},
rectStyles: {
color: '#d74b28',
radius: '50%'
}
}, {
tag: 'font',
id: 'icon',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
position: {
top: '0px',
left: '5px',
width: '50px',
height: '100%'
},
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align: 'center',
color: '#fff',
size: '30px'
}
}]);
// 添加到当前父webview中,------此步骤很重要
self.append(drawNativeIcon);
2.view控件添加监听事件
//自定义监听图标点击事件
drawNativeIcon.addEventListener('click', function(e) {
mui.alert('你点击了图标,你在此可以打开摄像头或者新窗口等自定义点击事件。','悬浮球点击事件');
});
原生view控件使用说明
- 以上描述创建并绘制原生view控件有两种方法:
a.如果是首页应用,可以在manifest.json文件中相应节点配置,渲染快,配置方法简单
b.通过new plus.nativeObj.View(),创建View实例对象,然后将该实例对象append到当前窗口(plus.webview.currentWebview) - 这两种方法都需要开发者在首页plusReady事件中去针对view控件添加监听事件,比如切换对应窗口这种。
- view控件支持绘制类型:图片、矩形区域、文本(包括字体图标)
- 字体图标比如该悬浮球字体,来自iconfont.cn 阿里巴巴字体库,字体一般为Unicode(16进制)码:'\e600',但是配置的时候,需要填写为"\ue600"才能被原生层正确解析
- 参考 HTML 5+ API plus.nativeObj.View
该示例补充说明
- 中央悬浮大图标都是通过字体加纯色背景实现
- 其背后带边线半球区域也是通过两个矩形区域的view控件叠加拼成的,具体实现方法可以在附件中查看
- 本示例字体文件分别采用mui字体文件和阿里巴巴字体库
- 第四个选项卡点击打开新窗口,为示例教程,开发者可自行定义
- 屏幕旋转后,需手动重绘nview,参考nview的api。虽复杂也可以实现。也可以在manifest里禁用掉旋转。
扩展链接
字体图标绘制原生view控件
如何更新通过nativeObj.View创建的view控件教程
下载附件中的文件,直接解压真机运行即可体验
收起阅读 »
IOS提交时报ITMS-90168错和Missing Info.plist key 的解决
IOS提交时,先是报90168错
后来查了下,说要换APPLICATION LOADER 3.6版本,但朋友那边用3.0提交他的APP,一点问题没有
用朋友的3.0提交,也还是报ITMS-90168错
估计还是自己的APP问题,后来发现有IP3和IP4的引导图大小不太对,把这俩图换了,再让朋友提交就OK了。(我这边用APPLICATION LOADER 3.0提交还是不行,可能是系统原因吧)
猜想ITMS-90168的错是个笼统的,没有详细的出错说明,这点做的太不到位
提交完成后,过了一会收到邮件,说Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSContactsUsageDescription key with a string value explaining to the user how the app uses this data.
在坛子里查了一下,也有几个说法,最后综合了一下,改为下面这样
然后就过了初审了
IOS提交时,先是报90168错
后来查了下,说要换APPLICATION LOADER 3.6版本,但朋友那边用3.0提交他的APP,一点问题没有
用朋友的3.0提交,也还是报ITMS-90168错
估计还是自己的APP问题,后来发现有IP3和IP4的引导图大小不太对,把这俩图换了,再让朋友提交就OK了。(我这边用APPLICATION LOADER 3.0提交还是不行,可能是系统原因吧)
猜想ITMS-90168的错是个笼统的,没有详细的出错说明,这点做的太不到位
提交完成后,过了一会收到邮件,说Missing Info.plist key - This app attempts to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSContactsUsageDescription key with a string value explaining to the user how the app uses this data.
在坛子里查了一下,也有几个说法,最后综合了一下,改为下面这样
然后就过了初审了
收起阅读 »
利用mui toast制作下拉刷新成功后的顶部提醒
在很多资讯类App中,下拉刷新后,会在顶部提示获取多少条更新内容,如今日头条:
mui要实现类似效果很简单,重写div模式的toast控件样式即可,先看基于Hello MUI中单webview下拉刷新示例改造后的结果:
代码实现
1、重写div模式toast控件样式
这部分实现主要包括:
- toast顶部显示
- 宽度修改为100%宽度
- 定制颜色
示例代码如下:
.mui-toast-container {
top: 0px; //顶部显示
left: 0;
width: 100%;//宽度修改为100%宽度
-webkit-transform:none;
transform: none;
}
.mui-toast-container.mui-active {
opacity: .7;
}
.mui-toast-message {
padding: 8px 15px;
background-color: #007AFF;//定制颜色
color: #fff;
border-radius: 0;
font-size: 13px;
}
2、下拉刷新结束后,显示toast控件
/**
* 下拉刷新具体业务实现
*/
function pulldownRefresh() {
setTimeout(function() {
addData();//这里需要修改为具体业务代码,比如ajax请求
mui('#pullrefresh').pullRefresh().endPulldown();
mui.toast("Hello MUI推荐引擎有5条更新",{type:'div'});
}, 1500);
}
在很多资讯类App中,下拉刷新后,会在顶部提示获取多少条更新内容,如今日头条:
mui要实现类似效果很简单,重写div模式的toast控件样式即可,先看基于Hello MUI中单webview下拉刷新示例改造后的结果:
代码实现
1、重写div模式toast控件样式
这部分实现主要包括:
- toast顶部显示
- 宽度修改为100%宽度
- 定制颜色
示例代码如下:
.mui-toast-container {
top: 0px; //顶部显示
left: 0;
width: 100%;//宽度修改为100%宽度
-webkit-transform:none;
transform: none;
}
.mui-toast-container.mui-active {
opacity: .7;
}
.mui-toast-message {
padding: 8px 15px;
background-color: #007AFF;//定制颜色
color: #fff;
border-radius: 0;
font-size: 13px;
}
2、下拉刷新结束后,显示toast控件
/**
* 下拉刷新具体业务实现
*/
function pulldownRefresh() {
setTimeout(function() {
addData();//这里需要修改为具体业务代码,比如ajax请求
mui('#pullrefresh').pullRefresh().endPulldown();
mui.toast("Hello MUI推荐引擎有5条更新",{type:'div'});
}, 1500);
}
收起阅读 »

获取屏幕滚动状态
应用场景:在屏幕滚动的时候触发相应事件。例如:侧边按钮的隐藏显示、回到顶部按钮的隐藏显示。
iOS:
var pullrefresh = document.getElementById("pullrefresh");
pullrefresh.addEventListener("scrollstart", function(e) {
//滚动开始的方法
});
document.getElementById("pullrefresh").addEventListener("scrollend", function(e) {
//滚动停止的方法
});
Android:
理论上可以监听到window.onscroll,但还不知道如何监听滚动开始和滚动停止的方法,这个方法在滚动的过程中一直触发。Android上的问题还没有解决,如有大神已经解决,还望指教。
相关文章:http://ask.dcloud.net.cn/question/901
http://ask.dcloud.net.cn/article/788
应用场景:在屏幕滚动的时候触发相应事件。例如:侧边按钮的隐藏显示、回到顶部按钮的隐藏显示。
iOS:
var pullrefresh = document.getElementById("pullrefresh");
pullrefresh.addEventListener("scrollstart", function(e) {
//滚动开始的方法
});
document.getElementById("pullrefresh").addEventListener("scrollend", function(e) {
//滚动停止的方法
});
Android:
理论上可以监听到window.onscroll,但还不知道如何监听滚动开始和滚动停止的方法,这个方法在滚动的过程中一直触发。Android上的问题还没有解决,如有大神已经解决,还望指教。
相关文章:http://ask.dcloud.net.cn/question/901
http://ask.dcloud.net.cn/article/788

【示例】Barcod二维码扫描及其结果在webview中的信息的传递
应用场景
1.A页面到B页面,B页面扫描得到结果,返回给A页面,A页面做相关处理;
2.A页面到B页面,B页面扫描得到结果,打开C页面,B页面的结果在C页面处理;根据需求是否关闭B页面,若不关闭,C页面back到B页面,重新调用barcode扫描二维码;
3.扫描页,可以添加本机图片进行扫描、也可以调用闪光灯;
具体实现
1.核心
调用扫描二维码Barcode的方法,Barcode参考文档
var scan = new plus.barcode.Barcode('mask');//创建
scan.start();//执行
scan.onmarked = function(type, result){//成功回调
console.log(result);
};
scan.onerror = function ( error ) {//失败回调
console.log(error);
}
2.A→B→A
首先仍是调用Barcode,得到结果,使用evalJ传递数据给指定页面,evalJ参考文档
scan.onmarked = function(type, result){
if(result) {
alert(result);
scan.close();
plus.storage.setItem('result',result);//这里使用storage来保存数据
var wn = plus.webview.getLaunchWebview();//传递消息返回的webview
wn && wn.evalJS("var result = plus.storage.getItem('result');document.querySelector('#a').innerText = result;");//引号里为指定窗口要执行的代码
plus.webview.currentWebview().close();//扫码成功,关闭当前webview
}
};
3.A→B→C
在B页面得到数据,传给C页面,这里采用的是 将数据存放在Webview窗口的额外扩展参数里面,参考文档
当然也可以用本地储存、mui自定义事件 mui.fire()等方法,本地储存文档,mui.fire()文档
scan.onmarked = function(type, result) {
if(result) {
alert(result);
scan.close();
var w = plus.webview.create('Barcode_B2C.html', 'id', {
'titleNView': {
'backgroundColor': '#262930',
'titleText': '这里是C页面,返回应该关闭B',
'titleColor': '#FFFFFF',
autoBackButton: true
}
}, {//额外参数
barcode_data: result
});
w.show('pop-in','300ms');
}
};
C页面返回时,关闭B页面,直接回到A页面,两种方法实现:
//1.在当前页面back时处理事件
plus.key.addEventListener('backbutton',function(){
plus.webview.getWebviewById('carcode2').close();
plus.webview.currentWebview().close();
});
//2.在页面加载完成后直接关闭B页面
plus.webview.getWebviewById('carcode2').close();
C页面返回时不关闭B页面,同时还要让B页面可以继续扫码:
plus.key.addEventListener('backbutton',function(){
var wn = plus.webview.getWebviewById('carcode3');
// wn && wn.reload();//刷新B页面
wn && wn.evalJS("scan = new plus.barcode.Barcode('mask');scan.start();scan.onmarked = function(type, result) {alert(result)}");//重新让B页面执行扫码操作
plus.webview.currentWebview().close();
})
4.调用闪光灯、本地图片
调用闪光灯的方法,参考文档,相关代码如下:
//闪光灯
document.querySelector('#scan2 img').addEventListener('click', function() {
if(/scan_off.png/.test(this.src)) {//实际中不建议用正则判断,声明个变量就行,这里偷了个懒
this.src = "../img/scan_on.png";
scan.setFlash(true);
} else {
this.src = "../img/scan_off.png";
scan.setFlash(false);
}
})
调用本地图片的方法,调用了 Gallery模块的,参考文档
//闪光灯
//添加本地图片
document.querySelector('#scan1 img').addEventListener('click', function() {
plus.gallery.pick(function(path){//调用本机图片
console.log(path);
plus.barcode.scan(path,onmarked,function(error){//识别图片
plus.nativeUI.alert(JSON.stringify(error));
});
}, function(err){
plus.nativeUI.alert('Failed: '+err.message);
});
})
最后,附上demo源码
应用场景
1.A页面到B页面,B页面扫描得到结果,返回给A页面,A页面做相关处理;
2.A页面到B页面,B页面扫描得到结果,打开C页面,B页面的结果在C页面处理;根据需求是否关闭B页面,若不关闭,C页面back到B页面,重新调用barcode扫描二维码;
3.扫描页,可以添加本机图片进行扫描、也可以调用闪光灯;
具体实现
1.核心
调用扫描二维码Barcode的方法,Barcode参考文档
var scan = new plus.barcode.Barcode('mask');//创建
scan.start();//执行
scan.onmarked = function(type, result){//成功回调
console.log(result);
};
scan.onerror = function ( error ) {//失败回调
console.log(error);
}
2.A→B→A
首先仍是调用Barcode,得到结果,使用evalJ传递数据给指定页面,evalJ参考文档
scan.onmarked = function(type, result){
if(result) {
alert(result);
scan.close();
plus.storage.setItem('result',result);//这里使用storage来保存数据
var wn = plus.webview.getLaunchWebview();//传递消息返回的webview
wn && wn.evalJS("var result = plus.storage.getItem('result');document.querySelector('#a').innerText = result;");//引号里为指定窗口要执行的代码
plus.webview.currentWebview().close();//扫码成功,关闭当前webview
}
};
3.A→B→C
在B页面得到数据,传给C页面,这里采用的是 将数据存放在Webview窗口的额外扩展参数里面,参考文档
当然也可以用本地储存、mui自定义事件 mui.fire()等方法,本地储存文档,mui.fire()文档
scan.onmarked = function(type, result) {
if(result) {
alert(result);
scan.close();
var w = plus.webview.create('Barcode_B2C.html', 'id', {
'titleNView': {
'backgroundColor': '#262930',
'titleText': '这里是C页面,返回应该关闭B',
'titleColor': '#FFFFFF',
autoBackButton: true
}
}, {//额外参数
barcode_data: result
});
w.show('pop-in','300ms');
}
};
C页面返回时,关闭B页面,直接回到A页面,两种方法实现:
//1.在当前页面back时处理事件
plus.key.addEventListener('backbutton',function(){
plus.webview.getWebviewById('carcode2').close();
plus.webview.currentWebview().close();
});
//2.在页面加载完成后直接关闭B页面
plus.webview.getWebviewById('carcode2').close();
C页面返回时不关闭B页面,同时还要让B页面可以继续扫码:
plus.key.addEventListener('backbutton',function(){
var wn = plus.webview.getWebviewById('carcode3');
// wn && wn.reload();//刷新B页面
wn && wn.evalJS("scan = new plus.barcode.Barcode('mask');scan.start();scan.onmarked = function(type, result) {alert(result)}");//重新让B页面执行扫码操作
plus.webview.currentWebview().close();
})
4.调用闪光灯、本地图片
调用闪光灯的方法,参考文档,相关代码如下:
//闪光灯
document.querySelector('#scan2 img').addEventListener('click', function() {
if(/scan_off.png/.test(this.src)) {//实际中不建议用正则判断,声明个变量就行,这里偷了个懒
this.src = "../img/scan_on.png";
scan.setFlash(true);
} else {
this.src = "../img/scan_off.png";
scan.setFlash(false);
}
})
调用本地图片的方法,调用了 Gallery模块的,参考文档
//闪光灯
//添加本地图片
document.querySelector('#scan1 img').addEventListener('click', function() {
plus.gallery.pick(function(path){//调用本机图片
console.log(path);
plus.barcode.scan(path,onmarked,function(error){//识别图片
plus.nativeUI.alert(JSON.stringify(error));
});
}, function(err){
plus.nativeUI.alert('Failed: '+err.message);
});
})
最后,附上demo源码
收起阅读 »
App云端打包历史记录保存时效说明
注意:本文章是针对老版本 HBuilder 说明的,新版HBuilderX中已不存在该界面。
HBuilder云端打包后,会保存最近的打包记录,开发者后期可以手动下载对应安装包,界面如下:
这些安装包在云端的保存时效,一句话概括就是:最近3个月内的最新10条打包记录可下载对应安装包,否则安装包不可下载;
详细说明:
- 打包历史中仅显示最近的10条打包记录
- 在显示的最近10条打包记录中,仅最近3个月内的打包记录可手动下载对应的安装包;
- 在显示的最近10条打包记录中,超过3个月的打包记录,仅显示记录,不显示“手动下载”按钮
如果开发者需要保存历史打包记录,需要自己提前手动下载,在本地进行保存。
注意:本文章是针对老版本 HBuilder 说明的,新版HBuilderX中已不存在该界面。
HBuilder云端打包后,会保存最近的打包记录,开发者后期可以手动下载对应安装包,界面如下:
这些安装包在云端的保存时效,一句话概括就是:最近3个月内的最新10条打包记录可下载对应安装包,否则安装包不可下载;
详细说明:
- 打包历史中仅显示最近的10条打包记录
- 在显示的最近10条打包记录中,仅最近3个月内的打包记录可手动下载对应的安装包;
- 在显示的最近10条打包记录中,超过3个月的打包记录,仅显示记录,不显示“手动下载”按钮
如果开发者需要保存历史打包记录,需要自己提前手动下载,在本地进行保存。
收起阅读 »
一个页面中实现多个侧滑菜单的效果
需求:实现在一个html页面中实现点击不同按钮,实现弹出不同侧滑菜单的效果,还请大家指教。
以前不是做前端的,最近公司有这方面的需求,来学习,遇到了问题有时候不知道怎么解决,在社区找了半天也没有找到想要的答案,所以通过其它方式达到了所要的效果,供坑友们参考。
<!doctype html>
<head>
<meta charset="UTF-8">
<title>在线监控</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link href="css/mui.min.css" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="css/mui.picker.min.css" />
<link rel="stylesheet" href="../css/web5.css" />
<style>
body {
font: 400 14px/1.5 Arial, "Lucida Grande", Verdana, "Microsoft YaHei", hei !important;
}
.aside_content {
margin-top: 60px;
}
.cml-table-view-cell {
padding: 3px 2px;
}
.mui-table-view-cell .ct-right-text {
position: absolute;
font-size: 12px;
height: 16px;
line-height: 16px;
right: 40px;
top: 50%;
margin-top: -8px;
}
</style>
</head>
<body>
<div class="mui-off-canvas-wrap mui-slide-in">
<div class="mui-inner-wrap">
<header class="mui-bar mui-bar-nav">
<a id="toaside" class="mui-icon mui-action-menu mui-icon-bars mui-pull-left"></a>
<h1 class="mui-title">在线监控</h1></header>
<nav class="mui-bar mui-bar-tab">
<a class="mui-tab-item mui-active"><span class="mui-icon mui-icon-home"></span><span class="mui-tab-label">首页</span></a>
<a class="mui-tab-item"><span class="mui-icon mui-icon-phone"></span><span class="mui-tab-label">电话</span></a>
<a class="mui-tab-item"><span class="mui-icon mui-icon-email"></span><span class="mui-tab-label">邮件</span></a>
<a class="mui-tab-item"><span class="mui-icon mui-icon-gear"></span><span class="mui-tab-label">设置</span></a>
</nav>
<div id="cmlcontent" class="mui-content mui-scroll-wrapper">
<div class="mui-scroll"><input id="uistate" type="hidden" /><input id="entityid" type="hidden" entityid="com.cmlsoft.vo.sys.online.OnlineKey" /><input id="pk_bill" type="hidden" pkfield='pk_visitpaper' pk_bill="" />
<ul class="mui-table-view" style="margin-top: 30px;">
<li class="mui-table-view-cell cml-aside" for="pk_operator">
<a id="pk_operator_btn" class="mui-navigate-right cml-tag-size"><span id="pk_operator_title">操作员</span><span id="pk_operator" valuetype="html" isref="true" reffield="pk_operator_ref" refshow="name" class="cml-init ct-color-blue ct-right-text">选择</span></a>
</li>
<li class="mui-table-view-cell cml-table-view-cell mui-input-row"><label>最近操作时间</label><input id="visitorname" valuetype="val" class="cml-init mui-text-right" type="text" placeholder="请输入最近操作时间"></li>
<li class="mui-table-view-cell cml-aside" for="pk_loginway">
<a id="pk_loginway_btn" class="mui-navigate-right cml-tag-size"><span id="pk_loginway_title">登录方式</span><span id="pk_loginway" valuetype="html" isref="true" reffield="pk_loginway_ref" refshow="name" class="cml-init ct-color-blue ct-right-text">选择</span></a>
</li>
</ul>
</div>
</div>
<div class="mui-off-canvas-backdrop"></div>
</div>
<!--弹出菜单-->
<aside id="aside" class="mui-off-canvas-right">
<header class="mui-bar mui-bar-nav">
<h1 id="aside_title" class="mui-title">登录方式</h1>
</header>
<div class="mui-scroll-wrapper">
<div class="mui-scroll">
<div id="pk_operator_content" for="pk_operator" class="aside_content">
<ul class="mui-table-view">
<li class="mui-table-view-cell mui-collapse">
<a class="mui-navigate-right" href="#">面板1</a>
<div class="mui-collapse-content">
<p>面板1子内容</p>
</div>
</li>
</ul>
</div>
<div id="pk_loginway_content" for="pk_loginway" class="aside_content">
<ul class="mui-table-view">
<li class="mui-table-view-cell mui-media">
<a href="javascript:;">
<img class="mui-media-object mui-pull-left" src="http://placehold.it/40x30">
<div class="mui-media-body">
幸福
<p class="mui-ellipsis">能和心爱的人一起睡觉,是件幸福的事情;可是,打呼噜怎么办?</p>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</aside>
</div>
</div>
<script src="js/mui.min.js"></script>
<script src="js/jquery.js"></script>
<script src="../js/mui.picker.min.js"></script>
<script type="text/javascript">
mui.init();
mui(".mui-table-view").on('tap', '.cml-aside', function() {
//获取id
var targetid = $(this).attr("for")
var title = $("#" + targetid + "_title").html();
$("#aside_title").html(title);
var asides = document.getElementsByClassName("aside_content");
for(var i = 0; i < asides.length; i++) {
var forid = asides[i].getAttribute("for");
if(forid && forid == targetid) {
$(asides[i]).attr("style", "display: block;");
} else {
$(asides[i]).attr("style", "display: none;");
}
}
mui("#aside").offCanvas("show");
});
mui('.mui-scroll-wrapper').scroll({
deceleration: 0.0005
});
</script>
</body>
需求:实现在一个html页面中实现点击不同按钮,实现弹出不同侧滑菜单的效果,还请大家指教。
以前不是做前端的,最近公司有这方面的需求,来学习,遇到了问题有时候不知道怎么解决,在社区找了半天也没有找到想要的答案,所以通过其它方式达到了所要的效果,供坑友们参考。
<!doctype html>
<head>
<meta charset="UTF-8">
<title>在线监控</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link href="css/mui.min.css" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="css/mui.picker.min.css" />
<link rel="stylesheet" href="../css/web5.css" />
<style>
body {
font: 400 14px/1.5 Arial, "Lucida Grande", Verdana, "Microsoft YaHei", hei !important;
}
.aside_content {
margin-top: 60px;
}
.cml-table-view-cell {
padding: 3px 2px;
}
.mui-table-view-cell .ct-right-text {
position: absolute;
font-size: 12px;
height: 16px;
line-height: 16px;
right: 40px;
top: 50%;
margin-top: -8px;
}
</style>
</head>
<body>
<div class="mui-off-canvas-wrap mui-slide-in">
<div class="mui-inner-wrap">
<header class="mui-bar mui-bar-nav">
<a id="toaside" class="mui-icon mui-action-menu mui-icon-bars mui-pull-left"></a>
<h1 class="mui-title">在线监控</h1></header>
<nav class="mui-bar mui-bar-tab">
<a class="mui-tab-item mui-active"><span class="mui-icon mui-icon-home"></span><span class="mui-tab-label">首页</span></a>
<a class="mui-tab-item"><span class="mui-icon mui-icon-phone"></span><span class="mui-tab-label">电话</span></a>
<a class="mui-tab-item"><span class="mui-icon mui-icon-email"></span><span class="mui-tab-label">邮件</span></a>
<a class="mui-tab-item"><span class="mui-icon mui-icon-gear"></span><span class="mui-tab-label">设置</span></a>
</nav>
<div id="cmlcontent" class="mui-content mui-scroll-wrapper">
<div class="mui-scroll"><input id="uistate" type="hidden" /><input id="entityid" type="hidden" entityid="com.cmlsoft.vo.sys.online.OnlineKey" /><input id="pk_bill" type="hidden" pkfield='pk_visitpaper' pk_bill="" />
<ul class="mui-table-view" style="margin-top: 30px;">
<li class="mui-table-view-cell cml-aside" for="pk_operator">
<a id="pk_operator_btn" class="mui-navigate-right cml-tag-size"><span id="pk_operator_title">操作员</span><span id="pk_operator" valuetype="html" isref="true" reffield="pk_operator_ref" refshow="name" class="cml-init ct-color-blue ct-right-text">选择</span></a>
</li>
<li class="mui-table-view-cell cml-table-view-cell mui-input-row"><label>最近操作时间</label><input id="visitorname" valuetype="val" class="cml-init mui-text-right" type="text" placeholder="请输入最近操作时间"></li>
<li class="mui-table-view-cell cml-aside" for="pk_loginway">
<a id="pk_loginway_btn" class="mui-navigate-right cml-tag-size"><span id="pk_loginway_title">登录方式</span><span id="pk_loginway" valuetype="html" isref="true" reffield="pk_loginway_ref" refshow="name" class="cml-init ct-color-blue ct-right-text">选择</span></a>
</li>
</ul>
</div>
</div>
<div class="mui-off-canvas-backdrop"></div>
</div>
<!--弹出菜单-->
<aside id="aside" class="mui-off-canvas-right">
<header class="mui-bar mui-bar-nav">
<h1 id="aside_title" class="mui-title">登录方式</h1>
</header>
<div class="mui-scroll-wrapper">
<div class="mui-scroll">
<div id="pk_operator_content" for="pk_operator" class="aside_content">
<ul class="mui-table-view">
<li class="mui-table-view-cell mui-collapse">
<a class="mui-navigate-right" href="#">面板1</a>
<div class="mui-collapse-content">
<p>面板1子内容</p>
</div>
</li>
</ul>
</div>
<div id="pk_loginway_content" for="pk_loginway" class="aside_content">
<ul class="mui-table-view">
<li class="mui-table-view-cell mui-media">
<a href="javascript:;">
<img class="mui-media-object mui-pull-left" src="http://placehold.it/40x30">
<div class="mui-media-body">
幸福
<p class="mui-ellipsis">能和心爱的人一起睡觉,是件幸福的事情;可是,打呼噜怎么办?</p>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</aside>
</div>
</div>
<script src="js/mui.min.js"></script>
<script src="js/jquery.js"></script>
<script src="../js/mui.picker.min.js"></script>
<script type="text/javascript">
mui.init();
mui(".mui-table-view").on('tap', '.cml-aside', function() {
//获取id
var targetid = $(this).attr("for")
var title = $("#" + targetid + "_title").html();
$("#aside_title").html(title);
var asides = document.getElementsByClassName("aside_content");
for(var i = 0; i < asides.length; i++) {
var forid = asides[i].getAttribute("for");
if(forid && forid == targetid) {
$(asides[i]).attr("style", "display: block;");
} else {
$(asides[i]).attr("style", "display: none;");
}
}
mui("#aside").offCanvas("show");
});
mui('.mui-scroll-wrapper').scroll({
deceleration: 0.0005
});
</script>
</body>
收起阅读 »
分享IOS上架审核经验
上图
我的应用的使用在线打包的,所使用HBuilder版本的是HBuilder 8.8.0.201706142254
上传APP使用XCode最新版内置的application loader3.6版本上传的。
上架期间遇到的几次问题和解决方案:
【问题1】上传卡“正在通过 App Store 进行鉴定”
【解】网络原因,可以挂VPN上传,我使用的是“蓝灯”这个科学上网的软件,每个月有免费额度,足够上传了。如果没有VPN也可以,大概等3~40分钟,有时候挂VPN也要等这么就。
【问题2】上传完提示时候提示“No architectures in the binary. Lipo failed to detect any architectures in the bundle executable.”
【解】需要更新XCode到最新版,然后打开XCode->左上角菜单栏->open developer tool->application loader 打开最新版内置的application loader3.6上传
【问题3】上传提示“生成的api分析文件太大,我们无法在交付前验证您的api信息”
【解】貌似不影响上传,可以忽略。
以上都是上传版本时候出现的问题,如果都走完了,就可以到itunes connect里面填写资料上传截图,然后提交审核了。
现在好像审核都比较快,所以拒绝也是很快的。。。审核期间出了一个问题被打回来,拒绝内容没有截图,现在好像也找不到了,大概是说在 IPV6 wifi环境 iPad 下面无法登陆。
这个说一下,大家上架APP前,最好拿iPad安装测试一下,看是否能正常使用,因为苹果测试人员会拿iPad安装测试,如果使用异常会被拒绝的。
回到这里的问题,就是在他们那里无法登陆,这个问题有两个解决方法。
先分析一下,由于是登录不了的情况,问题就定位到了,测试人员在美国无法访问我的服务器API接口,定位到问题了就解决问题。
【解决方案1】需要改动服务器
在排除了后端服务器原因后,问题就出在了网络层,因为美国的网络环境比天朝先进,他们已经把ipv6普及了,能正常解析ipv6地址,而天朝只有教育网支持ipv6,其他网络还停留在ipv4,我的服务器在阿里云,不支持ipv6,所以他们无法在ipv6环境下访问我的API(这个是猜的)。那么我们就给服务器建一条ipv6的隧道,让ipv6环境下的用户能通过隧道访问我们服务器就行了,这个过程很长,我就直接搬运了
1.创建隧道教程(这个教程走到第2步就可以了):http://www.cnblogs.com/vijayfly/p/6612771.html
2.后续步骤(接着前面教程第2步):https://bbs.aliyun.com/read/299254.html
以上教程针对系统版本CentOS7以下(不包括)。
CentOS7以上的:
在最后设置网卡信息时候:
登录Hurricane Electric Free IPv6 Tunnel Broker,在Example Configurateions里选择Linux-route2的配置方法
按照上面的方法建好隧道后,要去域名解析那里添加AAAA解析,并且在服务器要监听ipv6地址和端口
【解决方案2】不需要改动服务器
虽然上面说了,测试环境是ipv6下,但是在没有ipv6的情况下也会兼容ipv4,我在AWS主机上ping了一下我服务器ip,丢包率达到了75%。延迟也很高。这个也有可能造成无法登陆的原因。
解决方法也很简单,在域名解析里,给海外的路线套CDN,(如果你的域名解析没有海外线路,那就换个DNS提供商,DNSPod,阿里云dns这些大型的基本都有海外线路解析),很重要的一点,CDN提供商需要在美国有节点。这样,在美国的审核人员就会访问到美国的CDN节点,比访问国内肯定稳定了。
最后,如果你是直接使用了ip访问服务器接口的。。。。。直接重新提交,万一人品爆发。。。。。。
上图
我的应用的使用在线打包的,所使用HBuilder版本的是HBuilder 8.8.0.201706142254
上传APP使用XCode最新版内置的application loader3.6版本上传的。
上架期间遇到的几次问题和解决方案:
【问题1】上传卡“正在通过 App Store 进行鉴定”
【解】网络原因,可以挂VPN上传,我使用的是“蓝灯”这个科学上网的软件,每个月有免费额度,足够上传了。如果没有VPN也可以,大概等3~40分钟,有时候挂VPN也要等这么就。
【问题2】上传完提示时候提示“No architectures in the binary. Lipo failed to detect any architectures in the bundle executable.”
【解】需要更新XCode到最新版,然后打开XCode->左上角菜单栏->open developer tool->application loader 打开最新版内置的application loader3.6上传
【问题3】上传提示“生成的api分析文件太大,我们无法在交付前验证您的api信息”
【解】貌似不影响上传,可以忽略。
以上都是上传版本时候出现的问题,如果都走完了,就可以到itunes connect里面填写资料上传截图,然后提交审核了。
现在好像审核都比较快,所以拒绝也是很快的。。。审核期间出了一个问题被打回来,拒绝内容没有截图,现在好像也找不到了,大概是说在 IPV6 wifi环境 iPad 下面无法登陆。
这个说一下,大家上架APP前,最好拿iPad安装测试一下,看是否能正常使用,因为苹果测试人员会拿iPad安装测试,如果使用异常会被拒绝的。
回到这里的问题,就是在他们那里无法登陆,这个问题有两个解决方法。
先分析一下,由于是登录不了的情况,问题就定位到了,测试人员在美国无法访问我的服务器API接口,定位到问题了就解决问题。
【解决方案1】需要改动服务器
在排除了后端服务器原因后,问题就出在了网络层,因为美国的网络环境比天朝先进,他们已经把ipv6普及了,能正常解析ipv6地址,而天朝只有教育网支持ipv6,其他网络还停留在ipv4,我的服务器在阿里云,不支持ipv6,所以他们无法在ipv6环境下访问我的API(这个是猜的)。那么我们就给服务器建一条ipv6的隧道,让ipv6环境下的用户能通过隧道访问我们服务器就行了,这个过程很长,我就直接搬运了
1.创建隧道教程(这个教程走到第2步就可以了):http://www.cnblogs.com/vijayfly/p/6612771.html
2.后续步骤(接着前面教程第2步):https://bbs.aliyun.com/read/299254.html
以上教程针对系统版本CentOS7以下(不包括)。
CentOS7以上的:
在最后设置网卡信息时候:
登录Hurricane Electric Free IPv6 Tunnel Broker,在Example Configurateions里选择Linux-route2的配置方法
按照上面的方法建好隧道后,要去域名解析那里添加AAAA解析,并且在服务器要监听ipv6地址和端口
【解决方案2】不需要改动服务器
虽然上面说了,测试环境是ipv6下,但是在没有ipv6的情况下也会兼容ipv4,我在AWS主机上ping了一下我服务器ip,丢包率达到了75%。延迟也很高。这个也有可能造成无法登陆的原因。
解决方法也很简单,在域名解析里,给海外的路线套CDN,(如果你的域名解析没有海外线路,那就换个DNS提供商,DNSPod,阿里云dns这些大型的基本都有海外线路解析),很重要的一点,CDN提供商需要在美国有节点。这样,在美国的审核人员就会访问到美国的CDN节点,比访问国内肯定稳定了。
最后,如果你是直接使用了ip访问服务器接口的。。。。。直接重新提交,万一人品爆发。。。。。。
收起阅读 »
FTP插件获取不到文件目录
测试的服务器是win系统的,能获取到文件的目录,但是线上的是linux系统的。而且我使用FTP都能直接获取到目录,但是在使用HBuilder FTP插件的时候就是获取不到
测试的服务器是win系统的,能获取到文件的目录,但是线上的是linux系统的。而且我使用FTP都能直接获取到目录,但是在使用HBuilder FTP插件的时候就是获取不到

希望DCloud团队开发Linux版本的HBuilder
尊敬的DCloud团队,HBuilder是我见过的最强大的Web开发IDE,而且完全免费,真心非常喜欢。可惜没有Linux版本的HBuilder,希望强大的DCloud团队能够开发出Ubuntu版本的HBuilder。Please
尊敬的DCloud团队,HBuilder是我见过的最强大的Web开发IDE,而且完全免费,真心非常喜欢。可惜没有Linux版本的HBuilder,希望强大的DCloud团队能够开发出Ubuntu版本的HBuilder。Please

MUI-沉浸式导航代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<script src="js/mui.min.js"></script>
<link href="css/mui.min.css" rel="stylesheet"/>
<style type="text/css">
.bg-color{
/background: red;/
background: rgba(252,35,180,0);
}
.bg-color h1{
color: #fff;
font-weight: bold;
}
.box img{
width: 100%;
height: 300px;
}
</style>
</head><body>
<!--mheader 按下回车键就可以打出头部导航-->
<header class="mui-bar mui-bar-transparent bg-color" id="header">
<h1 class="mui-title">橙汁-2971611409</h1>
</header>
<!--mbody 按下回车键就可以打出主体身体的意思-->
<div class="mui-content">
<div class="box">
<img src="img/logo1.jpg"/>
</div>
<div style="height: 1000px;"></div>
</div>
<script type="text/javascript" charset="utf-8">
mui.init();
mui.plusReady(function(){
// 创建加载内容窗口
var topoffset='45px';
var header=document.getElementById("header");
if(plus.navigator.isImmersedStatusbar()){// 兼容immersed状态栏模式
// 获取状态栏高度并根据业务需求处理,这里重新计算了子窗口的偏移位置
topoffset=(Math.round(plus.navigator.getStatusbarHeight())+45);
header.style.height=topoffset+'px';
header.style.paddingTop=(topoffset-45)+'px';
}
});
</script>
把这行代码放到json文件里面的代码视图
"ImmersedStatusbar": true,
</body></html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<script src="js/mui.min.js"></script>
<link href="css/mui.min.css" rel="stylesheet"/>
<style type="text/css">
.bg-color{
/background: red;/
background: rgba(252,35,180,0);
}
.bg-color h1{
color: #fff;
font-weight: bold;
}
.box img{
width: 100%;
height: 300px;
}
</style>
</head><body>
<!--mheader 按下回车键就可以打出头部导航-->
<header class="mui-bar mui-bar-transparent bg-color" id="header">
<h1 class="mui-title">橙汁-2971611409</h1>
</header>
<!--mbody 按下回车键就可以打出主体身体的意思-->
<div class="mui-content">
<div class="box">
<img src="img/logo1.jpg"/>
</div>
<div style="height: 1000px;"></div>
</div>
<script type="text/javascript" charset="utf-8">
mui.init();
mui.plusReady(function(){
// 创建加载内容窗口
var topoffset='45px';
var header=document.getElementById("header");
if(plus.navigator.isImmersedStatusbar()){// 兼容immersed状态栏模式
// 获取状态栏高度并根据业务需求处理,这里重新计算了子窗口的偏移位置
topoffset=(Math.round(plus.navigator.getStatusbarHeight())+45);
header.style.height=topoffset+'px';
header.style.paddingTop=(topoffset-45)+'px';
}
});
</script>
把这行代码放到json文件里面的代码视图
"ImmersedStatusbar": true,
</body></html>