HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

感谢80万开发者厚爱,HBuilder8.0正式发布 【内含重要性能优化新策略】

小程序 性能

从2014年正式发布,3岁多的HBuilder正式发布了8.0,巧的是HBuilder的开发者数量也正好达到了80万。
中国HTML5开发者一共有多少我们不知道,但HBuilder确认是中国的主流HTML5开发工具无疑了。
在此之前,中国人制作开发工具从未成功过,有尝试者,都败在海外产品下。
如今我们终于可以自豪的说,HBuilder,可以和任何海外顶尖开发工具平起平坐!

成为主流开发工具,是一种荣誉,更是一种责任。
中国的HTML5发展,DCloud可以、也应当做更多事。

在过去的2016年,HTML5行业发生了重大的变化。不是喊HTML5元年来了,这次不是狼来了,是狼真的来了。
在微信小程序和流应用的影响下,人们终于认识到,HTML5经过强化后,是完全可达到商用标准的。
微信小程序虽然是私有语法,但wxml在手机端运行时也会翻译成html,其对HTML5的各种增强优化措施比如:多webview,采用webview动画来替代低效的DOM动画;采用c/s模式提升弱网表现,虽然有client端但可以即点即用。
这些是不是和流应用很像?
当然更真实的情况是,DCloud在2015年就给微信团队演示了流应用,DCloud的流应用让微信看到了一个新技术拐点的到来,我们如何优化html5的体验,又如何强化html5的优势,包括即扫即得的快码、像发消息一样分享应用,包括扫码、分享的直达二级页面,都成为目前微信小程序的重要应用场景。
不过我们并不埋怨什么,而是非常感谢微信,因为仅靠DCloud一家是难以快速教育市场的,没有微信小程序,不会有这么多人意识到强化过的HTML5可以达到原生体验。
当html5将替代原生成为主流技术平台的大幕拉起时,我们要做出比微信小程序体验更好、功能UI更加丰富、商业模式更加开放的产品,给开发者和用户更自由、更优质的选择。

在过去的2016年,我们也很高兴的看到一大批优秀的大型App入驻流应用平台,我们对html5优势的发掘,在商用环境中被证明,出现了一批体验良好、付费转化率达到原生水准、而获客成本又数倍低于原生App的案例,给开发商和用户带来了真真切切的价值。

可以看看这些操作视频:
36kr流应用
2秒快速启动、快速切换窗体、窗体滑动跟手、脱线可用,完全原生体验。

唯品会流应用
2秒快速启动、左右tab跟手拖动切换、下拉刷新、快速窗体进入,已在商用环境中取到良好证明,付费转化率、获客成本各项数据指标都获得成功。

体验方式,下载流应用管理器

HBuilder8.0,是HBuilder的一个里程碑产品,这次更新大幅强化了HTML5的性能体验,在启动速度、窗体切换速度、拖动等人机交互流畅度上达到了新的高度。
过去的HBuilder版本,已经帮助很多开发商取得成功,完全基于HTML5+打包的App中,美丽修行在Appstore健康健美分类中排名14、弈客围棋在Appstore体育分类中排名52、悟空理财在Appstore财务分类中排名86……
相信HBuilder8.0的发布,能帮助更多HTML5开发者取得成功,收获更多用户!
点击如下链接,了解HBuilder 8.0 更新日志及性能优化解读:http://ask.dcloud.net.cn/question/27999

继续阅读 »

从2014年正式发布,3岁多的HBuilder正式发布了8.0,巧的是HBuilder的开发者数量也正好达到了80万。
中国HTML5开发者一共有多少我们不知道,但HBuilder确认是中国的主流HTML5开发工具无疑了。
在此之前,中国人制作开发工具从未成功过,有尝试者,都败在海外产品下。
如今我们终于可以自豪的说,HBuilder,可以和任何海外顶尖开发工具平起平坐!

成为主流开发工具,是一种荣誉,更是一种责任。
中国的HTML5发展,DCloud可以、也应当做更多事。

在过去的2016年,HTML5行业发生了重大的变化。不是喊HTML5元年来了,这次不是狼来了,是狼真的来了。
在微信小程序和流应用的影响下,人们终于认识到,HTML5经过强化后,是完全可达到商用标准的。
微信小程序虽然是私有语法,但wxml在手机端运行时也会翻译成html,其对HTML5的各种增强优化措施比如:多webview,采用webview动画来替代低效的DOM动画;采用c/s模式提升弱网表现,虽然有client端但可以即点即用。
这些是不是和流应用很像?
当然更真实的情况是,DCloud在2015年就给微信团队演示了流应用,DCloud的流应用让微信看到了一个新技术拐点的到来,我们如何优化html5的体验,又如何强化html5的优势,包括即扫即得的快码、像发消息一样分享应用,包括扫码、分享的直达二级页面,都成为目前微信小程序的重要应用场景。
不过我们并不埋怨什么,而是非常感谢微信,因为仅靠DCloud一家是难以快速教育市场的,没有微信小程序,不会有这么多人意识到强化过的HTML5可以达到原生体验。
当html5将替代原生成为主流技术平台的大幕拉起时,我们要做出比微信小程序体验更好、功能UI更加丰富、商业模式更加开放的产品,给开发者和用户更自由、更优质的选择。

在过去的2016年,我们也很高兴的看到一大批优秀的大型App入驻流应用平台,我们对html5优势的发掘,在商用环境中被证明,出现了一批体验良好、付费转化率达到原生水准、而获客成本又数倍低于原生App的案例,给开发商和用户带来了真真切切的价值。

可以看看这些操作视频:
36kr流应用
2秒快速启动、快速切换窗体、窗体滑动跟手、脱线可用,完全原生体验。

唯品会流应用
2秒快速启动、左右tab跟手拖动切换、下拉刷新、快速窗体进入,已在商用环境中取到良好证明,付费转化率、获客成本各项数据指标都获得成功。

体验方式,下载流应用管理器

HBuilder8.0,是HBuilder的一个里程碑产品,这次更新大幅强化了HTML5的性能体验,在启动速度、窗体切换速度、拖动等人机交互流畅度上达到了新的高度。
过去的HBuilder版本,已经帮助很多开发商取得成功,完全基于HTML5+打包的App中,美丽修行在Appstore健康健美分类中排名14、弈客围棋在Appstore体育分类中排名52、悟空理财在Appstore财务分类中排名86……
相信HBuilder8.0的发布,能帮助更多HTML5开发者取得成功,收获更多用户!
点击如下链接,了解HBuilder 8.0 更新日志及性能优化解读:http://ask.dcloud.net.cn/question/27999

收起阅读 »

获取当前app的版本号

plus.runtime.version; //获取当前版本号  

注:此功能只有在打包后才起作用。

plus.runtime.version; //获取当前版本号  

注:此功能只有在打包后才起作用。

hbuilder App怎么调用node.js?0u

HBuilder

hbuilder App怎么调用node.js?

hbuilder App怎么调用node.js?

获取网络类型

// H5 plus事件处理  
function plusReady(){  
    var types = {};   
                types[plus.networkinfo.CONNECTION_UNKNOW]="网络连接状态未知";   
                types[plus.networkinfo.CONNECTION_NONE]="未连接网络";   
                types[plus.networkinfo.CONNECTION_ETHERNET]="有线网络";   
                types[plus.networkinfo.CONNECTION_WIFI]="WIFI";   
                types[plus.networkinfo.CONNECTION_CELL2G]="2G";   
                types[plus.networkinfo.CONNECTION_CELL3G]="3G";   
                types[plus.networkinfo.CONNECTION_CELL4G]="4G";   
                console.log("Network: " + types[plus.networkinfo.getCurrentType()]);  
}  
if(window.plus){  
    plusReady();  
}else{  
    document.addEventListener("plusready",plusReady,false);  
}
继续阅读 »
// H5 plus事件处理  
function plusReady(){  
    var types = {};   
                types[plus.networkinfo.CONNECTION_UNKNOW]="网络连接状态未知";   
                types[plus.networkinfo.CONNECTION_NONE]="未连接网络";   
                types[plus.networkinfo.CONNECTION_ETHERNET]="有线网络";   
                types[plus.networkinfo.CONNECTION_WIFI]="WIFI";   
                types[plus.networkinfo.CONNECTION_CELL2G]="2G";   
                types[plus.networkinfo.CONNECTION_CELL3G]="3G";   
                types[plus.networkinfo.CONNECTION_CELL4G]="4G";   
                console.log("Network: " + types[plus.networkinfo.getCurrentType()]);  
}  
if(window.plus){  
    plusReady();  
}else{  
    document.addEventListener("plusready",plusReady,false);  
}
收起阅读 »

localStorage 获取长度和值

    for(var i=localStorage.length - 1 ; i >=0; i--){  
                console.log("log:"+localStorage.key(i));  
                  console.log('第'+ (i+1) +'条数据的键值为:' + localStorage.key(i) +',数据为:' + localStorage.getItem(localStorage.key(i)));  
                   }
继续阅读 »
    for(var i=localStorage.length - 1 ; i >=0; i--){  
                console.log("log:"+localStorage.key(i));  
                  console.log('第'+ (i+1) +'条数据的键值为:' + localStorage.key(i) +',数据为:' + localStorage.getItem(localStorage.key(i)));  
                   }
收起阅读 »

网络状态

//=======================手机网络状态=============================  

                document.addEventListener("netchange", function() {  
                var network = plus.networkinfo.getCurrentType();  
                if(network < 2) {  
                if(this.network > 1) {  
                plus.nativeUI.toast('您的网络已断开', undefined, '期待乐');  
                }  
                }if(this.network == 3 && network > 3) {  
                    plus.nativeUI.toast('您网络已从wifi切换到蜂窝网络,浏览会产生流量', undefined, '期待乐', '我知道了');  
                }  
                this.network=network;  
                });
继续阅读 »
//=======================手机网络状态=============================  

                document.addEventListener("netchange", function() {  
                var network = plus.networkinfo.getCurrentType();  
                if(network < 2) {  
                if(this.network > 1) {  
                plus.nativeUI.toast('您的网络已断开', undefined, '期待乐');  
                }  
                }if(this.network == 3 && network > 3) {  
                    plus.nativeUI.toast('您网络已从wifi切换到蜂窝网络,浏览会产生流量', undefined, '期待乐', '我知道了');  
                }  
                this.network=network;  
                });
收起阅读 »

退出

退出
var first = null;  
                mui.back = function() {  
                //首次按键,提示‘再按一次退出应用’  
                if (!first) {  
                first = new Date().getTime();  
                mui.toast('再按一次退出应用');  
                setTimeout(function() {  
                first = null;  
                }, 1000);  
                } else {  
                if (new Date().getTime() - first < 1000) {  
                plus.runtime.quit();  
                }  
                }  
                };
继续阅读 »
var first = null;  
                mui.back = function() {  
                //首次按键,提示‘再按一次退出应用’  
                if (!first) {  
                first = new Date().getTime();  
                mui.toast('再按一次退出应用');  
                setTimeout(function() {  
                first = null;  
                }, 1000);  
                } else {  
                if (new Date().getTime() - first < 1000) {  
                plus.runtime.quit();  
                }  
                }  
                };
收起阅读 »

多语言

多语言
if(window.plus){  
                  plusReady();  
                }else{  
                  document.addEventListener("plusready",plusReady,false);  
                }  
                function plusReady(){  
                var Language=localStorage.getItem("Language");  
                 if(Language=="zh"){  
                        var dynamic=document.createElement("script");  
                        dynamic.src="js/locale_en_US.js";  
                        document.head.appendChild(dynamic);  
                    }  
                }  
继续阅读 »
if(window.plus){  
                  plusReady();  
                }else{  
                  document.addEventListener("plusready",plusReady,false);  
                }  
                function plusReady(){  
                var Language=localStorage.getItem("Language");  
                 if(Language=="zh"){  
                        var dynamic=document.createElement("script");  
                        dynamic.src="js/locale_en_US.js";  
                        document.head.appendChild(dynamic);  
                    }  
                }  
收起阅读 »

分享实现类似QQ的自动登陆的方法,代码比较简单,主要是给大家提供一个实现逻辑,具体的要结合自身的app来做

在官方的群里面发现很多朋友都希望能实现自动登陆的效果,但是可能因为没有做过app,所以缺乏相应的思路,今天我来和大家分享一下我的一个思路
1.首先我们在index.html页面下面进行是否登陆的判断,以及执行自动登陆等操作
index页面为你的底部导航页,因为底部导航页是你进入app的启动页面
index页面的代码如下

 //监听加载事件,执行自动登陆方法  
        window.addEventListener('load',function(){  
            loginagin();  
        });  
         //定义自动登陆的方法,如果本地存储存在则执行主动登陆,如果不存在则打开登陆页面,隐藏index页面  
                var ph=localStorage.getItem('ph');//本地存储,存储你的用户名  
        var passwrod =localStorage.getItem('password');//本地存储,存储你的密码  
//真实项目下应该存储一个服务器返回的token,通过token来实现自动登陆,保护用户的数据安全  
         function loginagin()  
        {   if (localStorage.getItem('ph')&&localStorage.getItem('password')) {  

                        mui.post('登陆接口地址',{  //请求接口地址  
                               username:ph,  
                               password:passwrod  

                            },  
                            function(data){ //data为服务器端返回数据  
                               var lg=JSON.parse(data);    
                             console.log(JSON.stringify(data));  
                             console.log(data.status);  
                             console.log(data.msg);  
                             localStorage.setItem('user',data.user_id);  
                             localStorage.setItem('token',data.access_token);  
                             localStorage.setItem('status',data.status);  
                       //通知个人中心页,更新用户数据  
                                 var upLogin =['ihome.html']  
                            ca.sendNotice(upLogin,'update_user',{  

                             userid:lg.user_id ,  
                             token:lg.access_token,  
                             status:lg.status     
                        });  

                            },'json'  
                        );  

                    }   
                    else   
                    {    

                        mui.plusReady(function(){  
                            plus.webview.open('login.html','login.html');  
                            plus.webview.currentWebview().hide();//不可以把index页面关闭否则无非执行通知等  
                        });  

                    }  

                };  

....................................................................................................................................................
2.在登陆页面,执行登陆完成后把inde页面显示出来

 //登陆成功后把index页面显示出来,并关闭登陆页面  
                        mui.plusReady(function(){  
                          plus.webview.getLaunchWebview().show();                 
                        });  
                        ca.closeCurrentInterface();

到此整个的业务逻辑就完成了实际测试了一下是可以实现类似qq登陆的效果。代码比较简单,大神勿喷!!!!!!!!!!!!!
第一次发帖,希望大家给点鼓励!!!!!

继续阅读 »

在官方的群里面发现很多朋友都希望能实现自动登陆的效果,但是可能因为没有做过app,所以缺乏相应的思路,今天我来和大家分享一下我的一个思路
1.首先我们在index.html页面下面进行是否登陆的判断,以及执行自动登陆等操作
index页面为你的底部导航页,因为底部导航页是你进入app的启动页面
index页面的代码如下

 //监听加载事件,执行自动登陆方法  
        window.addEventListener('load',function(){  
            loginagin();  
        });  
         //定义自动登陆的方法,如果本地存储存在则执行主动登陆,如果不存在则打开登陆页面,隐藏index页面  
                var ph=localStorage.getItem('ph');//本地存储,存储你的用户名  
        var passwrod =localStorage.getItem('password');//本地存储,存储你的密码  
//真实项目下应该存储一个服务器返回的token,通过token来实现自动登陆,保护用户的数据安全  
         function loginagin()  
        {   if (localStorage.getItem('ph')&&localStorage.getItem('password')) {  

                        mui.post('登陆接口地址',{  //请求接口地址  
                               username:ph,  
                               password:passwrod  

                            },  
                            function(data){ //data为服务器端返回数据  
                               var lg=JSON.parse(data);    
                             console.log(JSON.stringify(data));  
                             console.log(data.status);  
                             console.log(data.msg);  
                             localStorage.setItem('user',data.user_id);  
                             localStorage.setItem('token',data.access_token);  
                             localStorage.setItem('status',data.status);  
                       //通知个人中心页,更新用户数据  
                                 var upLogin =['ihome.html']  
                            ca.sendNotice(upLogin,'update_user',{  

                             userid:lg.user_id ,  
                             token:lg.access_token,  
                             status:lg.status     
                        });  

                            },'json'  
                        );  

                    }   
                    else   
                    {    

                        mui.plusReady(function(){  
                            plus.webview.open('login.html','login.html');  
                            plus.webview.currentWebview().hide();//不可以把index页面关闭否则无非执行通知等  
                        });  

                    }  

                };  

....................................................................................................................................................
2.在登陆页面,执行登陆完成后把inde页面显示出来

 //登陆成功后把index页面显示出来,并关闭登陆页面  
                        mui.plusReady(function(){  
                          plus.webview.getLaunchWebview().show();                 
                        });  
                        ca.closeCurrentInterface();

到此整个的业务逻辑就完成了实际测试了一下是可以实现类似qq登陆的效果。代码比较简单,大神勿喷!!!!!!!!!!!!!
第一次发帖,希望大家给点鼓励!!!!!

收起阅读 »

mui选择器和dom获取元素的区别(记得把mui对象转为dom对象才能调用用dom方法)

<!DOCTYPE html>
<html>

<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
    <title></title>  
    <script src="js/mui.min.js"></script>  
    <link href="css/mui.min.css" rel="stylesheet" />  

</head>  

<body>  
    <div id="div1">div1</div>  
    <div id="div">div2</div>  
    <div id="div2" class="nw1">div3</div>  
    <input type="button" name="text" id="" value="666" />  
    <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>  
    <script type="text/javascript">  
        console.log(mui('div')[0].innerHTML);//mui做dom操作必须先加【0】转为dom元素  
        console.log(mui('input')[0].value);//mui括号里的可以是id、标签、class属性  
        //getart  
        var lui=mui('input')[0];//mui方式获取input对象  
         console.log(lui.attributes.type.nodeValue);//获取input标签的type属性值  
        console.log(lui.attributes['name'].nodeValue);//另一种获取input标签的name属性值  
        console.log(document.getElementById('div').innerHTML);//这里是js的方法  
        var nw=document.getElementById('div2');  
        nw.setAttribute('demo','demo1');//设置自定义属性和值  
        console.log(nw.attributes['demo'].nodeValue);  
        var nw1=document.getElementsByClassName('nw1')[0].innerHTML;  
        console.log(nw1);  
        (function($){//这里是在闭包里使用mui获取元素  
            console.log($('div')[0].innerHTML);  
        })(mui);  
    </script>  
</body>  

</html>

继续阅读 »

<!DOCTYPE html>
<html>

<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
    <title></title>  
    <script src="js/mui.min.js"></script>  
    <link href="css/mui.min.css" rel="stylesheet" />  

</head>  

<body>  
    <div id="div1">div1</div>  
    <div id="div">div2</div>  
    <div id="div2" class="nw1">div3</div>  
    <input type="button" name="text" id="" value="666" />  
    <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>  
    <script type="text/javascript">  
        console.log(mui('div')[0].innerHTML);//mui做dom操作必须先加【0】转为dom元素  
        console.log(mui('input')[0].value);//mui括号里的可以是id、标签、class属性  
        //getart  
        var lui=mui('input')[0];//mui方式获取input对象  
         console.log(lui.attributes.type.nodeValue);//获取input标签的type属性值  
        console.log(lui.attributes['name'].nodeValue);//另一种获取input标签的name属性值  
        console.log(document.getElementById('div').innerHTML);//这里是js的方法  
        var nw=document.getElementById('div2');  
        nw.setAttribute('demo','demo1');//设置自定义属性和值  
        console.log(nw.attributes['demo'].nodeValue);  
        var nw1=document.getElementsByClassName('nw1')[0].innerHTML;  
        console.log(nw1);  
        (function($){//这里是在闭包里使用mui获取元素  
            console.log($('div')[0].innerHTML);  
        })(mui);  
    </script>  
</body>  

</html>

收起阅读 »

app开发视频教程汇总还有微信小程序开发教程 ^_^ 赶紧来一起学习吧!!

HelloH5 mui


mui 视频教程
http://www.hcoder.net/course/info_211.html

h5+ 视频教程
http://www.hcoder.net/course/info_212.html

app开发教程 - 《仿今日头条客户端》
http://www.hcoder.net/course/info_214.html

h.js - 致力于优化mui的dom操作及h5+的封装,完美兼容mui,提供更高效的开发。
http://www.hcoder.net/tutorials/info_147.html

微信小程序开发视频教程
http://www.hcoder.net/course/info_221.html

汇总地址
http://www.hcoder.net/course

我们一直在努力! 为了更好、更快的开发!

继续阅读 »


mui 视频教程
http://www.hcoder.net/course/info_211.html

h5+ 视频教程
http://www.hcoder.net/course/info_212.html

app开发教程 - 《仿今日头条客户端》
http://www.hcoder.net/course/info_214.html

h.js - 致力于优化mui的dom操作及h5+的封装,完美兼容mui,提供更高效的开发。
http://www.hcoder.net/tutorials/info_147.html

微信小程序开发视频教程
http://www.hcoder.net/course/info_221.html

汇总地址
http://www.hcoder.net/course

我们一直在努力! 为了更好、更快的开发!

收起阅读 »

解决安卓全屏“FLAG_FULLSCREEN”状态下“adjustResize”失效,全屏状态下WebView的输入框被软键盘挡住的问题

软键盘

  目前,5+SDK在全屏模式下问题比较多,比如webview的show和hide方法会概率性失效(调用后没反应)、软键盘挡住当前具有焦点的文本输入框等问题。
  本篇文章的意图,希望官方看到后可以引入到5+SDK中,以便解决全屏模式下,软键盘盖住文本框的问题。

  沿着这个问题的线索,可以追溯到:http://code.google.com/p/android/issues/detail?id=5497 ,安卓官方问题回馈帖,这个问题的代号为“5497” ,就这个问题帖的回复来看,该问题困惑了许多人数年之久,问题发布日期“Dec 16, 2009”,现在我在安卓4.4.2环境运行,这个问题依旧存在。在此推荐这其中的一个解决方法,来自:stackoverflow.com,实测有效。


[java] view plaincopy  
public class AndroidBug5497Workaround {  
    // For more information, see https://code.google.com/p/android/issues/detail?id=5497  
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.  
    public static void assistActivity (Activity activity) {  
        new AndroidBug5497Workaround(activity);  
    }  
    private View mChildOfContent;  
    private int usableHeightPrevious;  
    private FrameLayout.LayoutParams frameLayoutParams;  
    private AndroidBug5497Workaround(Activity activity) {  
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);  
        mChildOfContent = content.getChildAt(0);  
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {  
            public void onGlobalLayout() {  
                possiblyResizeChildOfContent();  
            }  
        });  
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();  
    }  
    private void possiblyResizeChildOfContent() {  
        int usableHeightNow = computeUsableHeight();  
        if (usableHeightNow != usableHeightPrevious) {  
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();  
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;  
            if (heightDifference > (usableHeightSansKeyboard/4)) {  
                // keyboard probably just became visible  
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;  
            } else {  
                // keyboard probably just became hidden  
                frameLayoutParams.height = usableHeightSansKeyboard;  
            }  
            mChildOfContent.requestLayout();  
            usableHeightPrevious = usableHeightNow;  
        }  
    }  
    private int computeUsableHeight() {  
        Rect r = new Rect();  
        mChildOfContent.getWindowVisibleDisplayFrame(r);  
        return (r.bottom - r.top);  
    }  
}  

在Activity/Fragment的onCreate()/onCreateView()里调用AndroidBug5497Workaround.assistActivity(Activity);代码搬运,希望能够帮助到各位。

另见:
必须在setContentView()后面添加AndroidBug5497Workaround.assistActivity(this);

Based on yghm is workaround, I coded up a convenience class that allows me to solve the problem with a one-liner (after adding the new class to my source code of course). The one-liner is:  
     AndroidBug5497Workaround.assistActivity(this);  
And the implementation class is:  
public class AndroidBug5497Workaround {  
    // For more information, see https://code.google.com/p/android/issues/detail?id=5497  
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.  
    public static void assistActivity (Activity activity) {  
        new AndroidBug5497Workaround(activity);  
    }  
    private View mChildOfContent;  
    private int usableHeightPrevious;  
    private FrameLayout.LayoutParams frameLayoutParams;  
    private AndroidBug5497Workaround(Activity activity) {  
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);  
        mChildOfContent = content.getChildAt(0);  
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {  
            public void onGlobalLayout() {  
                possiblyResizeChildOfContent();  
            }  
        });  
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();  
    }  
    private void possiblyResizeChildOfContent() {  
        int usableHeightNow = computeUsableHeight();  
        if (usableHeightNow != usableHeightPrevious) {  
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();  
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;  
            if (heightDifference > (usableHeightSansKeyboard/4)) {  
                // keyboard probably just became visible  
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;  
            } else {  
                // keyboard probably just became hidden  
                frameLayoutParams.height = usableHeightSansKeyboard;  
            }  
            mChildOfContent.requestLayout();  
            usableHeightPrevious = usableHeightNow;  
        }  
    }  
    private int computeUsableHeight() {  
        Rect r = new Rect();  
        mChildOfContent.getWindowVisibleDisplayFrame(r);  
        return (r.bottom - r.top);  
    }  
}  
Hope this helps someone.  
继续阅读 »

  目前,5+SDK在全屏模式下问题比较多,比如webview的show和hide方法会概率性失效(调用后没反应)、软键盘挡住当前具有焦点的文本输入框等问题。
  本篇文章的意图,希望官方看到后可以引入到5+SDK中,以便解决全屏模式下,软键盘盖住文本框的问题。

  沿着这个问题的线索,可以追溯到:http://code.google.com/p/android/issues/detail?id=5497 ,安卓官方问题回馈帖,这个问题的代号为“5497” ,就这个问题帖的回复来看,该问题困惑了许多人数年之久,问题发布日期“Dec 16, 2009”,现在我在安卓4.4.2环境运行,这个问题依旧存在。在此推荐这其中的一个解决方法,来自:stackoverflow.com,实测有效。


[java] view plaincopy  
public class AndroidBug5497Workaround {  
    // For more information, see https://code.google.com/p/android/issues/detail?id=5497  
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.  
    public static void assistActivity (Activity activity) {  
        new AndroidBug5497Workaround(activity);  
    }  
    private View mChildOfContent;  
    private int usableHeightPrevious;  
    private FrameLayout.LayoutParams frameLayoutParams;  
    private AndroidBug5497Workaround(Activity activity) {  
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);  
        mChildOfContent = content.getChildAt(0);  
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {  
            public void onGlobalLayout() {  
                possiblyResizeChildOfContent();  
            }  
        });  
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();  
    }  
    private void possiblyResizeChildOfContent() {  
        int usableHeightNow = computeUsableHeight();  
        if (usableHeightNow != usableHeightPrevious) {  
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();  
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;  
            if (heightDifference > (usableHeightSansKeyboard/4)) {  
                // keyboard probably just became visible  
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;  
            } else {  
                // keyboard probably just became hidden  
                frameLayoutParams.height = usableHeightSansKeyboard;  
            }  
            mChildOfContent.requestLayout();  
            usableHeightPrevious = usableHeightNow;  
        }  
    }  
    private int computeUsableHeight() {  
        Rect r = new Rect();  
        mChildOfContent.getWindowVisibleDisplayFrame(r);  
        return (r.bottom - r.top);  
    }  
}  

在Activity/Fragment的onCreate()/onCreateView()里调用AndroidBug5497Workaround.assistActivity(Activity);代码搬运,希望能够帮助到各位。

另见:
必须在setContentView()后面添加AndroidBug5497Workaround.assistActivity(this);

Based on yghm is workaround, I coded up a convenience class that allows me to solve the problem with a one-liner (after adding the new class to my source code of course). The one-liner is:  
     AndroidBug5497Workaround.assistActivity(this);  
And the implementation class is:  
public class AndroidBug5497Workaround {  
    // For more information, see https://code.google.com/p/android/issues/detail?id=5497  
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.  
    public static void assistActivity (Activity activity) {  
        new AndroidBug5497Workaround(activity);  
    }  
    private View mChildOfContent;  
    private int usableHeightPrevious;  
    private FrameLayout.LayoutParams frameLayoutParams;  
    private AndroidBug5497Workaround(Activity activity) {  
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);  
        mChildOfContent = content.getChildAt(0);  
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {  
            public void onGlobalLayout() {  
                possiblyResizeChildOfContent();  
            }  
        });  
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();  
    }  
    private void possiblyResizeChildOfContent() {  
        int usableHeightNow = computeUsableHeight();  
        if (usableHeightNow != usableHeightPrevious) {  
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();  
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;  
            if (heightDifference > (usableHeightSansKeyboard/4)) {  
                // keyboard probably just became visible  
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;  
            } else {  
                // keyboard probably just became hidden  
                frameLayoutParams.height = usableHeightSansKeyboard;  
            }  
            mChildOfContent.requestLayout();  
            usableHeightPrevious = usableHeightNow;  
        }  
    }  
    private int computeUsableHeight() {  
        Rect r = new Rect();  
        mChildOfContent.getWindowVisibleDisplayFrame(r);  
        return (r.bottom - r.top);  
    }  
}  
Hope this helps someone.  
收起阅读 »