Android 本地HTML螢幕適配的一種方案
阿新 • • 發佈:2019-01-29
前言:在Android開發中WebView載入網頁,網頁的適配應該是前端來處理的,畢竟客戶端的對網頁的控制是有限的。但是如果有一個本地的網頁而且該網頁的body
是固定寬度的,讓我們去適配所有裝置還是比較頭疼的,當然這種應用場景是很罕見的,儘管如此我們還是討論下該問題。
通常的網頁適配
// 設定載入進來的頁面自適應手機螢幕
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setLoadWithOverviewMode(true);
一般情況下客戶端只需要設定如上兩行就可以了,當然這兩行可以解決絕大部分網頁的適配問題。第一行就是設定WebView支援viewpoart,第二行是設定網頁超過螢幕寬度時重新佈局為螢幕寬度。
如果body
設定了確切值
儘管這種在前段開發中是要極力避免的,但有時候為了方便開發還是採用了這種方式。
這裡可以採用獲取body
的值然後根據WebView控制元件的寬度與body
的寬度計算一個比例,然後設定給網頁設定一個縮放比例。
JS
獲取body
寬度
- 定義
JS
介面
class HTMLWidthInterface {
@JavascriptInterface
public void getContentWidth(String value) {
if (value != null) {
int bodyWidth = Integer.parseInt(value );
}
}
}
- 設定網頁載入後呼叫
JS
介面返回body
寬度
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new HTMLWidthInterface(), "HTMLWidth");
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
mWebView.loadUrl("javascript:window.HTMLWidth.getContentWidth(document.body.offsetWidth);" );
}
});
計算縮放比例
private void htmlAdjustWithPageWidth(float bodyWidth, String html, WebView webView) {
// 計算要縮放的比例
DisplayMetrics metric = new DisplayMetrics();
((Activity)mContext).getWindowManager().getDefaultDisplay().getMetrics(metric);
float density = metric.density; // 螢幕密度
float scale = webView.getMeasuredWidth() / density / bodyWidth;
String insertText = "<meta name=\"viewport\" content=\"width="+ bodyWidth +"px initial-scale="+ scale
+ ", minimum-scale=0.1, maximum-scale=10.0, user-scalable=no\"/>";
insertBehindText(new File(html), "<head>", insertText);
}
在HTML插入viewpoart
資訊
/**
* 在指定文字之後插入一段文字
*
* @param file
* @param targetStr
* @param insertStr
* @return void:
* @version 1.0
* @date 2015-9-2
* @Author zhou.wenkai
*/
public void insertBehindText(File file, String targetStr, String insertStr) {
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
bufr = new BufferedReader(isr);
StringBuffer buf = new StringBuffer();
String line = null;
while ((line = bufr.readLine()) != null) {
// 儲存原文字
buf = buf.append(line);
// 儲存要插入文字
if(line.contains(targetStr)) {
buf.append(insertStr);
}
// 新增換行符號
buf = buf.append(System.getProperty("line.separator"));
}
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
bufw = new BufferedWriter(osw);
bufw.write(buf.toString());
bufw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufr != null) {
bufr.close();
}
if(bufw != null) {
bufw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
原始碼
public class MainActivity extends AppCompatActivity {
private final static String TAG = "WebViewContentWidth";
private WebView mWebView;
String path = Environment.getExternalStorageDirectory().getPath() + "/temp/HYLNK01/第一節_自我測試1.html";
// path = Environment.getExternalStorageDirectory().getPath() + "/temp/HYLNK02/首頁.html";
// path = Environment.getExternalStorageDirectory().getPath() + "/temp/HYLNK03/home.html";;
Context mContext;
@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
mWebView = (WebView) this.findViewById(R.id.main_act_wv);
// 設定不可縮放
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setSupportZoom(false);
mWebView.getSettings().setDisplayZoomControls(false);
// 設定支援螢幕適配
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new HTMLWidthInterface(), "HTMLWidth");
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
mWebView.loadUrl("javascript:window.HTMLWidth.getContentWidth(document.body.offsetWidth);");
}
});
mWebView.loadUrl("file://" + path);
}
class HTMLWidthInterface {
@JavascriptInterface
public void getContentWidth(String value) {
if (value != null) {
int bodyWidth = Integer.parseInt(value);
boolean hasChanged = isContainsText(new File(path), "<meta name=\"viewport\"");
if(!hasChanged) {
htmlAdjustWithPageWidth(bodyWidth, path, mWebView);
mWebView.loadUrl("file://" + path);
}
}
}
}
private void htmlAdjustWithPageWidth(float bodyWidth, String html, WebView webView) {
// 計算要縮放的比例
DisplayMetrics metric = new DisplayMetrics();
((Activity)mContext).getWindowManager().getDefaultDisplay().getMetrics(metric);
float density = metric.density; // 螢幕密度
float scale = webView.getMeasuredWidth() / density / bodyWidth;
String insertText = "<meta name=\"viewport\" content=\"width="+ bodyWidth +"px initial-scale="+ scale
+ ", minimum-scale=0.1, maximum-scale=10.0, user-scalable=no\"/>";
insertBehindText(new File(html), "<head>", insertText);
}
/**
* 在指定文字之後插入一段文字
*
* @param file
* @param targetStr
* @param insertStr
* @return void:
* @version 1.0
* @date 2015-9-2
* @Author zhou.wenkai
*/
public void insertBehindText(File file, String targetStr, String insertStr) {
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
bufr = new BufferedReader(isr);
StringBuffer buf = new StringBuffer();
String line = null;
while ((line = bufr.readLine()) != null) {
// 儲存原文字
buf = buf.append(line);
// 儲存要插入文字
if(line.contains(targetStr)) {
buf.append(insertStr);
}
// 新增換行符號
buf = buf.append(System.getProperty("line.separator"));
}
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
bufw = new BufferedWriter(osw);
bufw.write(buf.toString());
bufw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufr != null) {
bufr.close();
}
if(bufw != null) {
bufw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 檢查是否包含制定文字
*
* @param file
* @param containsStr
* @return
* @return boolean:
* @version 1.0
* @date 2015-10-28
* @Author zhou.wenkai
*/
public boolean isContainsText(File file, String containsStr) {
BufferedReader bufr = null;
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
bufr = new BufferedReader(isr);
String line;
while ((line = bufr.readLine()) != null) {
if(line != null && line.contains(containsStr)) {
return true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(bufr != null) {
bufr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}