1. 程式人生 > >Android 本地HTML螢幕適配的一種方案

Android 本地HTML螢幕適配的一種方案

前言:在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;
    }
}