HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

DCloud图片上传和压缩

HBuilder

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 定位代码

HBuilder
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中实现微信登录第三方登录获取用户信息

【参考资料】

  1. 授权登录插件配置:http://ask.dcloud.net.cn/article/192
  2. 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"
}

继续阅读 »

【参考资料】

  1. 授权登录插件配置:http://ask.dcloud.net.cn/article/192
  2. 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应用实现沉浸式状态栏

HTML5+ 5+App开发 状态栏 沉浸式状态栏

开启沉浸式状态栏

沉浸式状态不支持动态设置,属于应用级的。此类参数信息,通常在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 视频教程已经发布

map

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

【示例】解决软键盘弹出时底部元素上浮的问题

固定栏 css 软键盘 弹出软键盘 HTML5+ 输入法 底部选项卡

问题描述

在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点击整个页面上移解决方法

HTML5

先给你的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控件教程

更新view控件 原生view控件 nativeObj

需求说明

此教程将针对使用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。

收起阅读 »