HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

MUI的TAP事件在部分手机上会执行2次

已经验证HBuilder 版本 HBuilder 6.9.2.201601052351

MUI框架的事件tap在很多机器上都会被执行2次,换成click事件问题立即解决。
绝对不是两个窗体或者2次绑定引起的。已经在INSPECT里面调试过了。只有一个窗体实例,元素上也只有1个TAP监听。

我一直要求员工都用MUI的TAP事件。例如用TAP打开一个窗口。造成窗口都要闪烁2次,我原来以为是加速造成,结果发现完全是TAP引起的。。一次偶然,用TAP事件上,绑定了一个plus.nativeUI.alert,结果弹了2次框,我这才发现这个问题。。立即把所有TAP都改成CLICK了,结果所有因2次执行引起的闪烁全部消失。

以上问题不是在全部机器上都出现。。我用自己的NOTE5出现,用一个华为的手机出现。。有些小米手机出现,有些不出现。。未深究TAP的JS代码,有时间多的高人看看有没有更好的解决方案。

继续阅读 »

已经验证HBuilder 版本 HBuilder 6.9.2.201601052351

MUI框架的事件tap在很多机器上都会被执行2次,换成click事件问题立即解决。
绝对不是两个窗体或者2次绑定引起的。已经在INSPECT里面调试过了。只有一个窗体实例,元素上也只有1个TAP监听。

我一直要求员工都用MUI的TAP事件。例如用TAP打开一个窗口。造成窗口都要闪烁2次,我原来以为是加速造成,结果发现完全是TAP引起的。。一次偶然,用TAP事件上,绑定了一个plus.nativeUI.alert,结果弹了2次框,我这才发现这个问题。。立即把所有TAP都改成CLICK了,结果所有因2次执行引起的闪烁全部消失。

以上问题不是在全部机器上都出现。。我用自己的NOTE5出现,用一个华为的手机出现。。有些小米手机出现,有些不出现。。未深究TAP的JS代码,有时间多的高人看看有没有更好的解决方案。

收起阅读 »

【分享】常见字符集,字符编码编码和相互之间的转换以及Base64加密

技术分享 base64 字符编码

最近在用JS时,涉及到了不同编码之间的转换.于是汇总了一些网上的资料,整合成了自己的文档.

知识点涉及:
1.字符编码基础,几种常见字符编码的基本概念

  1. 不同编码之间的转换,如UTF-8转UTF-16,如UTF-16转GBK;
  2. Base64加密,GBK型与UTF-8型加密等
  3. 示例demo(js实现),比如如何用js将utf-16编码(js内置编码)转为UTF-8和GBK;比如如何将UTF-16编码的字符串(js内部的字符串)进行base64GBK和UTF-8编码

基础知识:(感谢@maq的提醒,这里普及下,字符集和字符编码的区别)

字符集(Charset):是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间建立对应关系,它是信息处理的一项基本技术。通常人们用符号集合(一般情况下就是文字)来表达信息。而以计算机为基础的信息处理系统则是利用元件(硬件)不同状态的组合来存储和处理信息的。元件不同状态的组合能代表数字系统的数字,因此字符编码就是将符号转换为计算机可以接受的数字系统的数,称为数字代码

常用字符集和字符编码

常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。经常说的GB2312即是字符集也是字符编码,所以经常将字符集和字符编码混着说.
参考来源:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

注:原文是在csdn博客上的,这里就不重复了.直接给出链接.(里面包含demo)

http://blog.csdn.net/u010979495/article/details/50601511

继续阅读 »

最近在用JS时,涉及到了不同编码之间的转换.于是汇总了一些网上的资料,整合成了自己的文档.

知识点涉及:
1.字符编码基础,几种常见字符编码的基本概念

  1. 不同编码之间的转换,如UTF-8转UTF-16,如UTF-16转GBK;
  2. Base64加密,GBK型与UTF-8型加密等
  3. 示例demo(js实现),比如如何用js将utf-16编码(js内置编码)转为UTF-8和GBK;比如如何将UTF-16编码的字符串(js内部的字符串)进行base64GBK和UTF-8编码

基础知识:(感谢@maq的提醒,这里普及下,字符集和字符编码的区别)

字符集(Charset):是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。即在符号集合与数字系统之间建立对应关系,它是信息处理的一项基本技术。通常人们用符号集合(一般情况下就是文字)来表达信息。而以计算机为基础的信息处理系统则是利用元件(硬件)不同状态的组合来存储和处理信息的。元件不同状态的组合能代表数字系统的数字,因此字符编码就是将符号转换为计算机可以接受的数字系统的数,称为数字代码

常用字符集和字符编码

常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。经常说的GB2312即是字符集也是字符编码,所以经常将字符集和字符编码混着说.
参考来源:http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html

注:原文是在csdn博客上的,这里就不重复了.直接给出链接.(里面包含demo)

http://blog.csdn.net/u010979495/article/details/50601511

收起阅读 »

webview页面中的子webview之间相互操作

今天开发中遇到A 页面中嵌套了B页面,然后B页面中的数据收到的值变化时,切A页面的稿件的参数也要变化见图!
开始一直通过plus.webview.getWebviewById('URL').evalJS();去操控A页面的函数方法,但是一直不可以,拿不到A的webview,后来去认
真看了API文档后才发现自己进入到了一个误区!
因为是嵌套的webview所以,我们可以先拿到当前我们操作的这个页面,就是我所谓的B页面的webview;
var centerView= plus.webview.currentWebview();
然后我们再去拿到B页面的父页面,就是所谓的A webview页面;
var par=centerView.parent();
关于parent这个方法参考地址:http://www.dcloud.io/docs/api/zh_cn/webview.shtml#plus.webview.WebviewObject.parent
这样我们就拿到了最外层的的父webview,然后操控par.evalJS();就可以执行A页面的函数了!
虽然我的描述方式差,逻辑差,文笔也差,这点东西也算不上什么,给予那些正需要的人的一点帮助吧!因为我就是没有在论坛找到相应
的解决办法(也可能有,但是我没有搜索对关键词,其次就是这个网站的搜索太垃圾了!嘻嘻),才去看文档的,不过建议还是多看文档!

继续阅读 »

今天开发中遇到A 页面中嵌套了B页面,然后B页面中的数据收到的值变化时,切A页面的稿件的参数也要变化见图!
开始一直通过plus.webview.getWebviewById('URL').evalJS();去操控A页面的函数方法,但是一直不可以,拿不到A的webview,后来去认
真看了API文档后才发现自己进入到了一个误区!
因为是嵌套的webview所以,我们可以先拿到当前我们操作的这个页面,就是我所谓的B页面的webview;
var centerView= plus.webview.currentWebview();
然后我们再去拿到B页面的父页面,就是所谓的A webview页面;
var par=centerView.parent();
关于parent这个方法参考地址:http://www.dcloud.io/docs/api/zh_cn/webview.shtml#plus.webview.WebviewObject.parent
这样我们就拿到了最外层的的父webview,然后操控par.evalJS();就可以执行A页面的函数了!
虽然我的描述方式差,逻辑差,文笔也差,这点东西也算不上什么,给予那些正需要的人的一点帮助吧!因为我就是没有在论坛找到相应
的解决办法(也可能有,但是我没有搜索对关键词,其次就是这个网站的搜索太垃圾了!嘻嘻),才去看文档的,不过建议还是多看文档!

收起阅读 »

M站、WAP站改造流应用指南

流应用

在wap2app推出后,开发者根据wap2app即可快速完成app及流应用提交。
具体见http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/13425

============以下内容已过期=================

背景和问题

流应用本身是可以达到原生app的体验的,从应用体验来讲,c/s方式比b/s方式体验更好:

  1. c/s的首页启动更快;
  2. c/s的页面转场更快;
  3. c/s具有脱线访问性。

所以如果开发新app,我们建议开发者使用mui框架,开发一次多端发布,流应用、wap、app都自动生成。
不过实际情况中大量开发商已经有了wap站和原生app,但仍需要制作流应用,那么此时他们需要一种在开发成本和用户体验之间取得平衡的一种方法。

如何基于m站快速改造出流应用,体验还不错,并维持版本的统一更新发布,这是本文讲解的内容。

前提准备

m站的体验本身要好,控件风格app化而不是浏览器化。
反面例子:有的m站的列表仍然是超链接方式,而不是list方式,体验就很差。举例:http://www.beijing.gov.cn/sjbsy/
正面例子:卖座电影
这些链接如果在pc上打开,请在浏览器控制台里调整为手机模式观看。
当然大多数m站的实际状态是处于2者之间的。

在改造方面,有两种大的思路。

  1. 修改m站源码,根据ua动态引用增强的js,发现ua包含html5plus或stream时,动态引入一些js,实现对HTML5+扩展能力的调用
  2. 不修改m站源码,利用wap2app框架进行wap站配置,完成增强体验,wap2app教程建议从《wap2app快速体验》开始入手。

因为wap2app相对成熟,有完整的教程,本文不做过多解释,重点讲解第一种思路,即:修改m站源码,实现流应用的发布。

改造工作

  1. 首页
    如果是直接改wap站源码,那么在首页引入一个streamapp.js的文件,然后在这个js里编写代码控制整个app的体验强化。
    同时注意在这个js要拦截所有页面切换请求,点击首页后的所有窗体切换均为新开webview,保证首页的webview一直存在,否则强化的js文件也会不见掉,导致无法再生效。

    我们需要在HBuilder里新建一个移动app项目,才能提交流应用。新建工程时注意调整manifest.json:
    a) 项目首页就是wap站地址
    b) 项目的manifest.json 加 popGesture":"close"
    c) 控制页create显示webview时,webview style设置popGesture为none
    不调整的话,在iOS上左滑屏幕返回时会露出空白的控制webview。
    d) 强制打开硬件加速,具体参考http://ask.dcloud.net.cn/article/94

  2. 登陆注册体验
    很多wap站的用户登陆cookie有效期只有一周,一周后需要用户重新输入用户名密码,app可不会这么设计。如果用户在桌面安装了一个流应用,就不应该让他一周后重新输入用户名密码登陆。开发者可根据流应用引擎的ua(包括steamapp)判断,设置流应用的cookie有效期为永久。
    还有很多wap站在登陆时需要输入验证码,这都是比较糟糕的体验,同样也需要判断ua,去掉验证码。

    注册优化也是很重要的问题,对于技术人员而言,未必关心从app激活到注册之间的折损,但产品负责人和运营是非常关心这个数据的。
    流应用提供了优化注册折损的方案,通过plus.oauth,可以调用一键登入,如果wap站本身有单点登陆接口,尽量支持好流应用的一键登陆。
    尤其是用户注册基数不大或品牌不强的新app,如果用户体验产品或消费下单前有比较高的注册门槛,很容易折损流失。
    需要开发单点登陆的开发商,除了客户端调用plus.oauth外还需要服务器对接。请加入底部显示的流应用qq群,与管理员沟通,我们会单独提供服务器端对接的文档和api。

  3. back处理
    浏览器的back是非常难用的,它的顺序是用户访问页面的先后顺序,而不是app的逻辑顺序,流应用的back逻辑需要单独处理。
    Android的back按键需要通过plus.key来监听和处理,不能简单的走网页的前进后退,要按app的逻辑处理后退。
    比如,页面A跳转到B时发现需要登陆,进入了登陆页C,登陆后又进入了页面B,此时点back,要求回页面A,而不是后退到登陆页。
    再比如,从首页点了一个栏目1,back回首页,然后点了栏目2,再back回首页,此时按back,应该提醒是否退出app而不是后退到栏目1里。一般在首页里按back一定是提醒退出app而不是走浏览器的history back。
    另外注意有的列表页面滚动后,点一个列表项进入下一个页面,点back回到刚才的列表页面,但滚动条跑最顶部了,这种情况体验太差,要处理。
    流应用需要在首页监听back按键,设计退出逻辑,比如连续按2下back退出,或者按一下back弹出confirm框,询问用户是否退出。
    如果用户是push或wap导流来的,那么退出时,应提示用户下次可以从桌面直接启动,不然会有不少用户不知道桌面多了一个图标。
    除了页面切换的back,当页面中出现一个div选择层,此时点back应该是关闭选择层而不是整体后退。
    参考http://www.html5plus.org/doc/zh_cn/key.html

  4. 页面切换等待
    页面切换不能白屏,不能依赖浏览器的进度条,切换过程要有自己的模态进度指示如转雪花,避免在新页面切换完成前用户连续点击引发问题。
    参考http://www.html5plus.org/doc/zh_cn/nativeui.html#plus.nativeUI.Waiting
    由于wap网页的载入速度较慢,一般的体验优化做法是在首页注入的控制js里绘制一个原生的title,使用plus.nativeobj里的原生view绘制title,可以快速展现title出来,然后title下面加载wap页面。

  5. 去wap的展现形式
    有些wap页面底部有电脑版、手机版,还有版权或icp信息,还有原生app的下载banner,这都不是app感觉,都需要去掉;实现方案参考:如何在流应用环境下去wap化展现

  6. 原生定位
    如果业务涉及定位,把HTML5的定位改为plus的原生定位。
    HTML5的定位会弹框让用户选择是否允许某网页访问位置,体验太差,而且HTML5的定位速度、精度都不够。改调原生定位又快又准又不弹框。
    流应用提供的定位是高德定位的坐标系。
    在物流相关业务里,配送地址可以通过流应用的api查询到街道信息,可以自动填写到送货地址的输入框中,避免用户敲太多字。
    用户有可能未开启手机的gps或未给应用赋予定位权限,对于强定位需求的app,需要写代码调用流应用的api判断并提醒用户开启gps或相应权限,在弹出框跳转到系统设置里开启定位或赋权并返回后,应自动刷新重调定位api。
    参考:http://html5plus.org/doc/zh_cn/geolocation.html
    参考:http://ask.dcloud.net.cn/question/11890

  7. 原生支付
    流应用提供了原生的支付宝支付和微信支付能力,开发商可参考流应用提供的原生支付api,改进支付体验。
    目前支付宝和微信支付,都支持通过h5的schemes调起本机的原生app进行原生支付,体验比较好,wap站改造量也比较小。
    关于微信的h5支付,需要开发商向微信申请微信wap支付资格,有了该资格,可以在HTML5页面里直接调起微信的原生支付。
    微信wap支付其实就是微信公众号里的支付方式,可以放大到不止是在微信浏览器里可支付,在外部浏览器里也可以再调起微信来完成支付。
    目前大大小小很多开发商都申请到了wap支付资格,比如京东、唯品会、卖座电影、蛋糕叔叔…
    开发商之前的M站的支付宝支付都是wap支付,要输入较长的用户名、密码,体验差、折损高。
    目前看到的数据是用户点微信和支付宝的占比基本是55开,这两种支付方式都应该优化到位。

  8. 硬件加速
    如果是使用控制webview创建显示webview的方式做流应用,注意在显示webview创建时对webview开启硬件加速,以提升页面滚动流畅度。
    参考http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewStyle 里的hardwareAccelerated

  9. 网络异常处理
    网络异常导致页面打不开或ajax请求失败,需要单独控制。因为在浏览器里有工具栏和刷新按钮,用户可以自己刷新,但在流应用里没有刷新按钮。而且一旦进入404界面会很难看。
    推荐的体验是流应用的本地代码有网络监听判断,如果用户没有开启网络,则应该提醒用户开启,如果用户网络异常,应弹出提示框,让用户选择重试或退出。
    参考 http://www.html5plus.org/doc/zh_cn/device.html#plus.networkinfo
    参考 http://ask.dcloud.net.cn/question/1475

  10. Titile处理
    有些wap页面没有title或title不能固定,在全屏app界面里不应该出现这种情况,需要每个界面都有title、并且保持固定在顶部。除首页外每个界面的左上角都应该有返回按钮,不能仅依赖back按键来返回。

  11. 桌面快捷方式修复
    桌面快捷方式驻留是流应用留存率的基础。可以从桌面直接启动才能增加次日或7日留存。
    用户可能会误删除桌面上的某流应用的快捷方式。所以需要app在关于界面或其他合适位置放置快捷方式修复的按钮。
    体验参考 大众点评外卖流应用的右上角关于按钮。
    代码参考:http://ask.dcloud.net.cn/article/406

  12. 打点统计
    流应用是可以采集imei的,流应用的统计不是按uv统计,而是按imei的激活统计。
    流应用启动后,应像App一样给后台App统计系统报数打点。
    DCloud给所有流应用开发商提供了数据报表,因为流应用客户端包的下载和更新是在我们的服务器上,并且每个流应用每次启动时会自动检查更新,所以我们可以给开发商完善的报表数据,包括下载、激活、日活、留存、总设备数以及下载来源分析,比如是搜索下载、快码下载、分享下载、wap导量下载、push下载...。DCloud还有订单回传接口,开发商调用后还可在DCloud提供的报表系统里看到订单统计。
    大开发商一般要求自己的后台也需要报数统计,并m站的uv统计是现成的。但是uv不如imei准,有些开发商发现自己统计的uv多于DCloud报表里提供的日活,建议开发商把uv统计里的cookie id值设为imei,通过plus.device取imei,这样开发商的uv和DCloud报表里的激活能对上。
    如果想采集本机是否安装了本公司的其他app产品或竞品的安装情况,也是可以采集的。
    参考:http://www.html5plus.org/doc/zh_cn/device.html
    参考:http://ask.dcloud.net.cn/question/7604

  13. 快码和直通车
    快码和分享直通车是流应用的重要功能,对于拉新和二次传播作用明显,建议使用。
    快码无需开发,在HBuilder的菜单发行里申请即可。
    这里是快码的介绍和申请指南:http://ask.dcloud.net.cn/article/492

    直通车需要开发,但社交直购等分享直通车的功能价值很明显。
    体验参考 大众点评外卖流应用的右上角关于按钮里的快码和饭馆分享里的分享直通车。
    视频参考:http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_r0171bswy6f.html
    代码参考 Hello H5+里的分享源代码。

  14. 其他细节
    如果涉及到照片选择上传、文件上传、摄像头麦克风控制,也请将HTML5的代码替换为HTML5+的代码,以得到更好的体验。
    参考:http://www.html5plus.org/doc/

关于一次开发多端发布

通过条件编译工具如glup,可以做到一套代码同时输出m站和流应用,避免多处维护业务逻辑变更的烦恼。
Mui框架本身是支持多端发布的,Hello mui是一个浏览器、流应用、Android app、iOS app一套代码多端均可使用的示例,可参考Hello mui的代码。

案例推荐

关于把M站改造为流应用,可以参考如下案例。

唯品会
唯品会是wap站改造流应用里做的体验较好的应用。
唯品会的业务特点决定了其页面里大量动态内容,其原生app里也有很多wap页面。
流应用版的唯品会和原生版的唯品会差异很小。
唯品会的快码
请使用360手助扫码体验

合作支持

对于有较大流量的wap站,可以发邮件到stream@dcloud.io,说明wap站地址和联系方式,我们可以提供电话咨询,协助快速完成转换。

继续阅读 »

在wap2app推出后,开发者根据wap2app即可快速完成app及流应用提交。
具体见http://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/13425

============以下内容已过期=================

背景和问题

流应用本身是可以达到原生app的体验的,从应用体验来讲,c/s方式比b/s方式体验更好:

  1. c/s的首页启动更快;
  2. c/s的页面转场更快;
  3. c/s具有脱线访问性。

所以如果开发新app,我们建议开发者使用mui框架,开发一次多端发布,流应用、wap、app都自动生成。
不过实际情况中大量开发商已经有了wap站和原生app,但仍需要制作流应用,那么此时他们需要一种在开发成本和用户体验之间取得平衡的一种方法。

如何基于m站快速改造出流应用,体验还不错,并维持版本的统一更新发布,这是本文讲解的内容。

前提准备

m站的体验本身要好,控件风格app化而不是浏览器化。
反面例子:有的m站的列表仍然是超链接方式,而不是list方式,体验就很差。举例:http://www.beijing.gov.cn/sjbsy/
正面例子:卖座电影
这些链接如果在pc上打开,请在浏览器控制台里调整为手机模式观看。
当然大多数m站的实际状态是处于2者之间的。

在改造方面,有两种大的思路。

  1. 修改m站源码,根据ua动态引用增强的js,发现ua包含html5plus或stream时,动态引入一些js,实现对HTML5+扩展能力的调用
  2. 不修改m站源码,利用wap2app框架进行wap站配置,完成增强体验,wap2app教程建议从《wap2app快速体验》开始入手。

因为wap2app相对成熟,有完整的教程,本文不做过多解释,重点讲解第一种思路,即:修改m站源码,实现流应用的发布。

改造工作

  1. 首页
    如果是直接改wap站源码,那么在首页引入一个streamapp.js的文件,然后在这个js里编写代码控制整个app的体验强化。
    同时注意在这个js要拦截所有页面切换请求,点击首页后的所有窗体切换均为新开webview,保证首页的webview一直存在,否则强化的js文件也会不见掉,导致无法再生效。

    我们需要在HBuilder里新建一个移动app项目,才能提交流应用。新建工程时注意调整manifest.json:
    a) 项目首页就是wap站地址
    b) 项目的manifest.json 加 popGesture":"close"
    c) 控制页create显示webview时,webview style设置popGesture为none
    不调整的话,在iOS上左滑屏幕返回时会露出空白的控制webview。
    d) 强制打开硬件加速,具体参考http://ask.dcloud.net.cn/article/94

  2. 登陆注册体验
    很多wap站的用户登陆cookie有效期只有一周,一周后需要用户重新输入用户名密码,app可不会这么设计。如果用户在桌面安装了一个流应用,就不应该让他一周后重新输入用户名密码登陆。开发者可根据流应用引擎的ua(包括steamapp)判断,设置流应用的cookie有效期为永久。
    还有很多wap站在登陆时需要输入验证码,这都是比较糟糕的体验,同样也需要判断ua,去掉验证码。

    注册优化也是很重要的问题,对于技术人员而言,未必关心从app激活到注册之间的折损,但产品负责人和运营是非常关心这个数据的。
    流应用提供了优化注册折损的方案,通过plus.oauth,可以调用一键登入,如果wap站本身有单点登陆接口,尽量支持好流应用的一键登陆。
    尤其是用户注册基数不大或品牌不强的新app,如果用户体验产品或消费下单前有比较高的注册门槛,很容易折损流失。
    需要开发单点登陆的开发商,除了客户端调用plus.oauth外还需要服务器对接。请加入底部显示的流应用qq群,与管理员沟通,我们会单独提供服务器端对接的文档和api。

  3. back处理
    浏览器的back是非常难用的,它的顺序是用户访问页面的先后顺序,而不是app的逻辑顺序,流应用的back逻辑需要单独处理。
    Android的back按键需要通过plus.key来监听和处理,不能简单的走网页的前进后退,要按app的逻辑处理后退。
    比如,页面A跳转到B时发现需要登陆,进入了登陆页C,登陆后又进入了页面B,此时点back,要求回页面A,而不是后退到登陆页。
    再比如,从首页点了一个栏目1,back回首页,然后点了栏目2,再back回首页,此时按back,应该提醒是否退出app而不是后退到栏目1里。一般在首页里按back一定是提醒退出app而不是走浏览器的history back。
    另外注意有的列表页面滚动后,点一个列表项进入下一个页面,点back回到刚才的列表页面,但滚动条跑最顶部了,这种情况体验太差,要处理。
    流应用需要在首页监听back按键,设计退出逻辑,比如连续按2下back退出,或者按一下back弹出confirm框,询问用户是否退出。
    如果用户是push或wap导流来的,那么退出时,应提示用户下次可以从桌面直接启动,不然会有不少用户不知道桌面多了一个图标。
    除了页面切换的back,当页面中出现一个div选择层,此时点back应该是关闭选择层而不是整体后退。
    参考http://www.html5plus.org/doc/zh_cn/key.html

  4. 页面切换等待
    页面切换不能白屏,不能依赖浏览器的进度条,切换过程要有自己的模态进度指示如转雪花,避免在新页面切换完成前用户连续点击引发问题。
    参考http://www.html5plus.org/doc/zh_cn/nativeui.html#plus.nativeUI.Waiting
    由于wap网页的载入速度较慢,一般的体验优化做法是在首页注入的控制js里绘制一个原生的title,使用plus.nativeobj里的原生view绘制title,可以快速展现title出来,然后title下面加载wap页面。

  5. 去wap的展现形式
    有些wap页面底部有电脑版、手机版,还有版权或icp信息,还有原生app的下载banner,这都不是app感觉,都需要去掉;实现方案参考:如何在流应用环境下去wap化展现

  6. 原生定位
    如果业务涉及定位,把HTML5的定位改为plus的原生定位。
    HTML5的定位会弹框让用户选择是否允许某网页访问位置,体验太差,而且HTML5的定位速度、精度都不够。改调原生定位又快又准又不弹框。
    流应用提供的定位是高德定位的坐标系。
    在物流相关业务里,配送地址可以通过流应用的api查询到街道信息,可以自动填写到送货地址的输入框中,避免用户敲太多字。
    用户有可能未开启手机的gps或未给应用赋予定位权限,对于强定位需求的app,需要写代码调用流应用的api判断并提醒用户开启gps或相应权限,在弹出框跳转到系统设置里开启定位或赋权并返回后,应自动刷新重调定位api。
    参考:http://html5plus.org/doc/zh_cn/geolocation.html
    参考:http://ask.dcloud.net.cn/question/11890

  7. 原生支付
    流应用提供了原生的支付宝支付和微信支付能力,开发商可参考流应用提供的原生支付api,改进支付体验。
    目前支付宝和微信支付,都支持通过h5的schemes调起本机的原生app进行原生支付,体验比较好,wap站改造量也比较小。
    关于微信的h5支付,需要开发商向微信申请微信wap支付资格,有了该资格,可以在HTML5页面里直接调起微信的原生支付。
    微信wap支付其实就是微信公众号里的支付方式,可以放大到不止是在微信浏览器里可支付,在外部浏览器里也可以再调起微信来完成支付。
    目前大大小小很多开发商都申请到了wap支付资格,比如京东、唯品会、卖座电影、蛋糕叔叔…
    开发商之前的M站的支付宝支付都是wap支付,要输入较长的用户名、密码,体验差、折损高。
    目前看到的数据是用户点微信和支付宝的占比基本是55开,这两种支付方式都应该优化到位。

  8. 硬件加速
    如果是使用控制webview创建显示webview的方式做流应用,注意在显示webview创建时对webview开启硬件加速,以提升页面滚动流畅度。
    参考http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewStyle 里的hardwareAccelerated

  9. 网络异常处理
    网络异常导致页面打不开或ajax请求失败,需要单独控制。因为在浏览器里有工具栏和刷新按钮,用户可以自己刷新,但在流应用里没有刷新按钮。而且一旦进入404界面会很难看。
    推荐的体验是流应用的本地代码有网络监听判断,如果用户没有开启网络,则应该提醒用户开启,如果用户网络异常,应弹出提示框,让用户选择重试或退出。
    参考 http://www.html5plus.org/doc/zh_cn/device.html#plus.networkinfo
    参考 http://ask.dcloud.net.cn/question/1475

  10. Titile处理
    有些wap页面没有title或title不能固定,在全屏app界面里不应该出现这种情况,需要每个界面都有title、并且保持固定在顶部。除首页外每个界面的左上角都应该有返回按钮,不能仅依赖back按键来返回。

  11. 桌面快捷方式修复
    桌面快捷方式驻留是流应用留存率的基础。可以从桌面直接启动才能增加次日或7日留存。
    用户可能会误删除桌面上的某流应用的快捷方式。所以需要app在关于界面或其他合适位置放置快捷方式修复的按钮。
    体验参考 大众点评外卖流应用的右上角关于按钮。
    代码参考:http://ask.dcloud.net.cn/article/406

  12. 打点统计
    流应用是可以采集imei的,流应用的统计不是按uv统计,而是按imei的激活统计。
    流应用启动后,应像App一样给后台App统计系统报数打点。
    DCloud给所有流应用开发商提供了数据报表,因为流应用客户端包的下载和更新是在我们的服务器上,并且每个流应用每次启动时会自动检查更新,所以我们可以给开发商完善的报表数据,包括下载、激活、日活、留存、总设备数以及下载来源分析,比如是搜索下载、快码下载、分享下载、wap导量下载、push下载...。DCloud还有订单回传接口,开发商调用后还可在DCloud提供的报表系统里看到订单统计。
    大开发商一般要求自己的后台也需要报数统计,并m站的uv统计是现成的。但是uv不如imei准,有些开发商发现自己统计的uv多于DCloud报表里提供的日活,建议开发商把uv统计里的cookie id值设为imei,通过plus.device取imei,这样开发商的uv和DCloud报表里的激活能对上。
    如果想采集本机是否安装了本公司的其他app产品或竞品的安装情况,也是可以采集的。
    参考:http://www.html5plus.org/doc/zh_cn/device.html
    参考:http://ask.dcloud.net.cn/question/7604

  13. 快码和直通车
    快码和分享直通车是流应用的重要功能,对于拉新和二次传播作用明显,建议使用。
    快码无需开发,在HBuilder的菜单发行里申请即可。
    这里是快码的介绍和申请指南:http://ask.dcloud.net.cn/article/492

    直通车需要开发,但社交直购等分享直通车的功能价值很明显。
    体验参考 大众点评外卖流应用的右上角关于按钮里的快码和饭馆分享里的分享直通车。
    视频参考:http://v.qq.com/boke/gplay/c17d8789e7dd8a208cd6e6189ae90664_nst000001qufah3_r0171bswy6f.html
    代码参考 Hello H5+里的分享源代码。

  14. 其他细节
    如果涉及到照片选择上传、文件上传、摄像头麦克风控制,也请将HTML5的代码替换为HTML5+的代码,以得到更好的体验。
    参考:http://www.html5plus.org/doc/

关于一次开发多端发布

通过条件编译工具如glup,可以做到一套代码同时输出m站和流应用,避免多处维护业务逻辑变更的烦恼。
Mui框架本身是支持多端发布的,Hello mui是一个浏览器、流应用、Android app、iOS app一套代码多端均可使用的示例,可参考Hello mui的代码。

案例推荐

关于把M站改造为流应用,可以参考如下案例。

唯品会
唯品会是wap站改造流应用里做的体验较好的应用。
唯品会的业务特点决定了其页面里大量动态内容,其原生app里也有很多wap页面。
流应用版的唯品会和原生版的唯品会差异很小。
唯品会的快码
请使用360手助扫码体验

合作支持

对于有较大流量的wap站,可以发邮件到stream@dcloud.io,说明wap站地址和联系方式,我们可以提供电话咨询,协助快速完成转换。

收起阅读 »

mui图片预览(perviewimage)的优化

图片预览

mui图片预览(perviewimage)的优化

更好的显示效果看这http://www.cnblogs.com/phillyx/p/5164231.html
主要对mui图片全屏预览插件做了以下三点补充
1.添加了预览图片文字说明,使用的时候需要添加以下cssDOM属性

            .mui-slider-img-content {  
                position: absolute;  
                bottom: 10px;  
                left: 10px;  
                right: 10px;  
                color: white;  
                text-align: center;  
                line-height: 21px  
            }
<img src="../images/yuantiao.jpg" data-preview-src="" data-preview-group="2" data-content="这里是文字说明"/>

2.如果图片过宽或过长,预加载图片(上一张或下一张)时,会和当前显示的图片重叠
原来的效果是这样

主要对缩放进行了更改

    proto._initImgData = function(itemData, imgEl) {  
        if (!itemData.sWidth) {  
            var img = itemData.el;  
            itemData.sWidth = img.offsetWidth;  
            itemData.sHeight = img.offsetHeight;  
            var offset = $.offset(img);  
            itemData.sTop = offset.top;  
            itemData.sLeft = offset.left;  
            //缩放判断,解决预加载图片时,图片过大,和当前显示图片重叠的问题  
            //未更改之前缩放比例能达到2.5倍以上  
            var scale = Math.max(itemData.sWidth / window.innerWidth, itemData.sHeight / window.innerHeight);  
            itemData.sScale = scale > 1 ? 0.977 : scale;  
        }  
        imgEl.style.webkitTransform = 'translate3d(0,0,0) scale(' + itemData.sScale + ')';  
    };

3.解决了预加载页面返回(mui.back)重新加载数据并打开时,预览无用的问题
主要应用场景是这样的:

  • view是预加载的,返回时view隐藏,DOM重置,
  • 如果不清除当前预览对象previmage的话,加载数据后打开当前页面,重新调用mui.previewImage()无效,依然是第一次的预览的DOM结果
  • 因为插件源码决定了该对象是不变的
    var previewImageApi = null;  
    $.previewImage = function(options) {  
        if (!previewImageApi) {  
            previewImageApi = new PreviewImage(options);  
        }  
        return previewImageApi;  
    };
  • 有朋友会问,为毛要预加载,为什么不通过loadurl或其他方式刷新页面(或DOM)?
  • 就为了优化性能,秒开页面,整个详情页的代码前前后后改了一个多星期
  • 我不可能因为插件的不完整而放弃优化的成果。
  • 所以就有了以下的代码
    //释放当前对象及清除DOM  
    proto.dispose = function() {  
        var prevdom = document.getElementById("__MUI_PREVIEWIMAGE");  
        prevdom && prevdom.parentNode.removeChild(prevdom);  
        previewImageApi = null;  
    };

具体代码在这https://github.com/phillyx/mui/blob/master/examples/hello-mui/examples/imageviewer.html

继续阅读 »

mui图片预览(perviewimage)的优化

更好的显示效果看这http://www.cnblogs.com/phillyx/p/5164231.html
主要对mui图片全屏预览插件做了以下三点补充
1.添加了预览图片文字说明,使用的时候需要添加以下cssDOM属性

            .mui-slider-img-content {  
                position: absolute;  
                bottom: 10px;  
                left: 10px;  
                right: 10px;  
                color: white;  
                text-align: center;  
                line-height: 21px  
            }
<img src="../images/yuantiao.jpg" data-preview-src="" data-preview-group="2" data-content="这里是文字说明"/>

2.如果图片过宽或过长,预加载图片(上一张或下一张)时,会和当前显示的图片重叠
原来的效果是这样

主要对缩放进行了更改

    proto._initImgData = function(itemData, imgEl) {  
        if (!itemData.sWidth) {  
            var img = itemData.el;  
            itemData.sWidth = img.offsetWidth;  
            itemData.sHeight = img.offsetHeight;  
            var offset = $.offset(img);  
            itemData.sTop = offset.top;  
            itemData.sLeft = offset.left;  
            //缩放判断,解决预加载图片时,图片过大,和当前显示图片重叠的问题  
            //未更改之前缩放比例能达到2.5倍以上  
            var scale = Math.max(itemData.sWidth / window.innerWidth, itemData.sHeight / window.innerHeight);  
            itemData.sScale = scale > 1 ? 0.977 : scale;  
        }  
        imgEl.style.webkitTransform = 'translate3d(0,0,0) scale(' + itemData.sScale + ')';  
    };

3.解决了预加载页面返回(mui.back)重新加载数据并打开时,预览无用的问题
主要应用场景是这样的:

  • view是预加载的,返回时view隐藏,DOM重置,
  • 如果不清除当前预览对象previmage的话,加载数据后打开当前页面,重新调用mui.previewImage()无效,依然是第一次的预览的DOM结果
  • 因为插件源码决定了该对象是不变的
    var previewImageApi = null;  
    $.previewImage = function(options) {  
        if (!previewImageApi) {  
            previewImageApi = new PreviewImage(options);  
        }  
        return previewImageApi;  
    };
  • 有朋友会问,为毛要预加载,为什么不通过loadurl或其他方式刷新页面(或DOM)?
  • 就为了优化性能,秒开页面,整个详情页的代码前前后后改了一个多星期
  • 我不可能因为插件的不完整而放弃优化的成果。
  • 所以就有了以下的代码
    //释放当前对象及清除DOM  
    proto.dispose = function() {  
        var prevdom = document.getElementById("__MUI_PREVIEWIMAGE");  
        prevdom && prevdom.parentNode.removeChild(prevdom);  
        previewImageApi = null;  
    };

具体代码在这https://github.com/phillyx/mui/blob/master/examples/hello-mui/examples/imageviewer.html

收起阅读 »

关于H5电子签名的实现。

最近一个项目需要客户在提交单据的时候,附带签名。度娘了一下。果然还是有这个JQuery插件的。学名:jSignature
好了,废话不多说。先来个截图(见附件)。这玩意功能还是比较强大的。支持各种设置和各种姿势的导出。可惜是在JQuery里的,得先引用JQuery.

                <script type="text/javascript" src="js/jquery.js"></script>  
        <script type="text/javascript" src="js/jSignature.min.js"></script>  
        <!--[if lt IE 9]>  
        <script type="text/javascript" src="js/flashcanvas.js"></script>  
        <![endif]-->

下面就简单了,给一个dom.比如这样的:

<div id="signature" style="height: 100%;"></div>

最后呢,就是初始化一下。可以这样的:

$(document).ready(function() {  
                $("#signature").jSignature()  
            });

要是想导出呢,这里是Base64,就要这样的:

var datapair = $("#signature").jSignature("getData", "image");  
                var array = datapair.splice(",");  
                mui.toast(array[1]);

好了,其他也就没什么 了。更多了解就去看 api 吧。
最后在附上js包,希望对大家有帮助。

继续阅读 »

最近一个项目需要客户在提交单据的时候,附带签名。度娘了一下。果然还是有这个JQuery插件的。学名:jSignature
好了,废话不多说。先来个截图(见附件)。这玩意功能还是比较强大的。支持各种设置和各种姿势的导出。可惜是在JQuery里的,得先引用JQuery.

                <script type="text/javascript" src="js/jquery.js"></script>  
        <script type="text/javascript" src="js/jSignature.min.js"></script>  
        <!--[if lt IE 9]>  
        <script type="text/javascript" src="js/flashcanvas.js"></script>  
        <![endif]-->

下面就简单了,给一个dom.比如这样的:

<div id="signature" style="height: 100%;"></div>

最后呢,就是初始化一下。可以这样的:

$(document).ready(function() {  
                $("#signature").jSignature()  
            });

要是想导出呢,这里是Base64,就要这样的:

var datapair = $("#signature").jSignature("getData", "image");  
                var array = datapair.splice(",");  
                mui.toast(array[1]);

好了,其他也就没什么 了。更多了解就去看 api 吧。
最后在附上js包,希望对大家有帮助。

收起阅读 »

修复mui中多选项卡切换时,隐藏选项卡初始化属性不正确的问题.

同页面中多选项卡切换显示时,由于隐藏的选项卡无法获得offsetWidth属性,导致初始隐藏的选项卡后期显示时,选项卡标签条无法根据正确的当前项滚动.

此方法属于补救措施,不修改mui.js源文件.具体事件绑定因项目架构而异,以下只作比方.
假设A, B, C, D控制4个选项卡的显/隐.每个选项卡包含N个子项.
4个选项卡分别为A_s, B_s, C_s, D_s

document.getElementById(A).addEventListener('tap', function (){  
    var slider_id = document.querySelector(A_s).getAttribute('data-slider');  
    var slider_data = mui.data[slider_id];  
    var progressBarWidth = slider_data.progressBarWidth;  

    if (!progressBarWidth) {  
        slider_data.progressBarWidth = document.querySelector(A_s).querySelector('.mui-slider-progress-bar').offsetWidth;  
    }  
})

修复前:

修复后:

继续阅读 »

同页面中多选项卡切换显示时,由于隐藏的选项卡无法获得offsetWidth属性,导致初始隐藏的选项卡后期显示时,选项卡标签条无法根据正确的当前项滚动.

此方法属于补救措施,不修改mui.js源文件.具体事件绑定因项目架构而异,以下只作比方.
假设A, B, C, D控制4个选项卡的显/隐.每个选项卡包含N个子项.
4个选项卡分别为A_s, B_s, C_s, D_s

document.getElementById(A).addEventListener('tap', function (){  
    var slider_id = document.querySelector(A_s).getAttribute('data-slider');  
    var slider_data = mui.data[slider_id];  
    var progressBarWidth = slider_data.progressBarWidth;  

    if (!progressBarWidth) {  
        slider_data.progressBarWidth = document.querySelector(A_s).querySelector('.mui-slider-progress-bar').offsetWidth;  
    }  
})

修复前:

修复后:

收起阅读 »

配合下拉刷新、上拉加载的返回顶部demo(适用任何页面)

看到很多人提到了这个问题,正好自己也需要返回顶部的操作,总结了下各处的问题与回答,把实现的代码放出来,供参考。

下拉刷新、上拉加载的容器和返回顶部按钮,按钮默认不显示:

<div id="pullrefresh" class="mui-scroll-wrapper">  
    <div class="mui-scroll">  
        <ul id="list" class="mui-table-view"></ul>  
    </div>  
</div>  

<a id="scrollToTop" class="backTop hide">  
    <span class="mui-icon mui-icon-arrowup"></span>  
</a>

按钮对应的css:

.hide {  
    display: none;  
}  
.backTop {  
    background: #DDDDDD;  
    border-radius: 50%;  
    position: fixed;  
    right: 10px;  
    bottom: 15px;  
    width: 38px;  
    height: 38px;  
    z-index: 9999;  
    text-align: center;  
    font-size: 18px;  
    color: #666666;  
    padding-top: 8px;  
    opacity: 0.8;  
}

js中添加事件监听:

var scrollToTopBox = document.getElementById('scrollToTop');  
//返回按钮tap  
scrollToTopBox.addEventListener('tap', function(e) {  
    e.stopPropagation();  
    mui('#pullrefresh').pullRefresh().scrollTo(0, 0, 100);//滚动到顶部  
});  
//Android上监听原生滚动,iOS上监听div滚动,上拉超过一屏后显示按钮,否则隐藏,可自行在条件判断中修改  
if (mui.os.android) {  
    window.addEventListener('scroll', function(e) {  
        if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))  
            scrollToTopBox.classList.remove('hide');  
        else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))  
            scrollToTopBox.classList.add('hide');  
    });  
} else {  
    document.getElementById('pullrefresh').addEventListener('scroll', function() {  
            if (mui('#pullrefresh').pullRefresh().y <= window.innerHeight * (-1) && scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.remove('hide');  
            else if (mui('#pullrefresh').pullRefresh().y > window.innerHeight * (-1) && !scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.add('hide');  
    });  
}

该方法也可用于任何需要返回顶部的页面,做一下适当的修改,此时不区分Android和iOS,代码如下:

var scrollToTopBox = document.getElementById('scrollToTop');  
        scrollToTopBox.addEventListener('tap', function(e) {  
            e.stopPropagation();  
            mui('body').pullRefresh().scrollTo(0, 0, 100);  
        });  
        window.addEventListener('scroll', function() {  
            if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.remove('hide');  
            else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.add('hide');  
        });
继续阅读 »

看到很多人提到了这个问题,正好自己也需要返回顶部的操作,总结了下各处的问题与回答,把实现的代码放出来,供参考。

下拉刷新、上拉加载的容器和返回顶部按钮,按钮默认不显示:

<div id="pullrefresh" class="mui-scroll-wrapper">  
    <div class="mui-scroll">  
        <ul id="list" class="mui-table-view"></ul>  
    </div>  
</div>  

<a id="scrollToTop" class="backTop hide">  
    <span class="mui-icon mui-icon-arrowup"></span>  
</a>

按钮对应的css:

.hide {  
    display: none;  
}  
.backTop {  
    background: #DDDDDD;  
    border-radius: 50%;  
    position: fixed;  
    right: 10px;  
    bottom: 15px;  
    width: 38px;  
    height: 38px;  
    z-index: 9999;  
    text-align: center;  
    font-size: 18px;  
    color: #666666;  
    padding-top: 8px;  
    opacity: 0.8;  
}

js中添加事件监听:

var scrollToTopBox = document.getElementById('scrollToTop');  
//返回按钮tap  
scrollToTopBox.addEventListener('tap', function(e) {  
    e.stopPropagation();  
    mui('#pullrefresh').pullRefresh().scrollTo(0, 0, 100);//滚动到顶部  
});  
//Android上监听原生滚动,iOS上监听div滚动,上拉超过一屏后显示按钮,否则隐藏,可自行在条件判断中修改  
if (mui.os.android) {  
    window.addEventListener('scroll', function(e) {  
        if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))  
            scrollToTopBox.classList.remove('hide');  
        else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))  
            scrollToTopBox.classList.add('hide');  
    });  
} else {  
    document.getElementById('pullrefresh').addEventListener('scroll', function() {  
            if (mui('#pullrefresh').pullRefresh().y <= window.innerHeight * (-1) && scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.remove('hide');  
            else if (mui('#pullrefresh').pullRefresh().y > window.innerHeight * (-1) && !scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.add('hide');  
    });  
}

该方法也可用于任何需要返回顶部的页面,做一下适当的修改,此时不区分Android和iOS,代码如下:

var scrollToTopBox = document.getElementById('scrollToTop');  
        scrollToTopBox.addEventListener('tap', function(e) {  
            e.stopPropagation();  
            mui('body').pullRefresh().scrollTo(0, 0, 100);  
        });  
        window.addEventListener('scroll', function() {  
            if (window.pageYOffset >= window.innerHeight && scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.remove('hide');  
            else if (window.pageYOffset < window.innerHeight && !scrollToTopBox.classList.contains('hide'))  
                scrollToTopBox.classList.add('hide');  
        });
收起阅读 »

Android Studio 离线打包

离线打包

android studio 版本1.5
android studio新建工程
libs 添加需要的jar包
src/main/assets/apps/对应的id/www/项目
src/main/assets/dataAndroid-SDK/SDK/assets/data 拷贝来的
src/main/java/io/dcloud/RInformation.javaAndroid-SDK\SDK\src 拷贝来的
src/main/resAndroid-SDK\SDK\res 拷贝来的
ps: 1.5下面只有一个drawable,剩下的是mipmap-hdpi、mipmap-mdpi等等,所以是拷贝的文件内容,而不是整个文件夹

androidmanifest.xml中application

<application  
        android:allowBackup="true"  
        android:icon="@mipmap/icon"  
        android:label="@string/app_name"  
        android:supportsRtl="true"  
        android:theme="@style/AppTheme">  
        <activity  
            android:name="io.dcloud.PandoraEntry"  
            android:configChanges="orientation|keyboardHidden"  
            android:label="@string/app_name"  
            android:launchMode="singleTask"  
            android:screenOrientation="user"  
            android:windowSoftInputMode="adjustResize" >  
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />  

                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
        <activity  
            android:name="io.dcloud.PandoraEntryActivity"  
            android:configChanges="orientation|keyboardHidden|screenSize"  
            android:hardwareAccelerated="true"  
            android:label="5+Debug"  
            android:launchMode="singleTask"  
            android:screenOrientation="user"  
            android:theme="@style/DCloudTheme"  
            android:windowSoftInputMode="adjustResize" >  
        </activity>  

        <service  
            android:name="io.dcloud.common.adapter.io.MiniServerService"  
            android:exported="true" />  

    </application>

activity,service 中 android:name 依赖的是pdr.jar

不知道这个jar包是做什么的,少引用时出错了。猜测和图片有关
universal-image-loader-1.9.0.jar

其他的可以参考如下链接:
SDK下载地址:http://ask.dcloud.net.cn/article/103
Android平台离线打包插件配置:http://ask.dcloud.net.cn/article/216
还有这个文章: http://ask.dcloud.net.cn/question/15183

继续阅读 »

android studio 版本1.5
android studio新建工程
libs 添加需要的jar包
src/main/assets/apps/对应的id/www/项目
src/main/assets/dataAndroid-SDK/SDK/assets/data 拷贝来的
src/main/java/io/dcloud/RInformation.javaAndroid-SDK\SDK\src 拷贝来的
src/main/resAndroid-SDK\SDK\res 拷贝来的
ps: 1.5下面只有一个drawable,剩下的是mipmap-hdpi、mipmap-mdpi等等,所以是拷贝的文件内容,而不是整个文件夹

androidmanifest.xml中application

<application  
        android:allowBackup="true"  
        android:icon="@mipmap/icon"  
        android:label="@string/app_name"  
        android:supportsRtl="true"  
        android:theme="@style/AppTheme">  
        <activity  
            android:name="io.dcloud.PandoraEntry"  
            android:configChanges="orientation|keyboardHidden"  
            android:label="@string/app_name"  
            android:launchMode="singleTask"  
            android:screenOrientation="user"  
            android:windowSoftInputMode="adjustResize" >  
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />  

                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
        <activity  
            android:name="io.dcloud.PandoraEntryActivity"  
            android:configChanges="orientation|keyboardHidden|screenSize"  
            android:hardwareAccelerated="true"  
            android:label="5+Debug"  
            android:launchMode="singleTask"  
            android:screenOrientation="user"  
            android:theme="@style/DCloudTheme"  
            android:windowSoftInputMode="adjustResize" >  
        </activity>  

        <service  
            android:name="io.dcloud.common.adapter.io.MiniServerService"  
            android:exported="true" />  

    </application>

activity,service 中 android:name 依赖的是pdr.jar

不知道这个jar包是做什么的,少引用时出错了。猜测和图片有关
universal-image-loader-1.9.0.jar

其他的可以参考如下链接:
SDK下载地址:http://ask.dcloud.net.cn/article/103
Android平台离线打包插件配置:http://ask.dcloud.net.cn/article/216
还有这个文章: http://ask.dcloud.net.cn/question/15183

收起阅读 »

将tap模拟成原生click体验

tap

将tap模拟成原生click体验

mui提供了tap事件替换了html5的click事件,解决了300ms延时的问题。不过相比原生app的click体验还是有些许差距的。  
仅用微信为例,只有当手指离开屏幕时才触发click事件,如果对象绑定了长按事件,则触发长按操作,离开时不再触发单击事件。  
这些逻辑无论是android, ios或者仅有1%的windows mobile都已经封装好了,根本不用关心。  

那么,我们应该怎么来实现呢?
下面是详细的填坑历程。。。。。。

坑1.通过原生的touch来实现

//直接对dom添加touchend,这种方法只能针对位置不变且并没有添加longtap事件的DOM有效  
//如果在listview中,你上下滑动,那就歇菜了。  
//那么自然而然就想到了touch.target的位移,并做出判断是下滑还是单击。  
//自己去写复杂度、代码量估计会很可观。  
//因此就想到了了在原有的框架代码上去实现。  
//下面就到了坑2  
document.getElementById("").('touchend', function() {  
    //  
});

坑2.更改mui.gestures.tap.js

坑2.1 自定义事件侦听机制

mui没有提供类似于jq.data('events')获取事件列表的机制,另外官方也推荐使用addEventListener去绑定事件。
我要去获取当前DOM的事件列表应该怎么做呢?

你问我问毛要去获取DOM的事件列表,,,
呵呵,我总要知道DOM有木有绑定longtap事件好做规避吧

csdn的这个帖子看似有用
http://bbs.csdn.net/topics/390250552

function addEvent(dom,type,fn) {  
    if(document.addEventListener) {  
        dom.addEventListener(type, fn, false);  
    } else if(document.attachEvent) {  
        dom.attachEvent('on' + type, fn);  
    } else {  
        dom['on' + type] = fn;  
    };  
    dom[""+type]=!0;  
}

实际上并没有什么卵用
思想是好的.....
我总不能每次addEventListener都去调一下这个方法吧!

坑2.2 使用getEventListeners

找啊找,终于找到了getEventListeners()这个全局方法,在chrome和safari控制台中测试都木有问题。
喜出望外......
这下终于能解决问题了
于是有了以下的方法

    var getEvents = function(obj) {  
        console.log(getEventListeners(obj));  
        return typeof(getEventListeners) == "function" && getEventListeners(obj);  
    }  
    var hasEventype = function(obj, e) {  
        var es = getEvents(obj);  
        console.log(es[e]);  
        return es && !!es[e];  
    }

调用下试试

if (!hasEventype(target, 'longtap')) {}

报错
getEventListeners is undefined

R U kidding?!!!!

你丫在逗我.............

我瞬间感受到了深深地恶意

原来这个方法只能在控制台中用,
呵呵,人艰不拆......

坑2.3 使用全局变量规避

给mui添加一个全局变量isLongTapAtived,看变量名就知道什么意思吧
mui.gestures.longtap.js中初始化,在handle中激活

(function($, name) {  
    $.isLongTapAtived = false;//初始化  
    var timer;  
    var handle = function(event, touch) {  
        switch (event.type) {  
            case $.EVENT_START:  
                clearTimeout(timer);  
                timer = setTimeout(function() {  
                    $.trigger(session.target, name, touch);  
                    //激活了  
                    $.isLongTapAtived = true;  
                }, options.holdTimeout);  
                break;  
        }  
    };  

    });  
})(mui, 'longtap');

mui.gestures.tap.js中判断有无激活

    var handle = function(event, touch) {  
        var session = $.gestures.session;  
        var options = this.options;  
        switch (event.type) {  
            case $.EVENT_END:  
                //......  
                if (touch.distance < options.tapMaxDistance) {  
                    if (touch.deltaTime < options.tapMaxTime) {  
                        //.....  
                    } else {  
                        //如果当前对象添加了长按侦听,略过,否则仍然视为tap事件  
                        //if (!hasEventype(target, 'longtap')) {  
                        if (!$.isLongTapAtived) {  
                            //如果没有longtap事件,离开屏幕是触发tap事件  
                            $.trigger(target, name, touch);  
                        }  
                        //重置  
                        $.isLongTapAtived = false;  
                    }  
                }  
                break;  
        }  
    };  

想法是美好的,现实是他么残酷的。无论有无longtap事件,都要走一遍longtaphandle代码
于是 $.isLongTapAtived === true;
于是 永远trigger tap 事件

呵呵,想死的心都有了


路子看来走对了,但是应该怎么做???

终极解决方案

mui.isLongTapAtived依然添加,只是在每一次DOM添加的longtap事件内激活

document.querySelector("#").addEventListener('longtap',function(){  
    mui.isLongTapAtived=true;  
    console.log('你触发了longtap事件');  
});

这样对开发者是不友好的,不过暂时没办法,只能如此取舍了

代码已提交至https://github.com/phillyx/mui/
并推送给官方

博客已同步至http://www.cnblogs.com/phillyx/p/5157850.html

觉得不错就打赏一下吧

继续阅读 »

将tap模拟成原生click体验

mui提供了tap事件替换了html5的click事件,解决了300ms延时的问题。不过相比原生app的click体验还是有些许差距的。  
仅用微信为例,只有当手指离开屏幕时才触发click事件,如果对象绑定了长按事件,则触发长按操作,离开时不再触发单击事件。  
这些逻辑无论是android, ios或者仅有1%的windows mobile都已经封装好了,根本不用关心。  

那么,我们应该怎么来实现呢?
下面是详细的填坑历程。。。。。。

坑1.通过原生的touch来实现

//直接对dom添加touchend,这种方法只能针对位置不变且并没有添加longtap事件的DOM有效  
//如果在listview中,你上下滑动,那就歇菜了。  
//那么自然而然就想到了touch.target的位移,并做出判断是下滑还是单击。  
//自己去写复杂度、代码量估计会很可观。  
//因此就想到了了在原有的框架代码上去实现。  
//下面就到了坑2  
document.getElementById("").('touchend', function() {  
    //  
});

坑2.更改mui.gestures.tap.js

坑2.1 自定义事件侦听机制

mui没有提供类似于jq.data('events')获取事件列表的机制,另外官方也推荐使用addEventListener去绑定事件。
我要去获取当前DOM的事件列表应该怎么做呢?

你问我问毛要去获取DOM的事件列表,,,
呵呵,我总要知道DOM有木有绑定longtap事件好做规避吧

csdn的这个帖子看似有用
http://bbs.csdn.net/topics/390250552

function addEvent(dom,type,fn) {  
    if(document.addEventListener) {  
        dom.addEventListener(type, fn, false);  
    } else if(document.attachEvent) {  
        dom.attachEvent('on' + type, fn);  
    } else {  
        dom['on' + type] = fn;  
    };  
    dom[""+type]=!0;  
}

实际上并没有什么卵用
思想是好的.....
我总不能每次addEventListener都去调一下这个方法吧!

坑2.2 使用getEventListeners

找啊找,终于找到了getEventListeners()这个全局方法,在chrome和safari控制台中测试都木有问题。
喜出望外......
这下终于能解决问题了
于是有了以下的方法

    var getEvents = function(obj) {  
        console.log(getEventListeners(obj));  
        return typeof(getEventListeners) == "function" && getEventListeners(obj);  
    }  
    var hasEventype = function(obj, e) {  
        var es = getEvents(obj);  
        console.log(es[e]);  
        return es && !!es[e];  
    }

调用下试试

if (!hasEventype(target, 'longtap')) {}

报错
getEventListeners is undefined

R U kidding?!!!!

你丫在逗我.............

我瞬间感受到了深深地恶意

原来这个方法只能在控制台中用,
呵呵,人艰不拆......

坑2.3 使用全局变量规避

给mui添加一个全局变量isLongTapAtived,看变量名就知道什么意思吧
mui.gestures.longtap.js中初始化,在handle中激活

(function($, name) {  
    $.isLongTapAtived = false;//初始化  
    var timer;  
    var handle = function(event, touch) {  
        switch (event.type) {  
            case $.EVENT_START:  
                clearTimeout(timer);  
                timer = setTimeout(function() {  
                    $.trigger(session.target, name, touch);  
                    //激活了  
                    $.isLongTapAtived = true;  
                }, options.holdTimeout);  
                break;  
        }  
    };  

    });  
})(mui, 'longtap');

mui.gestures.tap.js中判断有无激活

    var handle = function(event, touch) {  
        var session = $.gestures.session;  
        var options = this.options;  
        switch (event.type) {  
            case $.EVENT_END:  
                //......  
                if (touch.distance < options.tapMaxDistance) {  
                    if (touch.deltaTime < options.tapMaxTime) {  
                        //.....  
                    } else {  
                        //如果当前对象添加了长按侦听,略过,否则仍然视为tap事件  
                        //if (!hasEventype(target, 'longtap')) {  
                        if (!$.isLongTapAtived) {  
                            //如果没有longtap事件,离开屏幕是触发tap事件  
                            $.trigger(target, name, touch);  
                        }  
                        //重置  
                        $.isLongTapAtived = false;  
                    }  
                }  
                break;  
        }  
    };  

想法是美好的,现实是他么残酷的。无论有无longtap事件,都要走一遍longtaphandle代码
于是 $.isLongTapAtived === true;
于是 永远trigger tap 事件

呵呵,想死的心都有了


路子看来走对了,但是应该怎么做???

终极解决方案

mui.isLongTapAtived依然添加,只是在每一次DOM添加的longtap事件内激活

document.querySelector("#").addEventListener('longtap',function(){  
    mui.isLongTapAtived=true;  
    console.log('你触发了longtap事件');  
});

这样对开发者是不友好的,不过暂时没办法,只能如此取舍了

代码已提交至https://github.com/phillyx/mui/
并推送给官方

博客已同步至http://www.cnblogs.com/phillyx/p/5157850.html

觉得不错就打赏一下吧

收起阅读 »

【交流分享】解决IOS列表滑动不流畅的问题

技术分享 卡顿

很简单的列表:

<body>  
        <div class="list">  
            <h1>图片</h1>  
            <img sr c="xxx.jpg" />  

            ...这里是20个<h1><img>...  

            <h1>图片</h1>  
            <img sr c="xxx.jpg" />  
        </div>  
    </body>

上述很简单的图文列表运行在IOS上列表滑动起来总是不流畅,但是在Android运行就很快;就算把img删掉,只剩h1文字列表,在IOS上滑起来都有点卡顿,手指只要离开屏幕,列表就停了,没有继续惯性滚动一段距离;

分享一下我的解决办法:

方法一: 使用原生div的滚动
如果像上面代码一样,不使用mui框架,则加入以下css:

body,  
            html {  
                height: 100%;  
                -webkit-overflow-scrolling: touch;//允许独立的滚动区域和触摸回弹  
            }  
            .list{  
                height: 100%;  
                overflow-y: scroll;//使用原生div滚动  
            }

如果使用mui框架,则
引入mui.css, 把上面<div class="list">变成 <div class="mui-content">; 加入以下css:

body,  
            html {  
                height: 100%;  
            }  
            .mui-content{  
                height: 100%;  
                overflow-y: scroll;  
            }

方法二: 使用mui的区域滚动
参考:http://dev.dcloud.net.cn/mui/ui/#scroll
但是这种方式,体验不如上面css的; 按照我们公司IOS同事的话来讲:你会感觉滑动飞得太假;当然也能解决问题;

最后附上源码案例, 很简单, 导入到HBuilder就可以在IOS上运行了

继续阅读 »

很简单的列表:

<body>  
        <div class="list">  
            <h1>图片</h1>  
            <img sr c="xxx.jpg" />  

            ...这里是20个<h1><img>...  

            <h1>图片</h1>  
            <img sr c="xxx.jpg" />  
        </div>  
    </body>

上述很简单的图文列表运行在IOS上列表滑动起来总是不流畅,但是在Android运行就很快;就算把img删掉,只剩h1文字列表,在IOS上滑起来都有点卡顿,手指只要离开屏幕,列表就停了,没有继续惯性滚动一段距离;

分享一下我的解决办法:

方法一: 使用原生div的滚动
如果像上面代码一样,不使用mui框架,则加入以下css:

body,  
            html {  
                height: 100%;  
                -webkit-overflow-scrolling: touch;//允许独立的滚动区域和触摸回弹  
            }  
            .list{  
                height: 100%;  
                overflow-y: scroll;//使用原生div滚动  
            }

如果使用mui框架,则
引入mui.css, 把上面<div class="list">变成 <div class="mui-content">; 加入以下css:

body,  
            html {  
                height: 100%;  
            }  
            .mui-content{  
                height: 100%;  
                overflow-y: scroll;  
            }

方法二: 使用mui的区域滚动
参考:http://dev.dcloud.net.cn/mui/ui/#scroll
但是这种方式,体验不如上面css的; 按照我们公司IOS同事的话来讲:你会感觉滑动飞得太假;当然也能解决问题;

最后附上源码案例, 很简单, 导入到HBuilder就可以在IOS上运行了

收起阅读 »