flutter 抖动-禁用InAppWebView导航

j1dl9f46  于 2022-12-14  发布在  Flutter
关注(0)|答案(6)|浏览(259)

我是Flutter的新手,我想在其他小部件之间放置一个web视图,我使用InAppWebView flutter来实现这一点,但我想阻止用户在单击web视图中的按钮时导航到其他页面。我是否必须为iOS和Android编写一些本地代码来阻止导航?
谢谢

7gyucuyw

7gyucuyw1#

就像这样:

InAppWebView(
....
 shouldOverrideUrlLoading: (controller, navigationAction) async {
  final uri = navigationAction.request.url!;
  if(whitenAvigationHosts.contains(uri.host)){
    return NavigationActionPolicy.ALLOW;
  }
  return NavigationActionPolicy.CANCEL;
})
vsaztqbk

vsaztqbk2#

由于您使用的是InAppWebView包,因此您可以在Webview实际导航之前截取它要导航到的每个URL,然后使用回调shouldOverrideUrlLoading决定是否进行导航,如下所示:

shouldOverrideUrlLoading: (controller, navigationAction) async {
    // You can access the URL like this
    final url = navigationAction.request.url.toString();

    if (condition) {
        // This one means do not navigate
        return NavigationActionPolicy.CANCEL;
    }

    // This one means navigate
    return NavigationActionPolicy.ALLOW;
},

注意:要使用回调shouldOverrideUrlLoading,您必须在webview的initialOptions中启用它,如下所示,因为默认值为false

initialOptions: InAppWebViewGroupOptions(
    crossPlatform: InAppWebViewOptions(
        useShouldOverrideUrlLoading: true,
    ),
),
zi8p0yeb

zi8p0yeb3#

要禁用将用户导航到另一个页面,您可以使用onPageCommitVisible回调来确定用户正在单击重定向到另一个页面的url,因此只需在其中调用goBack

InAppWebView(
        onPageCommitVisible: (con,uri){
          print("url ${uri.toString()}");
          con.goBack();
        },

      ),
rhfm7lfc

rhfm7lfc4#

您可以通过导航委托属性阻止在webview中导航,如下所示:

WebView(
        debuggingEnabled: true,
        initialUrl: _currentURL,
        onWebViewCreated: (controller) {
          _controller = controller;
          return _controller;
        },
        onPageFinished: (url) {
          if (url.contains(ConstUtils.course)) {
            updateProfile();
          }
        },
        navigationDelegate: (navigation) => NavigationDecision.prevent,
        onWebResourceError: (error) {
          NavigationUtils(context).popCurrentPage();
        },
        onPageStarted: (url) {
          
        },
        javascriptMode: JavascriptMode.unrestricted,
      ),
jbose2ul

jbose2ul5#

禁用导航InAppWebView:-

我们在Inappwebview小部件中有onUpdateVisitedHistory属性。使用此onUpdateVisitedHistory属性,我们可以监听Inappwebview小部件中的url更改。因此,禁用导航,我们可以使用webcontroller.goback()方法。
小组件代码:

InAppWebView(
              key: webViewKey,
              onWebViewCreated: (controller) {
                webViewController = controller;
                _loadHtmlFromAssets();
              },
              onUpdateVisitedHistory: (controller, url, androidIsReload) {
                if (url!.host.contains("google.com")) {
                  webViewController?.goBack();
                  //You can do anything
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const Screen1()),
                  );
                  //Prevent that url works
                  return;
                } else if (url.host.contains("yahoo.com")) {
                  //You can do anything
                  webViewController?.goBack();
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const Screen3()),
                  );
                  //Prevent that url works
                  return;
                } else if (url.host.contains("duckduckgo.com")) {
                  //You can do anything
                  webViewController?.goBack();
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const Screen2()),
                  );
                }
              })

在这里,我们跳过加载搜索引擎和跳转到其他小部件
注意:如果我们没有添加webcontroller.goback()。它将加载网站并移动到小部件。如果我们按下它将显示网页。

样本代码:

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  WebViewController? _controller;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;
  late PullToRefreshController pullToRefreshController;
  InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
      crossPlatform: InAppWebViewOptions(
        useShouldOverrideUrlLoading: true,
        mediaPlaybackRequiresUserGesture: false,
      ),
      android: AndroidInAppWebViewOptions(
        useHybridComposition: true,
      ),
      ios: IOSInAppWebViewOptions(
        allowsInlineMediaPlayback: true,
      ));

  @override
  void initState() {
    super.initState();

    pullToRefreshController = PullToRefreshController(
      options: PullToRefreshOptions(
        color: Colors.blue,
      ),
      onRefresh: () async {
        if (Platform.isAndroid) {
          webViewController?.reload();
        } else if (Platform.isIOS) {
          webViewController?.loadUrl(
              urlRequest: URLRequest(url: await webViewController?.getUrl()));
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            webViewController?.goBack();
          },
          child: Icon(Icons.arrow_back),
        ),
        appBar: AppBar(
          backgroundColor: Colors.black87,
          title: Text(widget.title),
        ),
        body: Center(
          child: InAppWebView(
              key: webViewKey,
              onWebViewCreated: (controller) {
                webViewController = controller;
                _loadHtmlFromAssets();
              },
              onUpdateVisitedHistory: (controller, url, androidIsReload) {
                if (url!.host.contains("google.com")) {
                  webViewController?.goBack();
                  //You can do anything
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const Screen1()),
                  );
                  //Prevent that url works
                  return;
                } else if (url.host.contains("yahoo.com")) {
                  //You can do anything
                  webViewController?.goBack();
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const Screen3()),
                  );
                  //Prevent that url works
                  return;
                } else if (url.host.contains("duckduckgo.com")) {
                  //You can do anything
                  webViewController?.goBack();
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const Screen2()),
                  );
                }
              }),
        ));
  }

  _loadHtmlFromAssets() {
    var fileText =
        "<!DOCTYPE html> <html> <head> <title>HTML, CSS and JavaScript demo</title> <style> .rotate { transform: rotate(1700deg) ; } .rotate2 { transform: rotate(90deg) ; } .bg { background: url(https://picsum.photos/2000/1000?image=1069) center/cover; height: 50vh; width: 50vh; } body { margin:0; overflow:hidden; } </style> </head> "
        "<!-- Start your code here --> <ul> <li> <a href ='http://duckduckgo.com/' /><p> duckduckgo.com</a> </li>  <li> <a href='http://www.google.com'>google.com </a> </li>    <li> <a href='http://www.yahoo.com/'> yahoo.com </a> </li></ul> </html>";
    // return Uri.dataFromString(fileText,
    //         mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
    //     .toString();
    webViewController!.loadUrl(
        urlRequest: URLRequest(
            url: new Uri.dataFromString(fileText, mimeType: 'text/html')));

    // _controller?.loadUrl(Uri.dataFromString(fileText,
    //         mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
    //     .toString());
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class Screen1 extends StatelessWidget {
  const Screen1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: Text("Screen 1 google.com"),
      ),
    );
  }
}

class Screen2 extends StatelessWidget {
  const Screen2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: MaterialApp(
        home: Container(
          child: Text("Screen 2 yahoo.com"),
        ),
      ),
    );
  }
}

class Screen3 extends StatelessWidget {
  const Screen3({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: Text("Screen 3 duck.com"),
      ),
    );
  }
}

禁用Webview小部件中的导航:

我们可以使用navigationDelegate来监视webview中的url更改。NavigationDecision.prevent将阻止跳转到网站

WebView(
      // initialUrl: 'https://flutter.dev',
      onWebViewCreated: (WebViewController webViewController) {
        _controller = webViewController;
        _loadHtmlFromAssets();
      },
      navigationDelegate: (NavigationRequest request) {
        if (request.url.contains("google.com")) {
          //You can do anything
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const Screen1()),
          );
          //Prevent that url works
          return NavigationDecision.prevent;
        } else if (request.url.contains("yahoo.com")) {
          //You can do anything
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const Screen1()),
          );
          //Prevent that url works
          return NavigationDecision.prevent;
        } else if (request.url.contains("duckduckgo.com")) {
          //You can do anything
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const Screen3()),
          );
          //Prevent that url works
          return NavigationDecision.prevent;
        }
        //Any other url works
        return NavigationDecision.navigate;
      },
    );
ne5o7dgx

ne5o7dgx6#

对于Android阻止URL工作,你可以使用webViewController?.goBack();(但不工作在iOS设备上)
您可以使用webViewController?.stopLoading();(在iOS和Android设备上都可以使用)防止该URL工作
如果上面的解决方案使空白屏幕在android的使用简单ifelse

if (Platform.isIOS) {
  webViewController?.stopLoading();
} else {
  webViewController?.goBack();
}

相关问题