Safari调试iOS应用
HBuilder对前端代码的调试方式有边改边看、真机运行、webkit remote debug真机调试3种。
系列文章目录导航:
- 调试方式介绍一 边改边看
- 调试方式介绍二 真机运行
- 调试方式介绍三 webkit remote debug之Chrome调试Android手机
- [调试方式介绍四 webkit remote debug之Safari调试iOS手机]
Safari调试iOS手机概述
对于HTML5的开发,大家都知道Chrome的DevTools工具有强大的功能和友好的用户体验,不仅能快速方便调试JavaScript、检查HTML页面DOM结构、实时同步更新元素CSS样式,还能跟踪分析页面资源加载性能等问题。
对于移动平台的开发者来说,从iOS5.0开始,也可以通过Safari的Web Inspector工具连接设备对应用进行调试。
调试效果如图所示:
我们有2种方式,一种是使用xcode iOS模拟器,一种是使用iPhone、iPad、iTouch等真实设备。
如果使用xcode模拟器,可以直接使用safari的控制台debug。
如果使用真机,由于iOS有签名校验机制,正式包不允许safari debug,所以安装在真机上的包必须是测试签名打的包。此时参考如下步骤:
真机调试环境
准备环境
- Mac OS 10.9以上系统。无论使用模拟器还是真机,由于safari只有mac版本,所以必须配备mac电脑。
- xcode iOS模拟器
- 如果使用真实手机debug,还需要:
- 苹果开发者账号,申请苹果开发证书(Certificates)和描述文件(Provisoning Profiles)
- iOS5.0以上设备(iPhone、iPad、iTouch均可)
申请开发证书和描述文件
参考iOS证书(.p12)和描述文件(.mobileprovision)申请
使用HBuilder App云端打包获取调试安装包
在HBuilder中选中要调试的应用,在菜单中选择“发行”->“App打包”,打开“App云端打包”界面:
正确配置生成调试包的参数
- AppID:苹果开发者中心申请的应用标识,必须与申请描述文件时选择的一致
- 私钥证书:苹果开发者中心申请的Development证书,必须是p12格式证书
- 私钥密码:导入苹果开发者证书的密码,在导出成p12证书时设置
- pfofile文件:苹果开发者中心申请的描述文件
提交App云端打包成功后可获取ipa安装包:
使用iTunes或iTools工具安装ipa到设备
开启iOS设备的调试功能
打开“设置”程序,进入“Safari”->“高级”页面开启“Web检查器”:
启动上一步安装的应用,并将设备连接到Mac电脑
模拟器调试环境
使用模拟器调测更为方便。
准备环境
- Mac OS 10.9以上系统
- XCode6.0以上程序
安装XCode程序
在Safari中打开XCode下载页面
可以选择通过App Store,按提示一步步安装:
或者可以下载Beta版本dmg文件,在Finder中双击dmg文件按提示一步步安装:
HBuilder中启动模拟器运行
HBuilder中选中要调试的应用,在Mac OS上安装好XCode后会自动检测支持的iOS模拟器。
在菜单中选择“运行”->"手机运行"->"iOS模拟器运行":
或者通过“真机运行”图标打开:
在列表中选择要运行的模拟器后,会自动启动iOS模拟器并运行要调试的应用:
使用Safari调试
打开“开发者”菜单
运行Safari,点击“Safari”菜单下面的“偏好设置(Preferences...)”,切换到“高级选项(Advanced)”:
勾选“在菜单栏显示"开发"菜单(Show Develop menu in menu bar)”,关闭偏好设置。
此时在Safari的工具栏出现“开发(Develop)”菜单:
真机设备连接调试
如果是真机点击“开发(Develop)”弹出菜单会出现设备名称项,进入后显示设备上所有打开的“HTML页面”列表:
点击“HTML页面”列表中的项即可打开Web Inspector调试界面
模拟器连接调试
如果是真机点击“开发(Develop)”弹出菜单会出现“iOS Simulator”项,进入后显示模拟器上所有打开的“HTML页面”列表:
点击“HTML页面”列表中的项即可打开Web Inspector调试界面
Web Inspector调试
打开Web Inspector界面后,即可调试JavaScript、检查HTML页面DOM结构、实时同步更新元素CSS样式等操作:
可通过以下方式切换“DOM树(DOM Tree)”和“源码(Source Code)”方式显示页面:
在“源码(Source Code)”模式可在页面左侧添加断点进行调试。
HBuilder对前端代码的调试方式有边改边看、真机运行、webkit remote debug真机调试3种。
系列文章目录导航:
- 调试方式介绍一 边改边看
- 调试方式介绍二 真机运行
- 调试方式介绍三 webkit remote debug之Chrome调试Android手机
- [调试方式介绍四 webkit remote debug之Safari调试iOS手机]
Safari调试iOS手机概述
对于HTML5的开发,大家都知道Chrome的DevTools工具有强大的功能和友好的用户体验,不仅能快速方便调试JavaScript、检查HTML页面DOM结构、实时同步更新元素CSS样式,还能跟踪分析页面资源加载性能等问题。
对于移动平台的开发者来说,从iOS5.0开始,也可以通过Safari的Web Inspector工具连接设备对应用进行调试。
调试效果如图所示:
我们有2种方式,一种是使用xcode iOS模拟器,一种是使用iPhone、iPad、iTouch等真实设备。
如果使用xcode模拟器,可以直接使用safari的控制台debug。
如果使用真机,由于iOS有签名校验机制,正式包不允许safari debug,所以安装在真机上的包必须是测试签名打的包。此时参考如下步骤:
真机调试环境
准备环境
- Mac OS 10.9以上系统。无论使用模拟器还是真机,由于safari只有mac版本,所以必须配备mac电脑。
- xcode iOS模拟器
- 如果使用真实手机debug,还需要:
- 苹果开发者账号,申请苹果开发证书(Certificates)和描述文件(Provisoning Profiles)
- iOS5.0以上设备(iPhone、iPad、iTouch均可)
申请开发证书和描述文件
参考iOS证书(.p12)和描述文件(.mobileprovision)申请
使用HBuilder App云端打包获取调试安装包
在HBuilder中选中要调试的应用,在菜单中选择“发行”->“App打包”,打开“App云端打包”界面:
正确配置生成调试包的参数
- AppID:苹果开发者中心申请的应用标识,必须与申请描述文件时选择的一致
- 私钥证书:苹果开发者中心申请的Development证书,必须是p12格式证书
- 私钥密码:导入苹果开发者证书的密码,在导出成p12证书时设置
- pfofile文件:苹果开发者中心申请的描述文件
提交App云端打包成功后可获取ipa安装包:
使用iTunes或iTools工具安装ipa到设备
开启iOS设备的调试功能
打开“设置”程序,进入“Safari”->“高级”页面开启“Web检查器”:
启动上一步安装的应用,并将设备连接到Mac电脑
模拟器调试环境
使用模拟器调测更为方便。
准备环境
- Mac OS 10.9以上系统
- XCode6.0以上程序
安装XCode程序
在Safari中打开XCode下载页面
可以选择通过App Store,按提示一步步安装:
或者可以下载Beta版本dmg文件,在Finder中双击dmg文件按提示一步步安装:
HBuilder中启动模拟器运行
HBuilder中选中要调试的应用,在Mac OS上安装好XCode后会自动检测支持的iOS模拟器。
在菜单中选择“运行”->"手机运行"->"iOS模拟器运行":
或者通过“真机运行”图标打开:
在列表中选择要运行的模拟器后,会自动启动iOS模拟器并运行要调试的应用:
使用Safari调试
打开“开发者”菜单
运行Safari,点击“Safari”菜单下面的“偏好设置(Preferences...)”,切换到“高级选项(Advanced)”:
勾选“在菜单栏显示"开发"菜单(Show Develop menu in menu bar)”,关闭偏好设置。
此时在Safari的工具栏出现“开发(Develop)”菜单:
真机设备连接调试
如果是真机点击“开发(Develop)”弹出菜单会出现设备名称项,进入后显示设备上所有打开的“HTML页面”列表:
点击“HTML页面”列表中的项即可打开Web Inspector调试界面
模拟器连接调试
如果是真机点击“开发(Develop)”弹出菜单会出现“iOS Simulator”项,进入后显示模拟器上所有打开的“HTML页面”列表:
点击“HTML页面”列表中的项即可打开Web Inspector调试界面
Web Inspector调试
打开Web Inspector界面后,即可调试JavaScript、检查HTML页面DOM结构、实时同步更新元素CSS样式等操作:
可通过以下方式切换“DOM树(DOM Tree)”和“源码(Source Code)”方式显示页面:
在“源码(Source Code)”模式可在页面左侧添加断点进行调试。
【BUG】2015年1月15日发布Android平台HTML5+SDK
在HBuilder真机调试的时候正常,用2015年1月15日发布Android平台HTML5+SDK打包后,等待框不显示。
于是我用12月16的ui.jar替换,又能正常显示了,可能是1月15的ui.jar有bug,还是别的什么原因?特此反馈一下..
另外,希望Feature-Android.xls能完善些,好让我们选择需要的组件,特别是我这种有洁癖的。
原本打包出来3M,我精简掉不需要的jar和so后,700KB。。。
之所以不选择在线打包,这也是原因之一。
在HBuilder真机调试的时候正常,用2015年1月15日发布Android平台HTML5+SDK打包后,等待框不显示。
于是我用12月16的ui.jar替换,又能正常显示了,可能是1月15的ui.jar有bug,还是别的什么原因?特此反馈一下..
另外,希望Feature-Android.xls能完善些,好让我们选择需要的组件,特别是我这种有洁癖的。
原本打包出来3M,我精简掉不需要的jar和so后,700KB。。。
之所以不选择在线打包,这也是原因之一。
提升HTML5的性能体验系列之三 流畅下拉刷新和上拉翻页
系列文章目录导航:
- 提升HTML5的性能体验系列之一 避免切页白屏
- 提升HTML5的性能体验系列之二 列表流畅滑动
- [提升HTML5的性能体验系列之三 流畅下拉刷新]
- 提升HTML5的性能体验系列之四 使用原生UI(nativeUI)
- 提升HTML5的性能体验系列之五 webview启动速度优化及事件顺序解析
- 提升HTML5的性能体验系列之六 降低内存占用
本文更新于2017-5-8
下拉刷新
为实现下拉刷新功能,大多H5框架都是通过DIV模拟下拉回弹动画,在低端android手机上,DIV动画经常出现卡顿现象(特别是图文列表的情况)。
解决方案有如下2种。
1.原生circle下拉刷新
既然拉div卡,我们就不拉div,而是拉一个原生的圈圈下来。
在Android上,google官方提供了一个下拉刷新样式。5+引擎将其封装给js调用。如下图
在一个HTML页面中,title区域仍然是普通dom,不是双webview也不是原生头,在这个webview的style里指定下拉刷新的circle模式,配置起始位置高度,就可以在该webview拉到顶部后再次下拉时在指定位置出现一个旋转的箭头。
api见:http://html5plus.org/doc/zh_cn/webview.html里搜索circle。
示例代码参考Hello mui里pull to refresh(下拉刷新和上拉加载)中的单webview模式。
iOS上也可以使用circle方式。使用同样的代码,在iOS上也有同样的下拉刷新效果。
- 双webview上下拉开式下拉刷新
官方推荐使用高性能的circle下拉刷新方式,但如果实在不能接受circle这种风格,需要上下拉开的下拉刷新,那么可以使用如下方案。
拉div卡那就不拉div,改拉webview。webview的拉动是原生的,回弹效果也是原生的,体验与原生一致。
此时需要双webview的父子页面,思路是在父页面写title,title下面10像素左右写一个文字“下拉可刷新”。
然后append一个子webview,并在style里设置为可下拉。
那么在把子webview往下拉时,会露出父页面的“下拉可刷新”字样,并且在拉到一定距离后会触发一个事件,js捕获到这个事件后可以更改“下拉可刷新”为“松开可刷新”。同样松开也会触发一个事件。
这种模式,下拉漏出的内容是在父页面的HTML中写的,所以样式可以随便定制,实现个性化下拉刷新。
但目前上下拉开的下拉刷新,Android和iOS有实现差异。
上述模式为Android模式。在iOS上,不能在父页面title下面随便定制下拉露出内容的样式,而是需要在子webview的style里配置。
API同样是在http://html5plus.org/doc/zh_cn/webview.html,搜索WebviewRefreshStyles,style里选default模式。
因为是配置方式,iOS上这种模式的下拉刷新无法实现非常个性化的效果。
如果实在需要iOS上做个性化下拉刷新,也可以使用div方式,毕竟iOS上的div拉动性能还是没多大问题的。
为了方便开发者一套代码解决问题,mui框架对2种方案进行了统一封装,即Android上使用双webview自定义下拉刷新,iOS上使用了div下拉刷新。
参考:http://dev.dcloud.net.cn/mui/pulldown/
注意双webview模式增加了app的内存和渲染压力,官方首推的是单webview的circle模式的下拉刷新。
上拉翻页
App里很常见的列表是滚到最下面时载入下一页内容。
传统的思路里,是依靠js监听滚动条位置来实现。这导致任意滚动列表时,都会造成这个监听事件触发,容易引发列表滑动卡顿。
HTML5Plus扩展了一个事件,是原生的下拉到底事件,在webview滚动条到底部时会自动触发。
这样js只需监听这个拉到底事件即可,提升了App的执行性能。
5+ API参考:http://www.html5plus.org/#specification#/specification/Events.html
MUI封装参考:http://dev.dcloud.net.cn/mui/pullup/
这些代码示例在Hello H5+和Hello mui中都有。
系列文章目录导航:
- 提升HTML5的性能体验系列之一 避免切页白屏
- 提升HTML5的性能体验系列之二 列表流畅滑动
- [提升HTML5的性能体验系列之三 流畅下拉刷新]
- 提升HTML5的性能体验系列之四 使用原生UI(nativeUI)
- 提升HTML5的性能体验系列之五 webview启动速度优化及事件顺序解析
- 提升HTML5的性能体验系列之六 降低内存占用
本文更新于2017-5-8
下拉刷新
为实现下拉刷新功能,大多H5框架都是通过DIV模拟下拉回弹动画,在低端android手机上,DIV动画经常出现卡顿现象(特别是图文列表的情况)。
解决方案有如下2种。
1.原生circle下拉刷新
既然拉div卡,我们就不拉div,而是拉一个原生的圈圈下来。
在Android上,google官方提供了一个下拉刷新样式。5+引擎将其封装给js调用。如下图
在一个HTML页面中,title区域仍然是普通dom,不是双webview也不是原生头,在这个webview的style里指定下拉刷新的circle模式,配置起始位置高度,就可以在该webview拉到顶部后再次下拉时在指定位置出现一个旋转的箭头。
api见:http://html5plus.org/doc/zh_cn/webview.html里搜索circle。
示例代码参考Hello mui里pull to refresh(下拉刷新和上拉加载)中的单webview模式。
iOS上也可以使用circle方式。使用同样的代码,在iOS上也有同样的下拉刷新效果。
- 双webview上下拉开式下拉刷新
官方推荐使用高性能的circle下拉刷新方式,但如果实在不能接受circle这种风格,需要上下拉开的下拉刷新,那么可以使用如下方案。
拉div卡那就不拉div,改拉webview。webview的拉动是原生的,回弹效果也是原生的,体验与原生一致。
此时需要双webview的父子页面,思路是在父页面写title,title下面10像素左右写一个文字“下拉可刷新”。
然后append一个子webview,并在style里设置为可下拉。
那么在把子webview往下拉时,会露出父页面的“下拉可刷新”字样,并且在拉到一定距离后会触发一个事件,js捕获到这个事件后可以更改“下拉可刷新”为“松开可刷新”。同样松开也会触发一个事件。
这种模式,下拉漏出的内容是在父页面的HTML中写的,所以样式可以随便定制,实现个性化下拉刷新。
但目前上下拉开的下拉刷新,Android和iOS有实现差异。
上述模式为Android模式。在iOS上,不能在父页面title下面随便定制下拉露出内容的样式,而是需要在子webview的style里配置。
API同样是在http://html5plus.org/doc/zh_cn/webview.html,搜索WebviewRefreshStyles,style里选default模式。
因为是配置方式,iOS上这种模式的下拉刷新无法实现非常个性化的效果。
如果实在需要iOS上做个性化下拉刷新,也可以使用div方式,毕竟iOS上的div拉动性能还是没多大问题的。
为了方便开发者一套代码解决问题,mui框架对2种方案进行了统一封装,即Android上使用双webview自定义下拉刷新,iOS上使用了div下拉刷新。
参考:http://dev.dcloud.net.cn/mui/pulldown/
注意双webview模式增加了app的内存和渲染压力,官方首推的是单webview的circle模式的下拉刷新。
上拉翻页
App里很常见的列表是滚到最下面时载入下一页内容。
传统的思路里,是依靠js监听滚动条位置来实现。这导致任意滚动列表时,都会造成这个监听事件触发,容易引发列表滑动卡顿。
HTML5Plus扩展了一个事件,是原生的下拉到底事件,在webview滚动条到底部时会自动触发。
这样js只需监听这个拉到底事件即可,提升了App的执行性能。
5+ API参考:http://www.html5plus.org/#specification#/specification/Events.html
MUI封装参考:http://dev.dcloud.net.cn/mui/pullup/
这些代码示例在Hello H5+和Hello mui中都有。
收起阅读 »HBuilder如何支持微信App的JS SDK开发
- 新建web项目,选微信模板。创建好后的项目页面内容自带了微信JS SDK的初始化代码。
- 在js里敲wx,会出现微信JS SDK对象及大量代码块,由于微信JS SDK有不少匿名函数用法,代码比较多,这些整理好的代码块可以大幅提升开发效率。
- wx对象的框架语法库以sdocml的形式已经预置在HBuilder里,自动挂载在微信项目上。
所有微信JS SDK的语法提示、参数都可以无死角提示,并且自带API说明。
如果新建项目不选微信模板,也可以通过以下2种方式做提示:
- 对项目点右键,引入框架语法,选微信JS SDK框架语法库。
- 引用微信JS-SDK的js文件<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>,HBuilder会自动识别并加载微信的JS-SDK的框架语法库。
注意,由于微信并不支持HTML放在手机端离线运行,所以微信项目模板仍属于web项目分类。
移动App项目是指在手机端本地运行的App。
微信JS SDK的官方API手册说明地址: http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
- 新建web项目,选微信模板。创建好后的项目页面内容自带了微信JS SDK的初始化代码。
- 在js里敲wx,会出现微信JS SDK对象及大量代码块,由于微信JS SDK有不少匿名函数用法,代码比较多,这些整理好的代码块可以大幅提升开发效率。
- wx对象的框架语法库以sdocml的形式已经预置在HBuilder里,自动挂载在微信项目上。
所有微信JS SDK的语法提示、参数都可以无死角提示,并且自带API说明。
如果新建项目不选微信模板,也可以通过以下2种方式做提示:
- 对项目点右键,引入框架语法,选微信JS SDK框架语法库。
- 引用微信JS-SDK的js文件<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>,HBuilder会自动识别并加载微信的JS-SDK的框架语法库。
注意,由于微信并不支持HTML放在手机端离线运行,所以微信项目模板仍属于web项目分类。
移动App项目是指在手机端本地运行的App。
微信JS SDK的官方API手册说明地址: http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
收起阅读 »MUI文档chm版
关于mui官方提供的文档,个人感觉有点儿杂乱,很不利于开发。故鄙人专门花了一天时间,对官网提供的api进行了一下整理,编辑成chm格式。现发布在此,供广大的开发者免费学习使用。对于本文档,只可用于开发者学习使用,严禁以营利为目的的下载、传播等。
若在使用该文档过程中发现bug,可向zsf513@gmail.com发邮件进行反馈,大家一起来进行完善。
关于mui官方提供的文档,个人感觉有点儿杂乱,很不利于开发。故鄙人专门花了一天时间,对官网提供的api进行了一下整理,编辑成chm格式。现发布在此,供广大的开发者免费学习使用。对于本文档,只可用于开发者学习使用,严禁以营利为目的的下载、传播等。
若在使用该文档过程中发现bug,可向zsf513@gmail.com发邮件进行反馈,大家一起来进行完善。
收起阅读 »
app辛酸历程
从14年8月开始正式使用hbuilder到现在也有快半年了,我们的app经过漫长的历程终于有成果了。
简单说说,14年3月接触hbuilder,觉得这真是一个非常不错的工具,之前都是用phonegap+jquerymobile来做app,由于不是走的android和ios开发路线,
也碰到很多问题,但是一直觉得移动互联网是未来的一个发展趋势,5月公司外包app给别公司做,但是两个月后出来的app实在不咋的,关键是源生的app
在某个功能上还不支持,导致app没有上线,8月我极力推荐使用webapp,至少能解决那个源生app不支持的功能(与银行有关),8月底项目正式开始,从页面
设计,到后台设计,前台开发,历时1个月终于在国庆节时完成(吐槽一下,那真是黑暗的一个月,程序猿命苦),期间各种问题,各种想办法解决,特别是不同机型在某些
页面上会出很多稀奇古怪的bug,即使相同机型不同的android版本也是如此(对android无力吐槽),android完成后ios就特别快了,几天搞定(但是未提交审核),完成后给一些重要
的客户试用了一下,提了一些问题,然后重新进行了一些调整,在11月底正式面向所有用户推出了android版本,以上都是废话,下面才是重点。
说下ios的版本,要先到ios的开发者中心申请一个appid,再缴$99获得一年的开发权,申请一个用户appstore使用的appid,然后要在mac上创建一个私钥,根据这个私钥在ios开发者中心
里创建一个cer证书,下载这个证书到本地,在证书管理里面和私钥一起生成一个.p12的私钥证书文件,至此所有的准备工作完成,通过hbuilder的线上打包,打完是个ipa文件,这个文件
就可以通过mac上的application loader程序提交了,友情提示,如果出现error description not available这个错误提示,可能是网络问题,建议用手机建一个热点,mac连上后再上传文件,
最后从itunes conect里提交审核,审核时间如果不出意外一般在15天左右,如果出现意外(我们的app被拒了一次),一次意外加一周,我们的app除去圣诞大概在23天左右审核通过了。
感谢DCloud-App导师,感谢DCloud-MUI-CHB的帮助。
以下接着废话,蛋疼的是审核时间太长,android已经更新了两个版本,所以要在下个版本进行同步了。
中间多少汗和泪就不说了,走这条路确实辛苦,但是也有很多收获,希望大家多多交流,一起进步,活跃在论坛的各个角落。
我们的网址是(www.dtcash.com),论坛里有网站方面的高手可以加我qq聊聊最新的一些技术 我的qq是524014724
从14年8月开始正式使用hbuilder到现在也有快半年了,我们的app经过漫长的历程终于有成果了。
简单说说,14年3月接触hbuilder,觉得这真是一个非常不错的工具,之前都是用phonegap+jquerymobile来做app,由于不是走的android和ios开发路线,
也碰到很多问题,但是一直觉得移动互联网是未来的一个发展趋势,5月公司外包app给别公司做,但是两个月后出来的app实在不咋的,关键是源生的app
在某个功能上还不支持,导致app没有上线,8月我极力推荐使用webapp,至少能解决那个源生app不支持的功能(与银行有关),8月底项目正式开始,从页面
设计,到后台设计,前台开发,历时1个月终于在国庆节时完成(吐槽一下,那真是黑暗的一个月,程序猿命苦),期间各种问题,各种想办法解决,特别是不同机型在某些
页面上会出很多稀奇古怪的bug,即使相同机型不同的android版本也是如此(对android无力吐槽),android完成后ios就特别快了,几天搞定(但是未提交审核),完成后给一些重要
的客户试用了一下,提了一些问题,然后重新进行了一些调整,在11月底正式面向所有用户推出了android版本,以上都是废话,下面才是重点。
说下ios的版本,要先到ios的开发者中心申请一个appid,再缴$99获得一年的开发权,申请一个用户appstore使用的appid,然后要在mac上创建一个私钥,根据这个私钥在ios开发者中心
里创建一个cer证书,下载这个证书到本地,在证书管理里面和私钥一起生成一个.p12的私钥证书文件,至此所有的准备工作完成,通过hbuilder的线上打包,打完是个ipa文件,这个文件
就可以通过mac上的application loader程序提交了,友情提示,如果出现error description not available这个错误提示,可能是网络问题,建议用手机建一个热点,mac连上后再上传文件,
最后从itunes conect里提交审核,审核时间如果不出意外一般在15天左右,如果出现意外(我们的app被拒了一次),一次意外加一周,我们的app除去圣诞大概在23天左右审核通过了。
感谢DCloud-App导师,感谢DCloud-MUI-CHB的帮助。
以下接着废话,蛋疼的是审核时间太长,android已经更新了两个版本,所以要在下个版本进行同步了。
中间多少汗和泪就不说了,走这条路确实辛苦,但是也有很多收获,希望大家多多交流,一起进步,活跃在论坛的各个角落。
我们的网址是(www.dtcash.com),论坛里有网站方面的高手可以加我qq聊聊最新的一些技术 我的qq是524014724
通过native.js调用系统分享 - 示例
更新:目前plus.share已经实现了对系统分享的调用。已无必要使用Native.js调用系统分享。参考http://www.html5plus.org/doc/zh_cn/share.html#plus.share.sendWithSystem
============================================================================
先说明,我对原生只是有一点点了解。我的目的是教大家,希望大家也可以自己写native.js。
前几天我问为什么不集成 Intent.ACTION_SEND 分享,@DCloud_heavensoft 说官方刚好正在做。
今晚读了一下:
http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/114
http://www.dcloud.io/docs/api/zh_cn/android.shtml
对比了一下示例和网上找的原生代码,试着捣鼓,也捣鼓出来了。
二楼放代码,三楼放教程。
二楼不支持MD,那这里更新好了,直接拿去用就行了
function share(shareTip,shareText){ var Context = plus.android.importClass("android.content.Intent"); var Main = plus.android.runtimeMainActivity(); var shareIntent=new Context(Context.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(Context.EXTRA_TEXT, shareText); Main.startActivity(Context.createChooser(shareIntent,shareTip)); } //调用 share('分享到...','要分享的文本');
带注释
function share(shareTip,shareText){
//导入Java类对象
var Context = plus.android.importClass("android.content.Intent");
//获取应用主Activity
var Main = plus.android.runtimeMainActivity();
//将类Context的这个行为(Action)ACTION_SEND,赋给shareIntent
var shareIntent=new Context(Context.ACTION_SEND);
//***以下两种写法是一样的
//plus.android.invoke(shareIntent,"setType","text/plain");
//plus.android.invoke(shareIntent,"putExtra",Context.EXTRA_TEXT,shareText);
//设置分享类型
shareIntent.setType("text/plain");
//设置分享文本
shareIntent.putExtra(Context.EXTRA_TEXT, shareText);
//***以上两种写法是一样的
//指定分享的包名
//shareIntent.setPackage('com.tencent.mm',);
Main.startActivity(Context.createChooser(shareIntent,shareTip));
}
原生代码这样写,大家对比下,就发现不难懂,字符对应上
Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent,'send to...'));
更新:目前plus.share已经实现了对系统分享的调用。已无必要使用Native.js调用系统分享。参考http://www.html5plus.org/doc/zh_cn/share.html#plus.share.sendWithSystem
============================================================================
先说明,我对原生只是有一点点了解。我的目的是教大家,希望大家也可以自己写native.js。
前几天我问为什么不集成 Intent.ACTION_SEND 分享,@DCloud_heavensoft 说官方刚好正在做。
今晚读了一下:
http://ask.dcloud.net.cn/docs/#http://ask.dcloud.net.cn/article/114
http://www.dcloud.io/docs/api/zh_cn/android.shtml
对比了一下示例和网上找的原生代码,试着捣鼓,也捣鼓出来了。
二楼放代码,三楼放教程。
二楼不支持MD,那这里更新好了,直接拿去用就行了
function share(shareTip,shareText){ var Context = plus.android.importClass("android.content.Intent"); var Main = plus.android.runtimeMainActivity(); var shareIntent=new Context(Context.ACTION_SEND); shareIntent.setType("text/plain"); shareIntent.putExtra(Context.EXTRA_TEXT, shareText); Main.startActivity(Context.createChooser(shareIntent,shareTip)); } //调用 share('分享到...','要分享的文本');
带注释
function share(shareTip,shareText){
//导入Java类对象
var Context = plus.android.importClass("android.content.Intent");
//获取应用主Activity
var Main = plus.android.runtimeMainActivity();
//将类Context的这个行为(Action)ACTION_SEND,赋给shareIntent
var shareIntent=new Context(Context.ACTION_SEND);
//***以下两种写法是一样的
//plus.android.invoke(shareIntent,"setType","text/plain");
//plus.android.invoke(shareIntent,"putExtra",Context.EXTRA_TEXT,shareText);
//设置分享类型
shareIntent.setType("text/plain");
//设置分享文本
shareIntent.putExtra(Context.EXTRA_TEXT, shareText);
//***以上两种写法是一样的
//指定分享的包名
//shareIntent.setPackage('com.tencent.mm',);
Main.startActivity(Context.createChooser(shareIntent,shareTip));
}
原生代码这样写,大家对比下,就发现不难懂,字符对应上
Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent,'send to...'));
收起阅读 »
mui集成iscroll 5 以及下拉,上拉刷新
由于mui中自带的下拉组件存在bug,一个项目中无法有多个,因此改造了iscroll5作为下拉刷新的组件,以下是代码,请参考。
首先是页面布局,iscroll的推荐的wrapper和scroller两个div,也使用了mui的一些样式。
<div id="wrapper" class="mui-content mui-iscroll-wrapper">
<div id="scroller">
<div id="pullDown" class="ub ub-pc c-gra">
<div id="pullDownIcon"></div>
<div id="pullDownLabel">下拉刷新</div>
</div>
<ul class="mui-table-view mui-table-view-chevron" id="dataList"></ul>
<div id="pullUp" class="ub ub-pc c-gra">
<div id="pullUpIcon"></div>
<div id="pullUpLabel">上拉显示更多...</div>
</div>
</div>
</div>
样式的css,主要是下拉和上拉以后的一些样式定义,比较简陋
<style>
#wrapper {
position: absolute;
top: 40px;
bottom: 0px;
left: 0;
width: 100%;
background: #ccc;
overflow: hidden;
}
#pullDown,
#pullUp {
height: 40px;
line-height: 40px;
padding: 5px 10px;
font-weight: bold;
font-size: 14px;
color: #888;
}
#pullDown .pullDownIcon,
#pullUp .pullUpIcon {
display: block;
float: left;
width: 40px;
height: 40px;
background: url(img/pull-icon@2x.png) 0 0 no-repeat;
-webkit-background-size: 40px 80px;
background-size: 40px 80px;
-webkit-transition-property: -webkit-transform;
-webkit-transition-duration: 250ms;
}
#pullDown .pullDownIcon {
-webkit-transform: rotate(0deg) translateZ(0);
}
#pullUp .pullUpIcon {
-webkit-transform: rotate(-180deg) translateZ(0);
}
#pullDown.flip .pullDownIcon {
-webkit-transform: rotate(-180deg) translateZ(0);
}
#pullUp.flip .pullUpIcon {
-webkit-transform: rotate(0deg) translateZ(0);
}
#pullDown.loading .pullDownIcon,
#pullUp.loading .pullUpIcon {
background-position: 0 100%;
-webkit-transform: rotate(0deg) translateZ(0);
-webkit-transition-duration: 0ms;
-webkit-animation-name: loading;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
.-webkit-keyframes loading {
from {
-webkit-transform: rotate(0deg)translateZ(0);
}
.to {
-webkit-transform: rotate(360deg) translateZ(0);
}
}
</style>
关键的js代码
var firstresult = 0;
var pagesize = 20;
var stocktype = 0;
var myScroll;
var pullDownEl, pullDownL;
var pullDownc, pullUpc;
var pullUpEl, pullUpL;
var Downcount = 0,
Upcount = 0;
var loadingStep = 0; //加载状态0默认,1显示加载状态,2执行加载数据,只有当为0时才能再次加载,这是防止过快拉动刷新
function pullDownAction() { //下拉事件
setTimeout(function() {
var el, li, i;
//plus.nativeUI.showWaiting();
console.log('触发了下拉更多');
removeClass(pullDownEl, 'loading');
pullDownL.innerHTML = '下拉显示更多...';
pullDownEl['class'] = pullDownEl.className;
pullDownEl.className = '';
pullDownEl.style.display = 'none';
initData(stocktype);
loadingStep = 0;
//plus.nativeUI.closeWaiting();
}, 1000); //1秒
}
function pullUpAction() { //上拉事件
setTimeout(function() {
var el, li, i;
console.log('出发了上拉刷新事件');
removeClass(pullUpEl, 'loading');
pullUpL.innerHTML = '上拉显示更多...';
pullUpEl['class'] = pullUpEl.className;
pullUpEl.className = '';
pullUpEl.style.display = 'none';
nextPage(stocktype);
//myScroll.refresh();
loadingStep = 0;
}, 1000);
}
function loaded() {
pullDownEl = document.getElementById('pullDown');
pullDownL = document.getElementById('pullDownLabel');
pullDownEl['class'] = pullDownEl.className;
pullDownEl.className = '';
pullDownEl.style.display = 'NONE';
pullUpEl = document.getElementById('pullUp');
pullUpL = document.getElementById('pullUpLabel');
pullUpEl['class'] = pullUpEl.className;
pullUpEl.style.display = 'NONE';
myScroll = new IScroll('#wrapper', {
probeType: 2, //probeType:1对性能没有影响。在滚动事件被触发时,滚动轴是不是忙着做它的东西。probeType:2总执行滚动,除了势头,反弹过程中的事件。这类似于原生的onscroll事件。probeType:3发出的滚动事件与到的像素精度。注意,滚动被迫requestAnimationFrame(即:useTransition:假)。
scrollbars: true, //有滚动条
mouseWheel: true, //允许滑轮滚动
fadeScrollbars: true, //滚动时显示滚动条,默认影藏,并且是淡出淡入效果
bounce: true, //边界反弹
interactiveScrollbars: true, //滚动条可以拖动
shrinkScrollbars: 'scale', // 当滚动边界之外的滚动条是由少量的收缩。'clip' or 'scale'.
click: true, // 允许点击事件
keyBindings: true, //允许使用按键控制
momentum: true // 允许有惯性滑动
});
//滚动时
myScroll.on('scroll', function() {
if (loadingStep == 0 && !pullDownEl.className.match('flip|loading') && !pullUpEl.className.match('flip|loading')) {
if (this.y > 5) {
//下拉刷新效果
pullDownEl.className = pullUpEl['class'];
pullDownEl.style.display = '';
myScroll.refresh();
pullDownEl.className += 'flip';
pullDownL.innerHTML = '准备刷新...';
loadingStep = 1;
} else if (this.y < (this.maxScrollY - 5)) {
//上拉刷新效果
pullUpEl.className = pullUpEl['class'];
pullUpEl.style.display = '';
myScroll.refresh();
pullUpEl.className += 'flip';
pullUpL.innerHTML = '准备刷新...';
loadingStep = 1;
}
}
});
//滚动完毕
myScroll.on('scrollEnd', function() {
if (loadingStep == 1) {
if (pullUpEl.className.match('flip|loading')) {
removeClass(pullUpEl, 'flip');
addClass(pullUpEl, 'loading');
pullUpL.innerHTML = 'Loading...';
loadingStep = 2;
pullUpAction();
} else if (pullDownEl.className.match('flip|loading')) {
removeClass(pullDownEl, 'flip');
addClass(pullDownEl, 'loading');
pullDownL.className = 'Loading...';
loadingStep = 2;
pullDownAction();
}
}
});
//初始化数据
initData();
}
function initData() {
firstresult = 0;
getData('0', stocktype);
document.getElementById("dataList").innerHTML ='';
//refresh
myScroll.refresh();
}
function nextPage() {
firstresult += pagesize;
getData('1', stocktype);
myScroll.refresh();
}
function getData(flag) {
var url = ‘’;
JSONP({
url: url,
data: {
firstresult: firstresult,
maxcount: pagesize
},
success: function(data) {
var source = document.getElementById("contact-template").innerHTML;
var template = Handlebars.compile(source);
var wos = {
wos: data.result
};
if (flag == '1') {
document.getElementById("dataList").innerHTML += template(wos);
} else {
document.getElementById("dataList").innerHTML = template(wos);
}
},
error: function(data) {
console.log(objToString(data));
}
});
}
项目用了handlerbars。
由于mui中自带的下拉组件存在bug,一个项目中无法有多个,因此改造了iscroll5作为下拉刷新的组件,以下是代码,请参考。
首先是页面布局,iscroll的推荐的wrapper和scroller两个div,也使用了mui的一些样式。
<div id="wrapper" class="mui-content mui-iscroll-wrapper">
<div id="scroller">
<div id="pullDown" class="ub ub-pc c-gra">
<div id="pullDownIcon"></div>
<div id="pullDownLabel">下拉刷新</div>
</div>
<ul class="mui-table-view mui-table-view-chevron" id="dataList"></ul>
<div id="pullUp" class="ub ub-pc c-gra">
<div id="pullUpIcon"></div>
<div id="pullUpLabel">上拉显示更多...</div>
</div>
</div>
</div>
样式的css,主要是下拉和上拉以后的一些样式定义,比较简陋
<style>
#wrapper {
position: absolute;
top: 40px;
bottom: 0px;
left: 0;
width: 100%;
background: #ccc;
overflow: hidden;
}
#pullDown,
#pullUp {
height: 40px;
line-height: 40px;
padding: 5px 10px;
font-weight: bold;
font-size: 14px;
color: #888;
}
#pullDown .pullDownIcon,
#pullUp .pullUpIcon {
display: block;
float: left;
width: 40px;
height: 40px;
background: url(img/pull-icon@2x.png) 0 0 no-repeat;
-webkit-background-size: 40px 80px;
background-size: 40px 80px;
-webkit-transition-property: -webkit-transform;
-webkit-transition-duration: 250ms;
}
#pullDown .pullDownIcon {
-webkit-transform: rotate(0deg) translateZ(0);
}
#pullUp .pullUpIcon {
-webkit-transform: rotate(-180deg) translateZ(0);
}
#pullDown.flip .pullDownIcon {
-webkit-transform: rotate(-180deg) translateZ(0);
}
#pullUp.flip .pullUpIcon {
-webkit-transform: rotate(0deg) translateZ(0);
}
#pullDown.loading .pullDownIcon,
#pullUp.loading .pullUpIcon {
background-position: 0 100%;
-webkit-transform: rotate(0deg) translateZ(0);
-webkit-transition-duration: 0ms;
-webkit-animation-name: loading;
-webkit-animation-duration: 2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
.-webkit-keyframes loading {
from {
-webkit-transform: rotate(0deg)translateZ(0);
}
.to {
-webkit-transform: rotate(360deg) translateZ(0);
}
}
</style>
关键的js代码
var firstresult = 0;
var pagesize = 20;
var stocktype = 0;
var myScroll;
var pullDownEl, pullDownL;
var pullDownc, pullUpc;
var pullUpEl, pullUpL;
var Downcount = 0,
Upcount = 0;
var loadingStep = 0; //加载状态0默认,1显示加载状态,2执行加载数据,只有当为0时才能再次加载,这是防止过快拉动刷新
function pullDownAction() { //下拉事件
setTimeout(function() {
var el, li, i;
//plus.nativeUI.showWaiting();
console.log('触发了下拉更多');
removeClass(pullDownEl, 'loading');
pullDownL.innerHTML = '下拉显示更多...';
pullDownEl['class'] = pullDownEl.className;
pullDownEl.className = '';
pullDownEl.style.display = 'none';
initData(stocktype);
loadingStep = 0;
//plus.nativeUI.closeWaiting();
}, 1000); //1秒
}
function pullUpAction() { //上拉事件
setTimeout(function() {
var el, li, i;
console.log('出发了上拉刷新事件');
removeClass(pullUpEl, 'loading');
pullUpL.innerHTML = '上拉显示更多...';
pullUpEl['class'] = pullUpEl.className;
pullUpEl.className = '';
pullUpEl.style.display = 'none';
nextPage(stocktype);
//myScroll.refresh();
loadingStep = 0;
}, 1000);
}
function loaded() {
pullDownEl = document.getElementById('pullDown');
pullDownL = document.getElementById('pullDownLabel');
pullDownEl['class'] = pullDownEl.className;
pullDownEl.className = '';
pullDownEl.style.display = 'NONE';
pullUpEl = document.getElementById('pullUp');
pullUpL = document.getElementById('pullUpLabel');
pullUpEl['class'] = pullUpEl.className;
pullUpEl.style.display = 'NONE';
myScroll = new IScroll('#wrapper', {
probeType: 2, //probeType:1对性能没有影响。在滚动事件被触发时,滚动轴是不是忙着做它的东西。probeType:2总执行滚动,除了势头,反弹过程中的事件。这类似于原生的onscroll事件。probeType:3发出的滚动事件与到的像素精度。注意,滚动被迫requestAnimationFrame(即:useTransition:假)。
scrollbars: true, //有滚动条
mouseWheel: true, //允许滑轮滚动
fadeScrollbars: true, //滚动时显示滚动条,默认影藏,并且是淡出淡入效果
bounce: true, //边界反弹
interactiveScrollbars: true, //滚动条可以拖动
shrinkScrollbars: 'scale', // 当滚动边界之外的滚动条是由少量的收缩。'clip' or 'scale'.
click: true, // 允许点击事件
keyBindings: true, //允许使用按键控制
momentum: true // 允许有惯性滑动
});
//滚动时
myScroll.on('scroll', function() {
if (loadingStep == 0 && !pullDownEl.className.match('flip|loading') && !pullUpEl.className.match('flip|loading')) {
if (this.y > 5) {
//下拉刷新效果
pullDownEl.className = pullUpEl['class'];
pullDownEl.style.display = '';
myScroll.refresh();
pullDownEl.className += 'flip';
pullDownL.innerHTML = '准备刷新...';
loadingStep = 1;
} else if (this.y < (this.maxScrollY - 5)) {
//上拉刷新效果
pullUpEl.className = pullUpEl['class'];
pullUpEl.style.display = '';
myScroll.refresh();
pullUpEl.className += 'flip';
pullUpL.innerHTML = '准备刷新...';
loadingStep = 1;
}
}
});
//滚动完毕
myScroll.on('scrollEnd', function() {
if (loadingStep == 1) {
if (pullUpEl.className.match('flip|loading')) {
removeClass(pullUpEl, 'flip');
addClass(pullUpEl, 'loading');
pullUpL.innerHTML = 'Loading...';
loadingStep = 2;
pullUpAction();
} else if (pullDownEl.className.match('flip|loading')) {
removeClass(pullDownEl, 'flip');
addClass(pullDownEl, 'loading');
pullDownL.className = 'Loading...';
loadingStep = 2;
pullDownAction();
}
}
});
//初始化数据
initData();
}
function initData() {
firstresult = 0;
getData('0', stocktype);
document.getElementById("dataList").innerHTML ='';
//refresh
myScroll.refresh();
}
function nextPage() {
firstresult += pagesize;
getData('1', stocktype);
myScroll.refresh();
}
function getData(flag) {
var url = ‘’;
JSONP({
url: url,
data: {
firstresult: firstresult,
maxcount: pagesize
},
success: function(data) {
var source = document.getElementById("contact-template").innerHTML;
var template = Handlebars.compile(source);
var wos = {
wos: data.result
};
if (flag == '1') {
document.getElementById("dataList").innerHTML += template(wos);
} else {
document.getElementById("dataList").innerHTML = template(wos);
}
},
error: function(data) {
console.log(objToString(data));
}
});
}
项目用了handlerbars。
收起阅读 »怎么解决input输入汉字时点击汉字执行某事件
var bind_name = "input";//定义所要绑定的事件名称
if (navigator.userAgent.indexOf("MSIE") != -1)
bind_name = "propertychange";//判断是否为IE内核 IE内核的事件名称要改为propertychange
/输入框键盘离开事件绑定/
$(".className").bind(bind_name, function ()
{
//事件
});
var bind_name = "input";//定义所要绑定的事件名称
if (navigator.userAgent.indexOf("MSIE") != -1)
bind_name = "propertychange";//判断是否为IE内核 IE内核的事件名称要改为propertychange
/输入框键盘离开事件绑定/
$(".className").bind(bind_name, function ()
{
//事件
});
Webview窗口设置遮罩层
在Webview窗口中如果存在子Webview的情况下,使用html中的css来做页面遮罩无法覆盖子Webview,为了解决此问题,WebviewStyle对象添加mask属性,用于设置Webview窗口的遮罩层。
mask属性值为字符串类型,可取值:
- rgba字符串,定义纯色遮罩层样式,如"rgba(0,0,0,0.5)";
- “none",表示不使用遮罩层。
Webview的遮罩层会覆盖Webview中所有内容(包括子Webview),并且截获Webview窗口的所有触屏事件。此时Webview窗口的点击操作会触发maskClick事件。
使用方法如下:
// 创建Webview窗口带遮罩层
var wd=plus.webview.create('http://www.dcloud.io/','dcloud',{mask:'rgba(0,0,0,0.5)'});
wd.show();
// 动态修改Webview窗口的遮罩层
var ws=plus.webview.currentWebview();
ws.setStyle({mask:"rgba(0,0,0,0.5)"});
// 用户点击Webview窗口后不显示遮罩层
ws.addEventListener("maskClick",function(){
ws.setStyle({mask:"none"});
},false);
注意:
- 显示遮罩层后仍然不会影响JS的执行;
- 在Android平台显示遮罩层后仍然可监听到backbutton事件;
- 在iOS平台显示遮罩层后仍然可以操作侧滑返回。
在Webview窗口中如果存在子Webview的情况下,使用html中的css来做页面遮罩无法覆盖子Webview,为了解决此问题,WebviewStyle对象添加mask属性,用于设置Webview窗口的遮罩层。
mask属性值为字符串类型,可取值:
- rgba字符串,定义纯色遮罩层样式,如"rgba(0,0,0,0.5)";
- “none",表示不使用遮罩层。
Webview的遮罩层会覆盖Webview中所有内容(包括子Webview),并且截获Webview窗口的所有触屏事件。此时Webview窗口的点击操作会触发maskClick事件。
使用方法如下:
// 创建Webview窗口带遮罩层
var wd=plus.webview.create('http://www.dcloud.io/','dcloud',{mask:'rgba(0,0,0,0.5)'});
wd.show();
// 动态修改Webview窗口的遮罩层
var ws=plus.webview.currentWebview();
ws.setStyle({mask:"rgba(0,0,0,0.5)"});
// 用户点击Webview窗口后不显示遮罩层
ws.addEventListener("maskClick",function(){
ws.setStyle({mask:"none"});
},false);
注意:
- 显示遮罩层后仍然不会影响JS的执行;
- 在Android平台显示遮罩层后仍然可监听到backbutton事件;
- 在iOS平台显示遮罩层后仍然可以操作侧滑返回。