DCloud图片上传和压缩
define(['common', 'config'], function(com, con) {
/*
* 打开摄像头、打开图库 模块
*/
return {
//model对象
_model: {
result: true,
id: 0,
img: ""
},
//记录上传文件数
upTimer: {
count: 0,
imgs: []
},
//打开摄像头
open: function(obj, callback) {
my = this;
mui.plusReady(function() {
if($(obj).attr('data-camera-gallery') == "1") {
var a = [{
title: "拍照"
}, {
title: "从手机相册选择"
}];
plus.nativeUI.actionSheet({
//title: "修改用户头像",
cancel: "取消",
buttons: a
}, function(b) {
/*actionSheet 按钮点击事件*/
switch(b.index) {
case 0:
break;
case 1:
my.getImage(obj, callback);
break;
case 2:
my.galleryImg(obj, callback);
break;
default:
break;
}
});
} else {
my.getImage(obj, callback);
}
});
},
//拍照
getImage: function(obj, callback) {
var my = this;
var photoType = $(obj).attr("data-PhotoType") ? $(obj).attr("data-PhotoType") : "";
mui.plusReady(function() {
var data = {
result: false,
msg: '',
data: null
};
var c = plus.camera.getCamera();
c.captureImage(function(e) {
$(obj).css('opacity', '0.3').attr('disabled', true);
plus.io.resolveLocalFileSystemURL(e, function(entry) {
var s = entry.toLocalURL();
data.result = true;
data.data = s;
my.upload(obj, con.urlCONFIG.post_upload, s, callback, photoType);
}, function(e) {
data.data = "读取拍照文件错误:" + e.message;
callback(data);
});
}, function(error) {
data.msg = error.message;
//callback(data);
})
});
},
//打开相册
galleryImg: function(obj, callback) {
var my = this;
plus.gallery.pick(function(a) {
var photoType = $(obj).attr("data-PhotoType") ? $(obj).attr("data-PhotoType") : "";
var data = {
result: false,
msg: '',
data: null
};
$(obj).css('opacity', '0.3').attr('disabled', true);
plus.io.resolveLocalFileSystemURL(a, function(entry) {
var s = entry.toLocalURL();
data.result = true;
data.data = s;
my.upload(obj, com.urlCONFIG.post_upload, s, callback, photoType);
}, function(e) {
data.data = "读取拍照文件错误:" + e.message;
callback(data);
});
}, function(a) {}, {
filter: "image"
})
},
//上传图片到服务器
upload: function(obj, url, filename, callback, photoType) {
var my = this;
my.upTimer.count++;
var tips = com.msg(my.upTimer.count + '个文件正在上传', 999);
mui.plusReady(function() {
var task = plus.uploader.createUpload(url, {
method: "POST",
blocksize: 0,
priority: 100
},
function(t, status) {
$(obj).css('opacity', '1').removeAttr('disabled');
var json_data = t.responseText.replace('null(','').replace(');null','');
//console.log(json_data)
var data = JSON.parse(json_data);
if(data) {
// 上传完成
if(status == 200) {
my.upTimer.count--;
if(my.upTimer.count <= 0) {
com.msg('所有图片上传完毕', 1);
}
var model = _.clone(my._model);
model.id = new Date().getTime();
model.img = data.data;
my.upTimer.imgs.push(model);
callback(model);
} else {
callback(data);
}
} else {
com.msg('上传失败:' + data.msg, 0);
}
}
);
//图片压缩
my.resize(filename, function(zipSrc) {
task.addFile(zipSrc, {
key: "upload"
});
task.addData(zipSrc, zipSrc);
task.start();
});
});
},
//压缩(需要获取本地文件权限)
resize: function(src, callback) {
var filename = src.substring(src.lastIndexOf('/') + 1);
plus.zip.compressImage({
src: src,
dst: '_doc/' + filename,
overwrite: true,
width: '1000px', //这里指定了宽度,同样可以修改
format: 'jpg',
quality: 90 //图片质量不再修改,以免失真
},
function(e) {
callback(e.target);
},
function(err) {
com.alert('未知错误!', 0, function() {
mui.back();
})
})
}
};
})
define(['common', 'config'], function(com, con) {
/*
* 打开摄像头、打开图库 模块
*/
return {
//model对象
_model: {
result: true,
id: 0,
img: ""
},
//记录上传文件数
upTimer: {
count: 0,
imgs: []
},
//打开摄像头
open: function(obj, callback) {
my = this;
mui.plusReady(function() {
if($(obj).attr('data-camera-gallery') == "1") {
var a = [{
title: "拍照"
}, {
title: "从手机相册选择"
}];
plus.nativeUI.actionSheet({
//title: "修改用户头像",
cancel: "取消",
buttons: a
}, function(b) {
/*actionSheet 按钮点击事件*/
switch(b.index) {
case 0:
break;
case 1:
my.getImage(obj, callback);
break;
case 2:
my.galleryImg(obj, callback);
break;
default:
break;
}
});
} else {
my.getImage(obj, callback);
}
});
},
//拍照
getImage: function(obj, callback) {
var my = this;
var photoType = $(obj).attr("data-PhotoType") ? $(obj).attr("data-PhotoType") : "";
mui.plusReady(function() {
var data = {
result: false,
msg: '',
data: null
};
var c = plus.camera.getCamera();
c.captureImage(function(e) {
$(obj).css('opacity', '0.3').attr('disabled', true);
plus.io.resolveLocalFileSystemURL(e, function(entry) {
var s = entry.toLocalURL();
data.result = true;
data.data = s;
my.upload(obj, con.urlCONFIG.post_upload, s, callback, photoType);
}, function(e) {
data.data = "读取拍照文件错误:" + e.message;
callback(data);
});
}, function(error) {
data.msg = error.message;
//callback(data);
})
});
},
//打开相册
galleryImg: function(obj, callback) {
var my = this;
plus.gallery.pick(function(a) {
var photoType = $(obj).attr("data-PhotoType") ? $(obj).attr("data-PhotoType") : "";
var data = {
result: false,
msg: '',
data: null
};
$(obj).css('opacity', '0.3').attr('disabled', true);
plus.io.resolveLocalFileSystemURL(a, function(entry) {
var s = entry.toLocalURL();
data.result = true;
data.data = s;
my.upload(obj, com.urlCONFIG.post_upload, s, callback, photoType);
}, function(e) {
data.data = "读取拍照文件错误:" + e.message;
callback(data);
});
}, function(a) {}, {
filter: "image"
})
},
//上传图片到服务器
upload: function(obj, url, filename, callback, photoType) {
var my = this;
my.upTimer.count++;
var tips = com.msg(my.upTimer.count + '个文件正在上传', 999);
mui.plusReady(function() {
var task = plus.uploader.createUpload(url, {
method: "POST",
blocksize: 0,
priority: 100
},
function(t, status) {
$(obj).css('opacity', '1').removeAttr('disabled');
var json_data = t.responseText.replace('null(','').replace(');null','');
//console.log(json_data)
var data = JSON.parse(json_data);
if(data) {
// 上传完成
if(status == 200) {
my.upTimer.count--;
if(my.upTimer.count <= 0) {
com.msg('所有图片上传完毕', 1);
}
var model = _.clone(my._model);
model.id = new Date().getTime();
model.img = data.data;
my.upTimer.imgs.push(model);
callback(model);
} else {
callback(data);
}
} else {
com.msg('上传失败:' + data.msg, 0);
}
}
);
//图片压缩
my.resize(filename, function(zipSrc) {
task.addFile(zipSrc, {
key: "upload"
});
task.addData(zipSrc, zipSrc);
task.start();
});
});
},
//压缩(需要获取本地文件权限)
resize: function(src, callback) {
var filename = src.substring(src.lastIndexOf('/') + 1);
plus.zip.compressImage({
src: src,
dst: '_doc/' + filename,
overwrite: true,
width: '1000px', //这里指定了宽度,同样可以修改
format: 'jpg',
quality: 90 //图片质量不再修改,以免失真
},
function(e) {
callback(e.target);
},
function(err) {
com.alert('未知错误!', 0, function() {
mui.back();
})
})
}
};
}) 收起阅读 »
DCloud 定位代码
define(['common'], function(com) {
/*
* GPS定位模块
*/
return {
/**
* @constructor
* @description 得到定位信息
*/
getlocation: function(callback) {
mui.plusReady(function() {
var data = {
result: false,
code: '',
msg: '',
position: null
};
plus.geolocation.getCurrentPosition(function(p) {
//debugCom.log(JSON.stringify(p))
data.result = true;
data.position = p;
data.code = 0;
data.msg = '';
//回调
callback(data);
}, function(e) {
console.log(JSON.stringify(e))
data.result = false;
data.code = e.code;
switch(e.code) {
case 1:
data.msg = "GPS访问被拒绝 或 GPS未开启";
break;
case 2:
data.msg = "位置信息不可用";
break;
case 3:
data.msg = "获取用户位置的请求超时";
break;
default:
data.msg = e.message;
break;
}
if(data.msg == '')
data.msg = "获取用户位置的请求超时";
//回调
callback(data);
}, {
provider: 'baidu'
});
/*
provider: (String 类型 )优先使用的定位模块可取以下供应者: "system":表示系统定位模块,支持wgs84坐标系; "baidu":表示百度定位模块,支持gcj02/bd09/bd09ll坐标系; "amap":表示高德定位模板,支持gcj02坐标系。 默认值按以下优先顺序获取(amap>baidu>system),若指定的provider不存在或无效则返回错误回调。 注意:百度/高德定位模块需要配置百度/高德地图相关参数才能正常使用。
* */
});
},
/**
* @constructor
* @description 得到地址
*/
getaddress: function(callback) {
this.getlocation(function(data) {
var resdata = {
result: false,
msg: '',
data: ''
}
if(data.result) {
resdata.result = true;
resdata.data = data.position.addresses;
callback(resdata);
} else {
resdata.msg = data.msg;
callback(resdata);
}
})
}
};
}); define(['common'], function(com) {
/*
* GPS定位模块
*/
return {
/**
* @constructor
* @description 得到定位信息
*/
getlocation: function(callback) {
mui.plusReady(function() {
var data = {
result: false,
code: '',
msg: '',
position: null
};
plus.geolocation.getCurrentPosition(function(p) {
//debugCom.log(JSON.stringify(p))
data.result = true;
data.position = p;
data.code = 0;
data.msg = '';
//回调
callback(data);
}, function(e) {
console.log(JSON.stringify(e))
data.result = false;
data.code = e.code;
switch(e.code) {
case 1:
data.msg = "GPS访问被拒绝 或 GPS未开启";
break;
case 2:
data.msg = "位置信息不可用";
break;
case 3:
data.msg = "获取用户位置的请求超时";
break;
default:
data.msg = e.message;
break;
}
if(data.msg == '')
data.msg = "获取用户位置的请求超时";
//回调
callback(data);
}, {
provider: 'baidu'
});
/*
provider: (String 类型 )优先使用的定位模块可取以下供应者: "system":表示系统定位模块,支持wgs84坐标系; "baidu":表示百度定位模块,支持gcj02/bd09/bd09ll坐标系; "amap":表示高德定位模板,支持gcj02坐标系。 默认值按以下优先顺序获取(amap>baidu>system),若指定的provider不存在或无效则返回错误回调。 注意:百度/高德定位模块需要配置百度/高德地图相关参数才能正常使用。
* */
});
},
/**
* @constructor
* @description 得到地址
*/
getaddress: function(callback) {
this.getlocation(function(data) {
var resdata = {
result: false,
msg: '',
data: ''
}
if(data.result) {
resdata.result = true;
resdata.data = data.position.addresses;
callback(resdata);
} else {
resdata.msg = data.msg;
callback(resdata);
}
})
}
};
}); 收起阅读 »
Dcloud APP中实现微信登录第三方登录获取用户信息
【参考资料】
- 授权登录插件配置:http://ask.dcloud.net.cn/article/192
- OAuth模块管理客户端的用户登录授权验证功能,允许应用访问第三方平台的资源:http://www.html5plus.org/doc/zh_cn/oauth.html
【代码封装】
define([], function() {
return {
_getServices: function(fun) {
mui.plusReady(function() {
plus.oauth.getServices(function(services) {
fun(services);
}, function(e) {
debugCom.log("获取分享服务列表失败:" + e.message + " - " + e.code);
return null;
});
})
},
login: function() {
this._getServices(function(auths) {
var s = auths[0];
if(!s.authResult) {
s.login(function(e) {
// 获取登录操作结果
s.getUserInfo(function(e) {
debugCom.log("获取用户信息成功:" + JSON.stringify(s.userInfo));
}, function(e) {
debugCom.log("获取用户信息失败:" + e.message + " - " + e.code);
});
}, function(e) {
debugCom.log("登录认证失败!");
});
} else {
debugCom.log("已经登录认证!");
}
})
}
}
})
【获取到的结果如下】:
{
"openid":"oRrdQt_8w0_WBlaSFoe-lENTxhvg",
"nickname":"大能猫灬Michael",
"sex":1,
"language":"zh_CN",
"city":"长宁",
"province":"上海",
"country":"中国",
"headimgurl":"http://wx.qlogo.cn/mmopen/ajNVdqHZLLCeX1pAR5AGjdTtIjHWgcUJmN1CSTGB4GrY3iccKmV5UkxxVrFZ0gPjn71Me758aO7aMxpicCGDr6ww/0",
"privilege":[],
"unionid":"oU5Yyt26Id2qvDXpBdfT9NbohmCM"
}
【参考资料】
- 授权登录插件配置:http://ask.dcloud.net.cn/article/192
- OAuth模块管理客户端的用户登录授权验证功能,允许应用访问第三方平台的资源:http://www.html5plus.org/doc/zh_cn/oauth.html
【代码封装】
define([], function() {
return {
_getServices: function(fun) {
mui.plusReady(function() {
plus.oauth.getServices(function(services) {
fun(services);
}, function(e) {
debugCom.log("获取分享服务列表失败:" + e.message + " - " + e.code);
return null;
});
})
},
login: function() {
this._getServices(function(auths) {
var s = auths[0];
if(!s.authResult) {
s.login(function(e) {
// 获取登录操作结果
s.getUserInfo(function(e) {
debugCom.log("获取用户信息成功:" + JSON.stringify(s.userInfo));
}, function(e) {
debugCom.log("获取用户信息失败:" + e.message + " - " + e.code);
});
}, function(e) {
debugCom.log("登录认证失败!");
});
} else {
debugCom.log("已经登录认证!");
}
})
}
}
})
【获取到的结果如下】:
{
"openid":"oRrdQt_8w0_WBlaSFoe-lENTxhvg",
"nickname":"大能猫灬Michael",
"sex":1,
"language":"zh_CN",
"city":"长宁",
"province":"上海",
"country":"中国",
"headimgurl":"http://wx.qlogo.cn/mmopen/ajNVdqHZLLCeX1pAR5AGjdTtIjHWgcUJmN1CSTGB4GrY3iccKmV5UkxxVrFZ0gPjn71Me758aO7aMxpicCGDr6ww/0",
"privilege":[],
"unionid":"oU5Yyt26Id2qvDXpBdfT9NbohmCM"
}
【示例】html5plus应用实现沉浸式状态栏
开启沉浸式状态栏
沉浸式状态不支持动态设置,属于应用级的。此类参数信息,通常在manifest.json中配置。
manifest.json->plus节点下
"statusbar": {
"immersed": true //开启沉浸式状态栏
}
配置后,运行看到首页是这样的。
我的天,Webview里面的内容上天了,这显然不是我们期望的沉浸式状态栏的样子。
设置Webview的状态栏颜色
上面这种情况,在html5plus应用开发中,可以通过设置Webview的状态栏样式,模拟出一个状态条来填充状态栏部分的空间。
终端支持
- Android5及以上系统支持
- iOS7.0及以上系统支持
首页
无论是launchwebview还是secondwebview,都是在manifest.json中配置相关的参数信息。
manifest.json->plus->launchwebview
"launchwebview": {
"statusbar": {
"background": "#FF3333"
}
}
此时,再次运行,我们看到的效果是这样的。
Webview的内容出现在了正常的位置,这才是正确的样子。
普通Webview
普通的Webview,可以在创建的时候,设置statusbar的background来填充状态栏颜色。
webview = plus.webview.create('test.html', 'test', {
statusbar: {
background: '#1478ee'
}
});
有titleNView的Webview
如果Webview配置了titleNView,创建Webview时,会取titleNView下的backgroundColor值,填充状态栏颜色。
webview = plus.webview.create('test.html', 'test', {
titleNView: {
titleText: '测试页',
backgroundColor: '#fb6f18'
}
});
效果是这样的
为了区分开来,这里特地使用了不同的颜色。
Webview窗口的系统状态栏区域样式
窗口标题栏控件样式
前景色
调整状态栏颜色后,有时会出现系统状态栏部分的文字不清楚的情况。这时候,需要调调整前景色。
前景色的设置,受到的限制更多,只有“dark”和“light”两个选项。
同时前景色处理在终端支持方面
- Android5只有小米和魅族支持,Android6及以上所有安卓支持
- iOS7及以上支持
manifest.json配置
manifest.json->plus->statusbar
"statusbar": {
"style": "dark"
}
调用API
也可以通过调用相关API进行设置调整,设置系统状态栏样式。
plus.navigator.setStatusBarStyle('dark');
注意事项
- 黑白灰等以及接近黑白灰的颜色不支持设置为状态栏前景色,防止与前景色一致导致状态栏文字看不到。
更多
更多关于状态栏的设置,参考状态栏大全-状态栏透明(沉浸式)、变色及全屏的区别等相关文章。
附件中提供了一个最简的沉浸式状态栏示例工程,下载后真机运行即可体验。
开启沉浸式状态栏
沉浸式状态不支持动态设置,属于应用级的。此类参数信息,通常在manifest.json中配置。
manifest.json->plus节点下
"statusbar": {
"immersed": true //开启沉浸式状态栏
}
配置后,运行看到首页是这样的。
我的天,Webview里面的内容上天了,这显然不是我们期望的沉浸式状态栏的样子。
设置Webview的状态栏颜色
上面这种情况,在html5plus应用开发中,可以通过设置Webview的状态栏样式,模拟出一个状态条来填充状态栏部分的空间。
终端支持
- Android5及以上系统支持
- iOS7.0及以上系统支持
首页
无论是launchwebview还是secondwebview,都是在manifest.json中配置相关的参数信息。
manifest.json->plus->launchwebview
"launchwebview": {
"statusbar": {
"background": "#FF3333"
}
}
此时,再次运行,我们看到的效果是这样的。
Webview的内容出现在了正常的位置,这才是正确的样子。
普通Webview
普通的Webview,可以在创建的时候,设置statusbar的background来填充状态栏颜色。
webview = plus.webview.create('test.html', 'test', {
statusbar: {
background: '#1478ee'
}
});
有titleNView的Webview
如果Webview配置了titleNView,创建Webview时,会取titleNView下的backgroundColor值,填充状态栏颜色。
webview = plus.webview.create('test.html', 'test', {
titleNView: {
titleText: '测试页',
backgroundColor: '#fb6f18'
}
});
效果是这样的
为了区分开来,这里特地使用了不同的颜色。
Webview窗口的系统状态栏区域样式
窗口标题栏控件样式
前景色
调整状态栏颜色后,有时会出现系统状态栏部分的文字不清楚的情况。这时候,需要调调整前景色。
前景色的设置,受到的限制更多,只有“dark”和“light”两个选项。
同时前景色处理在终端支持方面
- Android5只有小米和魅族支持,Android6及以上所有安卓支持
- iOS7及以上支持
manifest.json配置
manifest.json->plus->statusbar
"statusbar": {
"style": "dark"
}
调用API
也可以通过调用相关API进行设置调整,设置系统状态栏样式。
plus.navigator.setStatusBarStyle('dark');
注意事项
- 黑白灰等以及接近黑白灰的颜色不支持设置为状态栏前景色,防止与前景色一致导致状态栏文字看不到。
更多
更多关于状态栏的设置,参考状态栏大全-状态栏透明(沉浸式)、变色及全屏的区别等相关文章。
附件中提供了一个最简的沉浸式状态栏示例工程,下载后真机运行即可体验。
【讲座】html5+ App开发之 Android 平台离线集成 5+ SDK
html5+ App开发过程中有时候会遇到一些功能,单纯通过 html5 或者 5+ 规范无法满足要求,比如自定义相机这种定制性较强的功能,这时候不得不借助第三方库或者原生插件来完成,本次讲座主要面向的就是需要定制性开发的朋友。
本次讲座的主要内容:
- 简单介绍 Android 开发环境
- html5+ SDK 两种集成方式实例讲解
- 浅析 Android 原生 和 JavaScript 交互原理
- Native.js 实例讲解
- html5+ 插件开发实例详解
本节课时长80分钟左右。
面向人群:
- 想学习原生开发的前端开发朋友
- 想快速集成 5+ sdk 的原生开发朋友
往期系列讲座:
> 限时特价票:html5+ App开发之 Android 平台离线集成 5+ SDK
上次参与讲座的可以私聊我获取半价券。
html5+ App开发过程中有时候会遇到一些功能,单纯通过 html5 或者 5+ 规范无法满足要求,比如自定义相机这种定制性较强的功能,这时候不得不借助第三方库或者原生插件来完成,本次讲座主要面向的就是需要定制性开发的朋友。
本次讲座的主要内容:
- 简单介绍 Android 开发环境
- html5+ SDK 两种集成方式实例讲解
- 浅析 Android 原生 和 JavaScript 交互原理
- Native.js 实例讲解
- html5+ 插件开发实例详解
本节课时长80分钟左右。
面向人群:
- 想学习原生开发的前端开发朋友
- 想快速集成 5+ sdk 的原生开发朋友
往期系列讲座:
> 限时特价票:html5+ App开发之 Android 平台离线集成 5+ SDK
上次参与讲座的可以私聊我获取半价券。
收起阅读 »小米推送ios内MiSDKRun设置问题
最近在调试小米推送。发现ios版一直不好使。咨询了小米的工作人员,被告知是MiSDKRun的配置不对,
测试环境应为debug,正式环境应为online。但是云打包貌似一直都是online。导致测试环境下无法接收到
推送消息。请问这个如何解决?
最近在调试小米推送。发现ios版一直不好使。咨询了小米的工作人员,被告知是MiSDKRun的配置不对,
测试环境应为debug,正式环境应为online。但是云打包貌似一直都是online。导致测试环境下无法接收到
推送消息。请问这个如何解决?
h5+ 地图API 视频教程已经发布
h5+ 地图API 视频教程已经发布,观看地址
http://www.hcoder.net/course/index/cate/4
更多视频教程:
mui、h5+、app项目实战教程,请点击
http://www.hcoder.net/course/index/cate/4
h5+ 地图API 视频教程已经发布,观看地址
http://www.hcoder.net/course/index/cate/4
更多视频教程:
mui、h5+、app项目实战教程,请点击
http://www.hcoder.net/course/index/cate/4
技术交流群,旨在互相解决问题。反灌水,反乱聊。
QQ群号:194178496
欢迎开发中遇到的问题和乐意为别人提供帮助的请加群!
点击链接加入群【HBuilder+MUI技术交流群】:https://jq.qq.com/?_wv=1027&k=4BF2dhv
QQ群号:194178496
欢迎开发中遇到的问题和乐意为别人提供帮助的请加群!
点击链接加入群【HBuilder+MUI技术交流群】:https://jq.qq.com/?_wv=1027&k=4BF2dhv
【示例】解决软键盘弹出时底部元素上浮的问题
问题描述
在html5plus环境下,当html中存在固定在底部的元素时,此时弹出软键盘的话,底部的元素也会被弹上来。
出现这种情况时,看起来页面布局好像乱掉了,这样给用户的体验不太理想。
问题分析
问题原因
之所以会出现这种情况,是因为软键盘弹出会导致Webview的高度发生变化,进而导致html中元素位置发生变化。
其实也可以认为元素定位没有变,只是元素所在容器的宽高变化,看起来像是元素的位置变了。意思就是,元素定位相关的css并没有错误或者说失效。
验证方法
想验证这个变化,可以通过监听window的resize事件在回调中打印日志即可。
// 监听window的resize
window.addEventListener('resize', function() {
var height = document.documentElement.clientHeight;
var width = document.documentElement.clientWidth;
console.log('可见区域高度:' + height);
console.log('可见区域宽度:' + width);
});
当然,通过chrome调试Webview的功能,在chrome中可以很清楚地看到Webview的高度变化。
简单来说
软键盘被唤起的时候,原本属于Webview的空间被软键盘占用了(是占用,不是覆盖或者遮盖)。屏幕一共就那么高,软键盘把Webview的空间占用了一部分,那么Webview自然就被挤压,高度也就变了。
解决办法
固定元素
元素之所以会上浮,是因为通常我们都是设置元素的bottom值使其固定在底部。
.bottom {
height: 40px;
position: fixed;
bottom: 0;
}
但是Webview被挤压后,底部的位置上去了。元素是基于bottom值进行定位,那么它看起来就是在软键盘的上面。
逆向固定
既然bottom值会使元素上浮,但是我们又希望元素固定在底部。此时,可以使用逆向的方式,也就是设置top值让元素固定在顶部。
var bottomEl = document.querySelector('.bottom');
// 可见区域高度减去元素的高度
bottomEl.style.top = document.documentElement.clientHeight - 40 + 'px';
由于是基于top值定位,Webview被向上挤压,顶部的位置是不变的,那么元素的位置自然就不会发生变化。
效果图及源码
改进后的效果如下
示例代码见附件,下载后真机运行即可。
其它办法
如果各位有其它更好的解决办法,欢迎指教,并在社区分享你宝贵的经验。
问题描述
在html5plus环境下,当html中存在固定在底部的元素时,此时弹出软键盘的话,底部的元素也会被弹上来。
出现这种情况时,看起来页面布局好像乱掉了,这样给用户的体验不太理想。
问题分析
问题原因
之所以会出现这种情况,是因为软键盘弹出会导致Webview的高度发生变化,进而导致html中元素位置发生变化。
其实也可以认为元素定位没有变,只是元素所在容器的宽高变化,看起来像是元素的位置变了。意思就是,元素定位相关的css并没有错误或者说失效。
验证方法
想验证这个变化,可以通过监听window的resize事件在回调中打印日志即可。
// 监听window的resize
window.addEventListener('resize', function() {
var height = document.documentElement.clientHeight;
var width = document.documentElement.clientWidth;
console.log('可见区域高度:' + height);
console.log('可见区域宽度:' + width);
});
当然,通过chrome调试Webview的功能,在chrome中可以很清楚地看到Webview的高度变化。
简单来说
软键盘被唤起的时候,原本属于Webview的空间被软键盘占用了(是占用,不是覆盖或者遮盖)。屏幕一共就那么高,软键盘把Webview的空间占用了一部分,那么Webview自然就被挤压,高度也就变了。
解决办法
固定元素
元素之所以会上浮,是因为通常我们都是设置元素的bottom值使其固定在底部。
.bottom {
height: 40px;
position: fixed;
bottom: 0;
}
但是Webview被挤压后,底部的位置上去了。元素是基于bottom值进行定位,那么它看起来就是在软键盘的上面。
逆向固定
既然bottom值会使元素上浮,但是我们又希望元素固定在底部。此时,可以使用逆向的方式,也就是设置top值让元素固定在顶部。
var bottomEl = document.querySelector('.bottom');
// 可见区域高度减去元素的高度
bottomEl.style.top = document.documentElement.clientHeight - 40 + 'px';
由于是基于top值定位,Webview被向上挤压,顶部的位置是不变的,那么元素的位置自然就不会发生变化。
效果图及源码
改进后的效果如下
示例代码见附件,下载后真机运行即可。
其它办法
如果各位有其它更好的解决办法,欢迎指教,并在社区分享你宝贵的经验。
收起阅读 »关于input点击整个页面上移解决方法
先给你的body加如下代码:
body {
height: 100%;
margin: 0px;
padding: 0px;
overflow: hidden;
-webkit-touch-callout: none;
-webkit-user-select: none;
}
然后在你的plus里面添加一个样式设置该Activity总是调整屏幕的大小以便留出软键盘的空间:
plus.webview.currentWebview().setStyle({
softinputMode: "adjustResize"
});
先给你的body加如下代码:
body {
height: 100%;
margin: 0px;
padding: 0px;
overflow: hidden;
-webkit-touch-callout: none;
-webkit-user-select: none;
}
然后在你的plus里面添加一个样式设置该Activity总是调整屏幕的大小以便留出软键盘的空间:
plus.webview.currentWebview().setStyle({
softinputMode: "adjustResize"
});
如何更新通过nativeObj.View创建的view控件教程
需求说明
此教程将针对使用new plus.nativeObj.View() 创建的view对象如何更新作出详细说明;
创建示例
var currWV = plus.webview.currentWebview(),
leftPos = Math.ceil((window.innerWidth - 60) / 2);
var drawNativeIcon = new plus.nativeObj.View('tabIcon', {
bottom: '10px',
left: leftPos + 5 + 'px',
width: '50px',
height: '50px',
position:'dock' //此种停靠方式表明该控件应浮在窗口最上层,以免被其他窗口遮住
}, [{
tag: 'rect',
id: 'iconBg',
position: {
top: '0px',
left: '0px',
width: '50px',
height: '100%'
},
rectStyles: {
color: '#d74b28',
size: '50px',
radius:'50%'
}
},{
tag: 'font',
id: 'icon',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
position: {
top: '0px',
left: '0px',
width: '50px',
height: '100%'
},
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align:'center',
color: '#fff',
size: '30px'
}
}]);
currWV.append(drawNativeIcon);
实现更新方法
使用nativeObj提供的方法更新
通过 nativeObj 提供的 draw/drawBitmap/drawRect/drawText 方法对指定id重新绘制
说明:在当前View控件之上绘制指定的内容,可一次指定绘制多个元素,绘制元素可以是图片/矩形区域/文本, 即将多次调用drawBitmap/drawRect/drawText方法合并调用一次draw方法来实现, 推荐使用draw方法来替换多次调用drawBitmap/drawRect/drawText。
// 当前view控件需要更新的tags
drawNativeIcon.draw(tags);
// 更新指定id
drawNativeIcon.drawRect(styles, position, id) //绘制元素为矩形区域
drawNativeIcon.drawBitmap(src, sprite, position, id) //绘制元素为图片
drawNativeIcon.drawText(text, position, styles, id) //绘制元素为文本,包括字体图标
// 比如更新drawNativeIcon 控件的纯色背景颜色
drawNativeIcon.drawRect({
color: '#0ff',
radius: '50%'
}, {}, 'iconBg');
// 比如更新drawNativeIcon 控件的字体图标颜色
drawNativeIcon.drawText('\ue600', {}, {
color: '#ccc',
fontSrc: '_www/fonts/iconfont.ttf',
size: '30px'
}, 'icon');
// 使用draw方法
drawNativeIcon.draw([
{
id: 'iconBg',
tag:'rect',
rectStyles: {
color: '#ff0',
size: '50px',
radius: '50%'
}
}, {
id: 'icon',
tag:'font',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align: 'center',
color: '#000',
size: '30px'
}
}
])
说明:
1.position 的默认值为 {top:'0px',left:'0px',width:'100%',height:'100%'},如果与默认值相同,可以传空对象。
2.需要更新的tag 如果与默认值不相同,需要重新传值。
使用webview提供的方法更新
此方法使用 webview 提供的updateSubNViews()更新控件,是集成了nativeObj方法给webview提供一个直接操作原生view控件的方法。通过要更新view控件中的id属性值匹配子View控件更新绘制内容,如果没有查找到对应id的子View控件则忽略。 此操作仅更新子View控件上绘制的内容,不会添加或删除原生子View控件对象。
var currWV = plus.webview.currentWebview();
//比如更新控件颜色
currWV.updateSubNViews([{
id: 'tabIcon',
tags: [{
id: 'iconBg',
rectStyles: {
color: '#ff0',
size: '50px',
radius: '50%'
}
}, {
id: 'icon',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align: 'center',
color: '#000',
size: '30px'
}
}]
}])
说明:
1.position 的默认值为 {top:'0px',left:'0px',width:'100%',height:'100%'},如果与默认值相同,可以不传。
2.需要更新的tag 如果与默认值不相同,需要重新传值。
总结:
1.以上提供两种方式更新此类view控件,实现方法基本类似,开发者可根据使用场景选择恰当的方式。
2.此类方法创建的view控件与通过subNViews节点配置方法实现的效果一样,区别在于subNViews配置需要在创建webview时就引入。但是这样配置的信息就可以在页面中通过以下方式获取到view控件的相应信息。对于处理多个view控件的自动更新方便很多,比如首页底部选项卡
var nviews = currWV.getStyle().subNViews(); //返回配置的view控件的所有信息
3.关于如何更新subNViews节点配置的view控件。请下载参考教程 中上传的附件demo。
需求说明
此教程将针对使用new plus.nativeObj.View() 创建的view对象如何更新作出详细说明;
创建示例
var currWV = plus.webview.currentWebview(),
leftPos = Math.ceil((window.innerWidth - 60) / 2);
var drawNativeIcon = new plus.nativeObj.View('tabIcon', {
bottom: '10px',
left: leftPos + 5 + 'px',
width: '50px',
height: '50px',
position:'dock' //此种停靠方式表明该控件应浮在窗口最上层,以免被其他窗口遮住
}, [{
tag: 'rect',
id: 'iconBg',
position: {
top: '0px',
left: '0px',
width: '50px',
height: '100%'
},
rectStyles: {
color: '#d74b28',
size: '50px',
radius:'50%'
}
},{
tag: 'font',
id: 'icon',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
position: {
top: '0px',
left: '0px',
width: '50px',
height: '100%'
},
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align:'center',
color: '#fff',
size: '30px'
}
}]);
currWV.append(drawNativeIcon);
实现更新方法
使用nativeObj提供的方法更新
通过 nativeObj 提供的 draw/drawBitmap/drawRect/drawText 方法对指定id重新绘制
说明:在当前View控件之上绘制指定的内容,可一次指定绘制多个元素,绘制元素可以是图片/矩形区域/文本, 即将多次调用drawBitmap/drawRect/drawText方法合并调用一次draw方法来实现, 推荐使用draw方法来替换多次调用drawBitmap/drawRect/drawText。
// 当前view控件需要更新的tags
drawNativeIcon.draw(tags);
// 更新指定id
drawNativeIcon.drawRect(styles, position, id) //绘制元素为矩形区域
drawNativeIcon.drawBitmap(src, sprite, position, id) //绘制元素为图片
drawNativeIcon.drawText(text, position, styles, id) //绘制元素为文本,包括字体图标
// 比如更新drawNativeIcon 控件的纯色背景颜色
drawNativeIcon.drawRect({
color: '#0ff',
radius: '50%'
}, {}, 'iconBg');
// 比如更新drawNativeIcon 控件的字体图标颜色
drawNativeIcon.drawText('\ue600', {}, {
color: '#ccc',
fontSrc: '_www/fonts/iconfont.ttf',
size: '30px'
}, 'icon');
// 使用draw方法
drawNativeIcon.draw([
{
id: 'iconBg',
tag:'rect',
rectStyles: {
color: '#ff0',
size: '50px',
radius: '50%'
}
}, {
id: 'icon',
tag:'font',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align: 'center',
color: '#000',
size: '30px'
}
}
])
说明:
1.position 的默认值为 {top:'0px',left:'0px',width:'100%',height:'100%'},如果与默认值相同,可以传空对象。
2.需要更新的tag 如果与默认值不相同,需要重新传值。
使用webview提供的方法更新
此方法使用 webview 提供的updateSubNViews()更新控件,是集成了nativeObj方法给webview提供一个直接操作原生view控件的方法。通过要更新view控件中的id属性值匹配子View控件更新绘制内容,如果没有查找到对应id的子View控件则忽略。 此操作仅更新子View控件上绘制的内容,不会添加或删除原生子View控件对象。
var currWV = plus.webview.currentWebview();
//比如更新控件颜色
currWV.updateSubNViews([{
id: 'tabIcon',
tags: [{
id: 'iconBg',
rectStyles: {
color: '#ff0',
size: '50px',
radius: '50%'
}
}, {
id: 'icon',
text: '\ue600', //此为字体图标Unicode码'\e600'转换为'\ue600'
textStyles: {
fontSrc: '_www/fonts/iconfont.ttf',
align: 'center',
color: '#000',
size: '30px'
}
}]
}])
说明:
1.position 的默认值为 {top:'0px',left:'0px',width:'100%',height:'100%'},如果与默认值相同,可以不传。
2.需要更新的tag 如果与默认值不相同,需要重新传值。
总结:
1.以上提供两种方式更新此类view控件,实现方法基本类似,开发者可根据使用场景选择恰当的方式。
2.此类方法创建的view控件与通过subNViews节点配置方法实现的效果一样,区别在于subNViews配置需要在创建webview时就引入。但是这样配置的信息就可以在页面中通过以下方式获取到view控件的相应信息。对于处理多个view控件的自动更新方便很多,比如首页底部选项卡
var nviews = currWV.getStyle().subNViews(); //返回配置的view控件的所有信息
3.关于如何更新subNViews节点配置的view控件。请下载参考教程 中上传的附件demo。
收起阅读 »









