LoginSignup
6
2

More than 1 year has passed since last update.

Flutter Web画面表示(進捗バー付き)

Last updated at Posted at 2022-01-20

Flutterで、進捗バー付きのWeb画面表示を実装しました。

環境

  • Flutter 2.8.1
  • Dart 2.15.0

Package

Web画面表示の方法はいくつかあると思いますが、
今回は、webview_flutterを使用しました。

pubspec.yaml
webview_flutter: ^3.0.0 # 追加

完成形

output.gif

実装

初めの画面

main.dart
void main() {
  runApp(
    const MyApp(),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const HomeScreen(),
      routes: {
        // Web画面のルーティング
        WebViewScreen.routeName: (context) => const WebViewScreen(),
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          child: const Text('Press'),
          onPressed: () {
            // Web画面へ遷移
            Navigator.pushNamed(context, WebViewScreen.routeName);
          },
        ),
      ),
    );
  }
}

〜〜〜
続く
〜〜〜

Web画面

main.dart

class WebViewScreen extends StatefulWidget {
  const WebViewScreen({
    Key? key,
  }) : super(key: key);

  static const String routeName = '/web-view';

  @override
  _WebViewScreenState createState() => _WebViewScreenState();
}

class _WebViewScreenState extends State<WebViewScreen> {
  final _key = UniqueKey();
  final Completer<WebViewController> _controller = Completer<WebViewController>();
  bool _isLoading = true; // ローディングの有無
  String _title = ''; // Webタイトル
  double _downloadPercentage = 0.0; // 進捗バー用

  @override
  void initState() {
    super.initState();
    if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
  }

  // ローディングの切り替え
  void toggleLoading() {
    setState(() {
      _isLoading = !_isLoading;
    });
  }

  // 進捗計算
  void calculateProgress(int progress) {
    setState(() {
      _downloadPercentage = (progress / 100);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_title),// Web画面のタイトルを表示
      ),
      body: Column(
        children: [
          // 進捗バー
          _isLoading ? LinearProgressIndicator(value: _downloadPercentage, minHeight: 7.0,) : const SizedBox.shrink(),
          Expanded(
            child: Scrollbar(
              showTrackOnHover: true,
              child: WebView(
                key: _key,
                initialUrl: 'https://qiita.com/',
                javascriptMode: JavascriptMode.unrestricted,
                onWebViewCreated: _controller.complete,
                onPageFinished: (String url) async {
                  if (_isLoading) toggleLoading();
                  final controller = await _controller.future;
                  final title = await controller.getTitle();
                  if (title != null) _title = title;
                },
                onProgress: (progress) {
                  calculateProgress(progress);
                }
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Web画面が完全に読み込まれるまで、onProgressで読み込みの計算をします。

onProgress: (progress) {
  calculateProgress(progress);
}

その計算した値をLinearProgressIndicatorのvalueに渡せば進捗の表示ができます。

LinearProgressIndicator(value: _downloadPercentage)

onPageFinishedでは読み込まれた後の処理を記述
_isLoadingのローディングの非表示へ切り替え
controllerでWebに設定されているタイトルを取得し、変数に代入すればOKです。

onPageFinished: (String url) async {
  if (_isLoading) toggleLoading();
  final controller = await _controller.future;
  final title = await controller.getTitle();
  if (title != null) _title = title;
},
6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2