webview_ultra 0.0.6+8 copy "webview_ultra: ^0.0.6+8" to clipboard
webview_ultra: ^0.0.6+8 copied to clipboard

An ultra-optimized, feature-complete, lightweight multi-platform webview plugin for Flutter (Android, iOS, macOS, Windows).

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:webview_ultra/webview_ultra.dart';

void main() {
  runApp(const WebviewUltraShowcaseApp());
}

class WebviewUltraShowcaseApp extends StatelessWidget {
  const WebviewUltraShowcaseApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WebviewUltra Showcase',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6750A4),
          brightness: Brightness.dark,
        ),
      ),
      home: const WebviewUltraHomePage(),
    );
  }
}

class WebviewUltraHomePage extends StatefulWidget {
  const WebviewUltraHomePage({super.key});

  @override
  State<WebviewUltraHomePage> createState() => _WebviewUltraHomePageState();
}

class _WebviewUltraHomePageState extends State<WebviewUltraHomePage> {
  late final WebviewUltraController _controller;
  final TextEditingController _urlTextController =
      TextEditingController(text: 'https://flutter.dev');
  final TextEditingController _findTextController = TextEditingController();
  bool _showFindBar = false;

  @override
  void initState() {
    super.initState();
    _controller = WebviewUltraController(
      settings: const WebviewSettings(
        javascriptEnabled: true,
        allowsInlineMediaPlayback: true,
        allowsBackForwardNavigationGestures: true,
      ),
      onPageStarted: (url) {
        _urlTextController.text = url;
      },
    );

    // Register a typed JS RPC handler
    _controller.addJavaScriptHandler(
      handlerName: 'onUserAction',
      callback: (args) {
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Received RPC from JavaScript: $args')),
          );
        }
        return {'status': 'success', 'timestamp': DateTime.now().toIso8601String()};
      },
    );
  }

  @override
  void dispose() {
    _urlTextController.dispose();
    _findTextController.dispose();
    _controller.dispose();
    super.dispose();
  }

  Future<void> _runHeadlessDemo() async {
    late final HeadlessWebviewUltra headless;
    headless = HeadlessWebviewUltra(
      initialUrl: 'https://flutter.dev',
      onPageFinished: (url) async {
        final result = await headless.evaluateJavascript('document.title');
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Headless Result (Title): $result')),
          );
        }
        headless.dispose();
      },
    );
    await headless.run();
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Running Headless Webview in background...')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: WebviewTitleBuilder(
          controller: _controller,
          builder: (context, title, child) {
            return Text(
              title.isEmpty ? 'WebviewUltra' : title,
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
              style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            );
          },
        ),
        actions: <Widget>[
          WebviewHistoryBuilder(
            controller: _controller,
            builder: (context, history, child) {
              return Row(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  IconButton(
                    icon: const Icon(Icons.arrow_back),
                    onPressed: history.canGoBack ? () => _controller.goBack() : null,
                  ),
                  IconButton(
                    icon: const Icon(Icons.arrow_forward),
                    onPressed: history.canGoForward ? () => _controller.goForward() : null,
                  ),
                ],
              );
            },
          ),
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: () => _controller.reload(),
          ),
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () {
              setState(() {
                _showFindBar = !_showFindBar;
              });
              if (!_showFindBar) {
                _controller.findController.clearMatches();
              }
            },
          ),
        ],
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(4.0),
          child: WebviewProgressBuilder(
            controller: _controller,
            builder: (context, progress, child) {
              if (progress >= 1.0 || progress <= 0.0) {
                return const SizedBox(height: 4.0);
              }
              return LinearProgressIndicator(
                value: progress,
                backgroundColor: Colors.transparent,
                valueColor: AlwaysStoppedAnimation<Color>(
                  Theme.of(context).colorScheme.secondary,
                ),
              );
            },
          ),
        ),
      ),
      body: Column(
        children: <Widget>[
          // URL Bar
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
            color: Theme.of(context).colorScheme.surfaceContainerHighest,
            child: Row(
              children: <Widget>[
                Expanded(
                  child: TextField(
                    controller: _urlTextController,
                    decoration: InputDecoration(
                      hintText: 'Enter URL...',
                      isDense: true,
                      contentPadding:
                          const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(24.0),
                      ),
                      prefixIcon: const Icon(Icons.public, size: 20),
                    ),
                    onSubmitted: (urlStr) {
                      var formatted = urlStr.trim();
                      if (!formatted.startsWith('http://') &&
                          !formatted.startsWith('https://')) {
                        formatted = 'https://$formatted';
                      }
                      _controller.loadUrl(formatted);
                    },
                  ),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () {
                    final text = _urlTextController.text.trim();
                    if (text.isNotEmpty) {
                      var formatted = text;
                      if (!formatted.startsWith('http://') &&
                          !formatted.startsWith('https://')) {
                        formatted = 'https://$formatted';
                      }
                      _controller.loadUrl(formatted);
                    }
                  },
                  child: const Text('Go'),
                ),
              ],
            ),
          ),

          // Find on Page Search Bar
          if (_showFindBar)
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 6.0),
              color: Theme.of(context).colorScheme.surfaceContainer,
              child: Row(
                children: <Widget>[
                  Expanded(
                    child: TextField(
                      controller: _findTextController,
                      decoration: const InputDecoration(
                        hintText: 'Find on page...',
                        isDense: true,
                        prefixIcon: Icon(Icons.search, size: 18),
                      ),
                      onChanged: (text) => _controller.findController.findAll(findText: text),
                    ),
                  ),
                  IconButton(
                    icon: const Icon(Icons.navigate_before),
                    onPressed: () => _controller.findController.findNext(forward: false),
                  ),
                  IconButton(
                    icon: const Icon(Icons.navigate_next),
                    onPressed: () => _controller.findController.findNext(forward: true),
                  ),
                ],
              ),
            ),

          // Quick Action Presets
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),
            child: Row(
              children: <Widget>[
                ActionChip(
                  avatar: const Icon(Icons.open_in_browser, size: 18),
                  label: const Text('InAppBrowser Modal'),
                  onPressed: () {
                    InAppBrowserUltra.open(
                      context: context,
                      url: 'https://flutter.dev',
                    );
                  },
                ),
                const SizedBox(width: 6),
                ActionChip(
                  avatar: const Icon(Icons.visibility_off, size: 18),
                  label: const Text('Headless Scrape'),
                  onPressed: _runHeadlessDemo,
                ),
                const SizedBox(width: 6),
                ActionChip(
                  avatar: const Icon(Icons.cookie, size: 18),
                  label: const Text('Set Cookie'),
                  onPressed: () async {
                    await CookieManagerUltra.instance.setCookie(
                      url: 'https://flutter.dev',
                      name: 'demo_token',
                      value: 'sample_token_123',
                    );
                    if (context.mounted) {
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(content: Text('Cookie demo_token set!')),
                      );
                    }
                  },
                ),
                const SizedBox(width: 6),
                ActionChip(
                  avatar: const Icon(Icons.code, size: 18),
                  label: const Text('Call JS RPC'),
                  onPressed: () async {
                    await _controller.runJavaScript(
                      "window.webview_ultra.callHandler('onUserAction', 'ButtonClicked', 42);",
                    );
                  },
                ),
              ],
            ),
          ),

          // Core WebviewUltra Widget
          Expanded(
            child: WebviewUltra(
              controller: _controller,
              initialUrl: 'https://flutter.dev',
              showProgressBar: true,
              pullToRefresh: true,
            ),
          ),
        ],
      ),
    );
  }
}
3
likes
160
points
9
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

An ultra-optimized, feature-complete, lightweight multi-platform webview plugin for Flutter (Android, iOS, macOS, Windows).

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

file_selector, flutter, flutter_web_plugins, plugin_platform_interface, webview_flutter, webview_flutter_android, webview_flutter_platform_interface, webview_flutter_wkwebview, webview_windows

More

Packages that depend on webview_ultra

Packages that implement webview_ultra