Flutterで、進捗バー付きのWeb画面表示を実装しました。
環境
- Flutter 2.8.1
- Dart 2.15.0
Package
Web画面表示の方法はいくつかあると思いますが、
今回は、webview_flutterを使用しました。
pubspec.yaml
webview_flutter: ^3.0.0 # 追加
完成形
実装
初めの画面
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;
},