webview_flutter로 로드 표시기 표시

16676 단어 DartFlutter

webview_flutter 라이브러리



평소 간단하게 Webview를 표시하고 싶을 때는 webview_flutter 라이브러리를 사용하고 있습니다. 그 밖에도 라이브러리는 여러 가지 있는 것 같습니다만, 자신은 지금까지 webview_flutter로 만족하고 있습니다.

공식 문서
htps // 푸 b. 에서 v / 파 쿠카 s / 우 ぇ b ぃ 에 w_f

이번에는 webview_flutter로 지정된 URL의 페이지를로드하는 동안 표시기를 표시하는 방법을 기록해 둡니다.

Flutter Version: 1.22.4
webview_flutter version: 1.0.7

베이스로 사용할 코드



다음 코드를 사용합니다. Qiita로 기사 일람을 취득해 리스트 표시→아이템을 탭하면 기사의 상세를 열기, 라고 하는 것입니다.

변경 전의 상태에서는, 기사를 취득할 때에 인디케이터가 표시됩니다만, 기사를 탭해 기사 상세를 열 때는 인디케이터가 표시되지 않는 상태입니다.

이번 변경하는 article_detail_screen.dart의 변경전은 이하와 같습니다.

article_detail_screen.dart

class ArticleDetailScreen extends StatelessWidget {
  ArticleDetailScreen({@required this.qiitaInfo});

  final QiitaInfo qiitaInfo;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Expanded(
          child: Text(
            qiitaInfo.title,
            overflow: TextOverflow.ellipsis,
            style: TextStyle(
              fontSize: 13,
            ),
          ),
        ),
      ),
      body: WebView(
        initialUrl: qiitaInfo.url,
        javascriptMode: JavascriptMode.unrestricted,
      ),
    );
  }
}


변경점



위의 파일을 변경합니다. 먼저 setState를 사용해야하므로 StatefulWidget으로 변경해야합니다.
쓰는 방법에는 여러 가지가 있습니다.

article_detail_screen.dart
import 'package:flutter/material.dart';
import 'package:qiita_sample/data/entities/qiita_info.dart';
import 'package:webview_flutter/webview_flutter.dart';

class ArticleDetailScreen extends StatefulWidget {
  ArticleDetailScreen({
    @required this.qiitaInfo,
  });

  final QiitaInfo qiitaInfo;

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

class _ArticleDetailScreenState extends State<ArticleDetailScreen> {
  num position = 1;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Expanded(
          child: Text(
            widget.qiitaInfo.title,
            overflow: TextOverflow.ellipsis,
            style: TextStyle(
              fontSize: 13,
            ),
          ),
        ),
      ),
      body: IndexedStack(
        index: position,
        children: [
          WebView(
            initialUrl: widget.qiitaInfo.url,
            javascriptMode: JavascriptMode.unrestricted,
            // ローディング開始時に呼ばれる
            onPageStarted: (_) {
              setState(() {
                position = 1;
              });
            },
            // ローディング完了時に呼ばれる
            onPageFinished: (_) {
              setState(() {
                position = 0;
              });
            },
          ),
          Container(
            color: Colors.white,
            child: Center(
              child: CircularProgressIndicator(),
            ),
          ),
        ],
      ),
    );
  }
}

수정하면 탭한 기사 세부정보 페이지를 로드할 때 표시기가 표시됩니다.



먼저 "쓰는 방법은 몇 가지있다"고 썼지만,

구체적으로는 아래와 같이 Stack을 사용하여 쓰면 onPageFinished의 이벤트를 취득하는 것만으로 거의 같은 움직임이 됩니다만, 이쪽은 페이지가 표시된 후에도 조금의 사이 인디케이터가 돌아 계속합니다.
class _ArticleDetailScreenState extends State<ArticleDetailScreen> {
  bool _isLoading = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          widget.qiitaInfo.title,
          overflow: TextOverflow.ellipsis,
          style: TextStyle(
            fontSize: 13,
          ),
        ),
      ),
      body: Stack(
        children: [
          WebView(
            initialUrl: widget.qiitaInfo.url,
            javascriptMode: JavascriptMode.unrestricted,
            onPageFinished: (_) {
              setState(() {
                _isLoading = false;
              });
            },
          ),
          _isLoading
              ? Center(child: CircularProgressIndicator())
              : SizedBox.shrink()
        ],
      ),
    );
  }
}



이런 차이가 발생하는 원인은 아마도 Stack이라면 webview 위에 표시기를 겹치기 때문에 로드가 완전히 끝나기 전부터 페이지가 표시됩니다. IndexedStack의 경우라고 화면을 전환하고 있으므로, 로드가 끝날 때까지 화면이 표시되지 않습니다.

(IndexedStack 위젯을 지금까지 몰랐습니다.)

참고로 한 코드



추가



「WebView 표시의 로드시에 CircularProgressIndicator별로 사용하지 않을지도」라는 츳코미를 받았습니다.

그래서 LinearProgressIndicator를 사용하여 다시 작성해 보았습니다.
// ...(略)
class _ArticleDetailScreenState extends State<ArticleDetailScreen> {
  bool isLoading = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Expanded(
          child: Text(
            widget.qiitaInfo.title,
            overflow: TextOverflow.ellipsis,
            style: TextStyle(
              fontSize: 13,
            ),
          ),
        ),
      ),
      body: Column(
        children: [
          isLoading ? LinearProgressIndicator() : SizedBox.shrink(),
          Expanded(
            child: WebView(
              initialUrl: widget.qiitaInfo.url,
              javascriptMode: JavascriptMode.unrestricted,
              onPageFinished: (_) {
                setState(() {
                  isLoading = false;
                });
              },
            ),
          ),
        ],
      ),
    );
  }
}



(AppBar 바로 아래의 길쭉한 표시기에 주목하십시오)

이것이 가장 위화감이 없고 좋을지도 모릅니다.

추가 2



webview_flutter에서는 Loading의 진행도를 얻을 수 없었기 때문에, 다른 라이브러리를 사용해 가능하게 했습니다.
  • flutter_webview 대신 flutter_inappwebview를 사용해 보았습니다.
  • 좋은 웹페이지 즐겨찾기