近日谎痢,在把某網(wǎng)站用WebView加載到App里面的時候漓帚,出現(xiàn)的一個問題「尘#看下圖
簡直了~帶著標(biāo)題還有廣告,簡直太糟糕了.而且占屏幕的空間都太大了,很不協(xié)調(diào).... 所以我們要將他們所在的div隱藏掉,首先我想到的是讓服務(wù)器的哥們重新定制一個頁面來顯示,但是...坑的是他們不管...嗚嗚嗚~~~
俗話說,靠人不如靠己,咱們自己來!!
首先讓我們看看加載網(wǎng)頁的代碼:
private WebView webView;
private WebSettings settings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
webView = (WebView) findViewById(web);
//獲取webview的setting
settings = webView.getSettings();
//設(shè)置WebView屬性笋妥,能夠執(zhí)行Javascript腳本
settings.setJavaScriptEnabled(true);
//支持緩存
settings.setAppCacheEnabled(true);
webView.setWebViewClient(new NoAdWebViewClient());
//加載需要顯示的網(wǎng)頁
webView.loadUrl("http://www.ftchinese.com/channel/commodity.html");
}
然后在火狐瀏覽器上通過Ctrl+shift+m打開手機(jī)版網(wǎng)頁(這里有一個坑,等下再表....),右擊"查看元素"的調(diào)試模式可以輕易的獲取到標(biāo)題的div
找到對應(yīng)的div了,怎么才能隱藏他吶??? 一般我們獲取某個div是通過getElementsById("xxx")來找到對應(yīng)的div,但是我們發(fā)現(xiàn)div上并沒有id這個屬性,怎么辦? 有辦法! 我們還可以根據(jù)class屬性通過document.getElementsByClassName("xxx")來找到我們想要的div元素(不懂的,自動補(bǔ)齊:http://www.runoob.com/jsref/met-document-getelementsbyclassname.html)
下面是繼承WebViewClient()實現(xiàn)隱藏標(biāo)題和廣告div的代碼:
public class NoAdWebViewClient extends WebViewClient {
private Context context;
public NoAdWebViewClient(Context context) {
this.context = context;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
String js = getClearAdDivJs(context);
Log.v("adJs",js);
view.loadUrl(js); //加載js方法代碼
view.loadUrl("javascript:hideAd();"); //調(diào)用js方法
}
public String getClearAdDivJs(Context context) {
String js = "javascript:function hideAd() {";
Resources res = context.getResources();
String[] adDivs = res.getStringArray(R.array.adBlockDiv);
for (int i = 0; i < adDivs.length; i++) {
//通過div的id屬性刪除div元素
//js += "var adDiv"+i+"= document.getElementById('"+adDivs[i]+"');if(adDiv"+i+" != null)adDiv"+i+".parentNode.removeChild(adDiv"+i+");";
//通過div的class屬性隱藏div元素
js += "var adDiv" + i + "= document.getElementsByClassName('" + adDivs[i] + "');if(adDiv" + i + " != null)" +
"{var x; for (x = 0; x < adDiv" + i + ".length; x++) {adDiv" + i + "[x].style.display='none';}}";
}
js += "}";
return js;
}
}
在onPageFinished方法里調(diào)用的js方法整理后(為方便閱讀經(jīng)過處理):
javascript:function hidehideAd() {
var adDiv0 = document.getElementsByClassName("o-nav__placeholder");
if(adDiv0 != null){
var x;
for (x= 0; x< adDiv0 .length; x++) {
adDiv0 [x].style.display = "none";
}
}
var adDiv1 = document.getElementsByClassName("site-map");
if(adDiv1 != null){
var x;
for (x= 0; x< adDiv1.length; x++) {
adDiv1[x].style.display = "none";
}
}
var adDiv2 = document.getElementsByClassName("bn-ph");
if(adDiv2 != null){
var x;
for (x= 0; x< adDiv2.length; x++) {
adDiv2[x].style.display = "none";
}
}
...
}
通過values文件夾下的arrays.xml去管理去要去掉的標(biāo)題和廣告div懊昨,遍歷adDiv的集合窄潭,組合成一段js代碼,注入到網(wǎng)頁中去掉廣告.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="adBlockDiv">
<item>o-nav__placeholder</item>
<item>site-map</item>
<item>bn-ph</item>
<item>story-theme</item>
<item>story-action-placeholder</item>
<item>story-box last-child</item>
<item>bn-ph standard</item>
<item>footer-container</item>
<item>mpu-container</item>
<item>mpu-container last-child</item>
</string-array>
</resources>
網(wǎng)頁去掉標(biāo)題和廣告的效果如下:
還有個問題,雖然這樣可以隱藏掉我們不想顯示的div,但是我們在onFinished()方法里去調(diào)用這段js代碼,就意味著要在網(wǎng)頁加載完成之后才來隱藏,出現(xiàn)的效果就是:剛開始還是會顯示標(biāo)題和廣告,等網(wǎng)頁加載完之后標(biāo)題和廣告會突然消失...(一個很不好的體驗...)
那我們怎么優(yōu)化吶?
public class NoAdWebViewClient extends WebViewClient {
private Context context;
private WebView webView;
private boolean isClose;
public NoAdWebViewClient(Context context,WebView webView) {
this.context = context;
this.webView = webView;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if(isClose){ //如果線程正在運(yùn)行就不用重新開啟一個線程了
return;
}
new Thread(new Runnable() {
@Override
public void run() {
isClose = true;
while (isClose){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(0x001);
}
}
}).start();
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
String js = getClearAdDivJs(context);
Log.v("adJs",js);
view.loadUrl(js); //加載js方法代碼
view.loadUrl("javascript:hideAd();"); //調(diào)用js方法
}
};
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
isClose = false;
}
}
在NoAdWebViewClient里面我們重寫onPageStarted方法酵颁,因為Android機(jī)制不允許在主線程做耗時和在子線程更新UI,所以我們開啟一個線程嫉你,每100毫秒的循環(huán)注入js,并且利用Handler去注入js.然后在onPageFinished內(nèi)關(guān)閉線程.這樣之后躏惋,即使網(wǎng)絡(luò)很慢幽污,在沒有回調(diào)onPageFinished的時候,也不會出現(xiàn)廣告了簿姨。
總結(jié):
第一點 : 上面javaScript方法中:
getElementsByTagName("xxx")是通過標(biāo)簽的名稱獲取,結(jié)果是一個標(biāo)簽數(shù)組
getElementsByClassName("xxx")是通過標(biāo)簽上定義的class屬性獲取,結(jié)果是一個標(biāo)簽數(shù)組
getElementById("xxx")是通過標(biāo)簽上定義的id屬性獲取,結(jié)果是單個標(biāo)簽
第二點 : 為什么要用火狐瀏覽器打開手機(jī)版的網(wǎng)頁?
因為手機(jī)加載的網(wǎng)頁和你在pc加載的網(wǎng)頁地址不一樣距误,當(dāng)你用手機(jī)加載的時候,會自動重定向到m.xx.com這樣的站點(m指mobile加載的扁位,網(wǎng)頁加載時一般是www.xx.com)准潭。所以會造成網(wǎng)頁上帶有 Class的標(biāo)簽,在手機(jī)上加載時域仇,Class標(biāo)簽就不見了刑然,造成的后果是明明使用getElementByClassName(“”XXX“”).remove()處理過了,但是沒有起作用暇务。所以要直接打開手機(jī)版查看源碼
第三點 : 頁面閃爍問題
雖然代碼經(jīng)過開啟子線程通過handler來優(yōu)化了網(wǎng)頁加載過程中的標(biāo)題和廣告顯示問題,但是這種去標(biāo)題的方式還有個小不美的地方,因為本質(zhì)是加載兩次Url,一次是原本的Url,一次是處理過的URL ,所以剛開始會閃一次 . (這個問題還沒有解決,歡迎有思路的小伙伴一起探討~~~)
(文章參考地址:http://www.reibang.com/p/d793c8d4ff81)