패키지, 저장소 및 앱 카테고리 검색

패키지 상세v0.2.3

webviewx

모바일용 webview_flutter와 웹용 iframe를 사용하는 기능이 풍부한 크로스플랫폼 웹뷰. JS 상호운용성 지원.

AndroidiOSWeb
30일 다운로드
791
좋아요
266
Pub 점수
140

패키지 설치

flutter pub add webviewx

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

webviewx는 Android 및 iOS에서 webview_flutter를 사용하고 웹에서는 iframe을 활용하는 크로스플랫폼 웹뷰 패키지로, 플랫폼 간 일관된 API를 제공합니다. JavaScript 상호운용을 지원하여 Dart와 웹 콘텐츠 간의 원활한 통신이 가능합니다. Flutter 앱에 웹 콘텐츠를 삽입하고 풍부한 기능과 플랫폼 호환성을 갖춘 통합 솔루션을 찾는 개발자를 위한 것입니다.

사용 사례

  • 모바일 앱에 웹 콘텐츠 삽입
  • 웹 기반 양식 또는 대시보드 통합
  • 웹 컴포넌트를 사용한 하이브리드 앱 개발 활성화
  • URL에서 동적 콘텐츠를 로드하는 것을 지원
  • Flutter 앱에서 웹 임베드 기능 구축하기

주요 기능

  • 크로스 플랫폼 지원 (Android, iOS, Web)
  • 자바스크립트 상호 운용 기능
  • 모바일에서는 네이티브 웹뷰를, 웹에서는 iframe을 사용
  • 플랫폼 간 일관된 API
  • 경량이며 간편한 통합

적합한 대상

  • 하이브리드 플러터 앱을 개발하는 개발자
  • 웹 콘텐츠 삽입이 필요한 팀
  • 웹 뷰와의 JS 통신이 필요한 프로젝트
  • 공유 UI 로직을 가진 다중 플랫폼 앱
  • 웹 통합 기능을 빠르게 프로토타이핑하기

고려 사항

  • 웹 플랫폼은 iframe를 사용하며, 일부 고급 웹뷰 기능이 제한될 수 있습니다
  • 외부 콘텐츠를 로드할 때 보안을 신중하게 다뤄야 합니다
  • 네이티브 웹뷰 구현과 비교하여 사용자 정의가 제한적입니다
  • 복잡한 웹 상호작용을 위해 추가 구성이 필요할 수 있습니다
  • 모바일용 webview_flutter에 의존하며, 자체 제약 조건이 있음

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

This package has been deprecated

webviewx

pub package

A feature-rich cross-platform webview using webview_flutter for mobile and iframe for web. JS interop-ready.

Getting started


Gallery

Mobile

Web


Basic usage

1. Create a WebViewXController inside your stateful widget
late WebViewXController webviewController;
2. Add the WebViewX widget inside the build method, and set the onWebViewCreated callback in order to retrieve the controller when the webview is initialized
WebViewX(
    initialContent: '<h2> Hello, world! </h2>',
    initialSourceType: SourceType.HTML,
    onWebViewCreated: (controller) => webviewController = controller,
    ...
    ... other options
);

Important !

If you need to add other widgets on top of the webview (e.g. inside a Stack widget), you MUST wrap those widgets with a WebViewAware widget. This does nothing on mobile, but on web it allows widgets on top to intercept gestures. Otherwise, those widgets may not be clickable and/or the iframe will behave weird (unexpected refresh/reload - this is a well known issue).

Also, if you add widgets on top of the webview, wrap them and then you notice that the iframe still reloads unexpectedly, you should check if there are other widgets that sit on top without being noticed, or try to wrap InkWell, GestureRecognizer or Button widgets to see which one causes the problem.

3. Interact with the controller (run the example app to check out some use cases)
webviewController.loadContent(
    'https://flutter.dev',
    SourceType.url,
);
webviewController.goBack();

webviewController.goForward();
...
...

Features

Note: For more detailed information about things such as EmbeddedJsContent, please visit each own's .dart file from the utils folder.

  • Widget properties

Feature Details
String initialContent Initial webview content
SourceType initialSourceType Initial webview content type (url, urlBypass or html)
String? userAgent User agent
double width Widget's width
double height Widget's height
Function(WebViewXController controller)? onWebViewCreated Callback that gets executed when the webview has initialized
Set<EmbeddedJsContent> jsContent A set of EmbeddedJsContent, which is an object that defines some javascript which will be embedded in the page, once loaded (check the example app)
Set<DartCallback> dartCallBacks A set of DartCallback, which is an object that defines a dart callback function, which will be called from javascript (check the example app)
bool ignoreAllGestures Boolean value that specifies if the widget should ignore all gestures right after it is initialized
JavascriptMode javascriptMode This specifies if Javascript should be allowed to execute, or not (allowed by default, you must allow it in order to use above features)
AutoMediaPlaybackPolicy initialMediaPlaybackPolicy This specifies if media content should be allowed to autoplay when initialized (i.e when the page is loaded)
void Function(String src)? onPageStarted Callback that gets executed when a page starts loading (e.g. after you change the content)
void Function(String src)? onPageFinished Callback that gets executed when a page finishes loading
NavigationDelegate? navigationDelegate Callback that, if not null, gets executed when the user clicks something in the webview (on Web it only works for SourceType.urlBypass, for now)
void Function(WebResourceError error)? onWebResourceError Callback that gets executed when there is an error when loading resources ( issues on web )
WebSpecificParams webSpecificParams This is an object that contains web-specific options. Theese are not available on mobile (yet)
MobileSpecificParams mobileSpecificParams This is an object that contains mobile-specific options. Theese are not available on web (yet)

  • Controller properties

Feature Usage
Load URL that allows iframe embedding webviewController.loadContent(URL, SourceType.URL)
Load URL that doesnt allow iframe embedding webviewController.loadContent(URL, SourceType.URL_BYPASS)
Load URL that doesnt allow iframe embedding, with headers webviewController.loadContent(URL, SourceType.URL_BYPASS, headers: {'x-something': 'value'})
Load HTML from string webviewController.loadContent(HTML, SourceType.HTML)
Load HTML from assets webviewController.loadContent(HTML, SourceType.HTML, fromAssets: true)
Check if you can go back in history webviewController.canGoBack()
Go back in history webviewController.goBack()
Check if you can go forward in history webviewController.canGoForward()
Go forward in history webviewController.goForward()
Reload current content webviewController.reload()
Check if all gestures are ignored webviewController.ignoringAllGestures
Set ignore all gestures webviewController.setIgnoreAllGestures(value)
Evaluate "raw" javascript code webviewController.evalRawJavascript(JS)
Evaluate "raw" javascript code in global context ("page") webviewController.evalRawJavascript(JS, inGlobalContext: true)
Call a JS method webviewController.callJsMethod(METHOD_NAME, PARAMS_LIST)
Retrieve webview's content webviewController.getContent()
Get scroll position on X axis webviewController.getScrollX()
Get scroll position on Y axis webviewController.getScrollY()
Scrolls by x on X axis and by y on Y axis webviewController.scrollBy(int x, int y)
Scrolls exactly to the position (x, y) webviewController.scrollTo(int x, int y)
Retrieves the inner page title webviewController.getTitle()
Clears cache webviewController.clearCache()

Limitations and notes

While this package aims to put together the best of both worlds, there are differences between web and mobile.

  • Running and building

    First, this package was being developed while the default web renderer was html. Now(Flutter 2, Dart 2.12), the default renderer is canvaskit.

    From my experience, this package does behave a little bit weird on canvaskit, so you should use the html renderer.

    To do this, you have to run your ordinary flutter run -d chrome command with the --web-renderer html extra argument, like this:

    flutter run -d chrome --web-renderer html
    

    for running and

    flutter build web --web-renderer html
    

    for building.

  • Diferences between Web and Mobile behaviour:

    See issues/#27

  • About content loading on Web

    To make the web version (iframe) work as it is, I had to use some of the code from x-frame bypass in order to make a request to a CORS proxy, which removes the headers that block iframe embeddings.

    This might seem like a hack, and it really is, but I couldn't find any other way to make the iframe behave similar to the mobile webview (which is some kind of an actual browser, that's why everything works there by default).

  • About Web navigation

    On web, the history navigation stack is built from scratch because I couldn't handle iframe's internal history the right way.


Known issues and TODOs

  • [ x ] On web, user-agent and headers only work when using SourceType.urlBypass, and they only have effect the first time being used (view/web.dart)

  • [ x ] On web, it should be possible to send any errors caught when loading an urlBypass to a dart callback, which will then be sent through the onWebResourceError callback, just like on the mobile version (utils/x_frame_options_bypass.dart)

  • [ x ] On web, it should be possible to add a custom proxy list without the js null-checking mess (utils/x_frame_options_bypass.dart)

  • [ ? ] Eventually (if possible), most if not all properties from WebSpecificParams and MobileSpecificParams should merge and theese two objects may disappear

  • [ x ] On mobile, the controller's value's source type becomes out of sync when moving back and forth in history. This happens because the url change is not yet intercepted and set the model accordingly (shouldn't be hard to fix).

  • [ ] On mobile, the controller's callJsMethod doesnt throw an error if the operation failed. Instead it only shows the error in console.

  • [ ] Add tests

  • List open, there may be others

Credits

This package wouldn't be possible without the following:

  • webview_flutter for the mobile version
  • easy_web_view for ideas and starting point for the web version
  • pointer_interceptor for fixing iframe issues when other widgets are on top of it (see above)
  • x-frame-bypass for allowing the iframe to bypass websites' X-Frame-Options: deny/same-origin headers, thus allowing us to load any webpage (just like on mobile)
  • https://cors.bridged.cc/ for the free CORS proxy
  • https://api.codetabs.com/ for the free CORS proxy
  • And last but not least, http://deversoft.ro (the company I work for) for motivating me throughout the development process

License

MIT

카테고리

의존성

의존성 목록 5 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.