在WebView中嵌入android原生控件
在WebView加载的web页面特定位置展示原生控件的内容,并跟随web元素滑动。
实现思路:
- html文档流中插入占位元素初始高度为0.
- 当页面加载完成后获取元素的位置,把原生控件移动到此位置.
- 设置占位元素高度为原生控件的高度.
效果:
黄色背景为TextView,其他为html内容
html中插入占位元素
其中id为的advertisement元素 为需要插入原生控件的的位置.
<div id="section1"></div>
<div id="advertisement"></div>
<div id="section2"></div>
获取元素的位置,移动原生控件.
这里在onPageFinished(WebView view, String url)回调中,获取元素的位置,调用js方法getAdPosition获取位置(js传回的位置单位为dp),然后通过setTranslationY移动原生控件到id为advertisement的html元素位置处.
mWebview.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
L.e("mWebview:",mWebview.getChildCount()+"");
TextView textView=new TextView(getApplication());
textView.setTextColor(Color.GRAY);
textView.setTextSize(20f);
textView.setBackgroundColor(Color.YELLOW);
textView.setText("WebActivity TextView ");
textView.setGravity(Gravity.CENTER);
textView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,DensityUtil.dp2px(AndroidApplication.getContext(),TV_HEIGHT)));
mWebview .evaluateJavascript("javaScript:getAdPosition()",
new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.i("getAdPosition:",value);
textView.setTranslationY(DensityUtil.dp2px(WebActivity.this,Float.parseFloat(value)));
mWebview.addView(textView);
mWebview.loadUrl("javaScript:setAdHeight("+TV_HEIGHT+")");
}
});
}
});
设置占位元素高度
为了避免覆盖html的内容,还需要调用js方法setAdHeight把advertisement这个div设置为和原生控件同样的高度
js中的两个方法
<script type="text/javascript">
function getAdPosition() {
var advertisement = document.getElementById("advertisement");
return advertisement.offsetTop;
}
function setAdHeight(height) {
var advertisement = document.getElementById("advertisement");
advertisement.style.height=height+"px";
}
</script>
当然如果web端不提供js方法供调用也是可以的,那就把js方法也在本地代码里定义并调用.如下:
mWebview.evaluateJavascript("javaScript: function getAdPosition() {\n"
+ " var advertisement = document.getElementById(\"advertisement\");\n"
+ " return advertisement.offsetTop;\n"
+ " };getAdPosition()",
new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.i("getAdPosition:", value);
textView.setTranslationY(DensityUtil.dp2px(WebActivity.this, Float.parseFloat(value)));
mWebview.addView(textView);
mWebview.loadUrl("javaScript: function setAdHeight(height) {\n"
+ " var advertisement = document.getElementById(\"advertisement\");\n"
+ " advertisement.style.height=height+\"px\";\n"
+ " };javaScript:setAdHeight("+TV_HEIGHT+");");
}
});
线上页面
以上介绍了本地html的操作方法,那么加载在线页面,或者是第三方的网站还能这样操作吗?
也是可以的,方法基本一致。
这里以百度首页为例,目的是在搜索框上面插入自己的原生组件,这里找到搜索框的id为index-form,获取位置的操作同上,
出于简单起见这里不再插入元素占位,而是直接更改搜索框的样式,当插入原生组件后修改搜索框的marginTop值。
mWebView.evaluateJavascript("javaScript: function getAdPosition() {\n"
+ " var advertisement = document.getElementById(\"index-form\");\n"
+ " return advertisement.offsetTop;\n"
+ " };getAdPosition()",
new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
Log.e("getAdPosition:", value);
textView.setTranslationY(DensityUtil.dp2px(WebActivity.this, Float.parseFloat(value)));
mWebView.addView(textView);
mWebView.loadUrl("javaScript: function setAdHeight(height) {\n"
+ " var advertisement = document.getElementById(\"index-form\");\n"
+ " advertisement.style.marginTop=height+\"px\";\n"
+ " }; setAdHeight("+(TV_HEIGHT+16)+");");
}
});