Implementing common framework functions with Flutter and then implementing business functions with Vue can solve the company’s mobile development resource constraints, but each business group has a H5 development scenario.

And H5 development does not need to manage troublesome APP shelves, native hardware calls and other mobile terminal knowledge.

So I recently made an in-app browser using Flutter_inappwebview to achieve this function.

The implementation scheme is as follows:

Import Vue resource files

Open a web page directly with a WebView is obviously difficult to experience, so you need to build Vue pages into resource files and package them into the Flutter project.

Introduce resource files in the pubspec.yaml configuration file.

  assets:
    - assets/
    - assets/fonts/
    - assets/css/
    - assets/home/
    - assets/js/
    - assets/test/
Copy the code

If here I have introduced two Vue pages. One test, one home.

Prepare Flutter_inappwebview

The example used in the official case of Flutter_inappwebview uses the most primitive way. There is no progress bar, and the webView will be rebuilt whenever the page state changes. This clearly does not fit the current concept of Flutter development. The WebView should be fixed after loading the web page and not need to be rebuilt.

The Flutter_bloc framework was used to solve the problem, but it was easy to add a progress bar to the top of the page with a load animation in the middle.

Build an HPWebViewPage, the core code

InAppWebView webviewInit(BuildContext context) { HPWebViewBloc vbloc = BlocProvider.of<HPWebViewBloc>(context); print("view init: ${this.viewInfo.url}"); return InAppWebView( key: const Key("in_app_webview"), initialUrlRequest: this.viewInfo.url.startsWith(HPWebViewConst.filePath) ? null : URLRequest(url: Uri.parse(this.viewInfo.url)), onWebViewCreated: (controller) { if (jsHandler ! = null) { jsHandler! (controller, context); } }, onLoadStart: (controller, uri) => vbloc.add(HPWebViewLoadStartEvent(controller, uri)), onLoadError: (controller, uri, code, message) => vbloc.add(HPWebViewLoadErrorEvent(controller, uri, code, message)), onLoadHttpError: (controller, uri, code, message) => vbloc.add(HPWebViewLoadErrorEvent(controller, uri, code, message)), onLoadStop: (controller, uri) => vbloc.add(WebViewLoadStopEvent(controller, uri)), onProgressChanged: (controller, progress) => vbloc.add(WebViewProgressEvent(controller, progress)), initialUserScripts: this.injectJSList); }Copy the code

JsHandler and injectJSList are passed in from outside. The code for Flutter to interact with H5. This is defined by different businesses.

The build code

@override Widget build(BuildContext context) { return Stack( alignment: Alignment.center, fit: StackFit.expand, children: [ webviewInit(context), Positioned( top: 0, child: BlocBuilder<HPWebViewBloc, HPWebViewState>( builder: (context, state) { print(state); if (state is HPWebViewLoadStartState) { return Container( child: LinearProgressIndicator(value: 0), height: 2); } if (state is HPWebViewProgressState) { return Container( child: LinearProgressIndicator(value: state.progress / 100), height: 2); } return Container(height: 0, width: 0); }, ), left: 0, right: 0), Center( child: BlocBuilder<HPWebViewBloc, HPWebViewState>( builder: (context, state) { if (state is HPWebViewLoadStartState || state is HPWebViewProgressState) { return CircularProgressIndicator();  } return Container(height: 0, width: 0); }, ), ) ], ); }Copy the code

Open the Webview

To open the WebView, you need to inject interactive code, but you don’t need to.

class WebViewUtil { static void openWebView(WebViewModel viewInfo, BuildContext context) async { String injectJS = await rootBundle.loadString("assets/files/inject.js"); Navigator.of(context).push(MaterialPageRoute(builder: (context) { return HPWebViewPage( viewInfo: viewInfo, injectJSList: UnmodifiableListView<UserScript>([ UserScript( source: injectJS, injectionTime: UserScriptInjectionTime.AT_DOCUMENT_END), ]), jsHandler: _addJSHandler); })); } static void _addJSHandler( InAppWebViewController controller, BuildContext context) { controller.addJavaScriptHandler( handlerName: JSHandlerConst.close, callback: (_) { Navigator.of(context).pop(); }); controller.addJavaScriptHandler( handlerName: JSHandlerConst.openUrl, callback: (args) { var url = args[0]['url']; var title = args[0]['title']; var filterUrl = args[0]['filterurl']; var filterTitle = args[0]['filtertitle']; Navigator.of(context).pushNamed(HPWebViewPage.routeName, arguments: WebViewModel(url, title: title, filterUrl: filterUrl, filterTitle: filterTitle)); // bloc.add(JSHandlerOpenUrlEvent(args)); }); controller.addJavaScriptHandler( handlerName: JSHandlerConst.back, callback: (args) { Navigator.of(context).pop(); }); }}Copy the code

Inject.js as long as it defines a set of window.js.handler interface

Back = function() {window.flutter_inappwebView.callHandler ('back'); }Copy the code

The current code can only open a URL, not a local VUE page

void _openWebPage(WebViewModel viewInfo, BuildContext context) {
    WebViewUtil.openWebView(viewInfo, context);
  }
 
 _openWebPage(
        WebViewModel("https://github.com/wesin/hp_webview",
            title: "github"),
        context);
 
Copy the code

Loading local Web pages

Loading local web pages requires launching a proxy service in the app that intercepts requests when loading urls through proxies. Returns the H5 resource file. In this way, we can load THE HTML files downloaded from the server, as well as the HTML files already packaged in the project.

Start the local proxy service in main, specifying the port

final HPWebViewProxy localhostServer = new HPWebViewProxy(port: 8765);
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await localhostServer.start();
  print(localhostServer.isRunning());
  
Copy the code

This will open the local web page

ElevatedButton( onPressed: () => _openWebPage( WebViewModel("http://localhost:8765/home/"), context), child: Text(" open local web page "),Copy the code

The code for the proxy service and the entire code is available on my Github. portal