1. 程式人生 > 實用技巧 >Flutter應用開發之webview_flutter外掛

Flutter應用開發之webview_flutter外掛

簡介

在移動應用開發中,經常會遇到載入網頁的需求,開啟網頁通常有兩種方式,即在應用內使用內建的元件開啟和使用系統自帶的瀏覽器開啟。不過,在Flutter應用開發中,由於官方並沒有提供類似Webview的網頁載入元件,所以如果專案中涉及網頁載入需要使用第三方外掛庫,如webview_flutter、flutter_webview_plugin等。

其中,webview_flutter是Flutter官方開發和維護的網頁載入外掛庫,而flutter_webview_plugin則是Flutter開源社群推出的網頁載入外掛。兩個外掛功能都差不多,都支援載入本地html文字、Flutter呼叫js以及js呼叫Flutter等,但是我建議使用官方推出的外掛,因為它會持續的跟進已知的問題。

和其他Flutter外掛的使用方式一樣,使用webview_flutter之前需要先在pubspec.yaml檔案中新增依賴指令碼,如下所示。

dependencies:
   webview_flutter: ^0.3.22+1

然後,我們使用flutter packages get命令將webview_flutter外掛拉取到本地後,就可以使用它進行網頁載入開發了。

vi設計http://www.maiqicn.com 辦公資源網站大全https://www.wode007.com

基本使用

如下所示,是WebView元件的建構函式。

WebView({
    Key key,
    this.onWebViewCreated,             //WebView建立完成之後的回撥
    this.initialUrl,                               // 初始化 URL
    this.JavaScriptMode = JavaScriptMode.disabled,    //JS執行模式,預設是不呼叫
    this.javascriptChannels,             // JS可以呼叫Flutter 的通道
    this.navigationDelegate,            // 路由委託,可以使用它執行攔截操作
    this.gestureRecognizers,          // 手勢相關
    this.onPageStarted,                 //開始載入頁面回撥
    this.onPageFinished,              // 頁面載入完成的回撥
    this.onWebResourceError,     //資源載入失敗回撥
    this.debuggingEnabled = false,
    this.gestureNavigationEnabled = false,
    this.userAgent,
    this.initialMediaPlaybackPolicy =
        AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
  })

使用時,只需要按照引數傳遞對應的值即可。不過,在實際使用前,為了方便使用,我們一般會對它進行二次封裝,主要是介面和功能的封裝。下面是我封裝的一個可以載入本地和網路檔案的WebViewPage。

class WebViewPage extends StatefulWidget {

  String url;
  final String title;
  final bool isLocalUrl;

  WebViewController _webViewController;

  WebViewPage({this.url, this.isLocalUrl = false, this.title});

  @override
  _WebViewPage createState() => _WebViewPage();


}

class _WebViewPage extends State<WebViewPage> {

  JavascriptChannel jsBridge(BuildContext context) => JavascriptChannel(
      name: 'jsbridge', // 與h5 端的一致 不然收不到訊息
      onMessageReceived: (JavascriptMessage message) async{
        debugPrint(message.message);
      });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: _buildAppbar(),
        body: _buildBody()
    );
  }

  _buildAppbar() {
    return AppBar(
        elevation: 0,
        backgroundColor: Color(0xccd0d7),
        title: Text(widget.title, style: TextStyle(color: Colors.black),),
        centerTitle: true,
        leading: IconButton(icon: Icon(Icons.arrow_back, color: Color(0xFF23ADE5),), onPressed: () {

        })
    );
  }

  _buildBody() {
    return Column(
      children: <Widget>[
        SizedBox(
          height: 1,
          width: double.infinity,
          child: const
DecoratedBox(decoration: BoxDecoration(color: Color(0xFFEEEEEE))), ), Expanded( flex: 1, child: WebView( initialUrl: widget.isLocalUrl ? Uri.dataFromString(widget.url, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')) .toString(): widget.url, javascriptMode: JavascriptMode.unrestricted, javascriptChannels: <JavascriptChannel>[ jsBridge(context) ].toSet(), onWebViewCreated: (WebViewController controller){ widget._webViewController = controller; if(widget.isLocalUrl){ _loadHtmlAssets(controller); }else{ controller.loadUrl(widget.url); } controller.canGoBack().then((value) => debugPrint(value.toString())); controller.canGoForward().then((value) => debugPrint(value.toString())); controller.currentUrl().then((value) => debugPrint(value)); }, onPageFinished: (String value){ widget._webViewController.evaluateJavascript('document.title') .then((title) => debugPrint(title)); }, ), ) ], ); } //載入本地檔案 _loadHtmlAssets(WebViewController controller) async { String htmlPath = await rootBundle.loadString(widget.url); controller.loadUrl(Uri.dataFromString(htmlPath,mimeType: 'text/html', encoding: Encoding.getByName('utf-8')) .toString()); } }

使用時,只需要按照傳入對應的屬性即可。需要說明的是,載入本地Html檔案時,需要在pubspec.yaml檔案中申明這個Html檔案,如下所示。

flutter:
 //  ...
  assets:
   - assets/real_data_help.html

然後,我們使用封裝的元件即可載入本地的Html檔案。例如:

class MyApp extends StatelessWidget {

  String localUrl = 'assets/real_data_help.html';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home:WebViewPage(url:localUrl, isLocalUrl: true, title: '載入本地檔案'),
    );
  }
}