1. 程式人生 > >Flutter ListView 列表點選和網頁載入

Flutter ListView 列表點選和網頁載入

上一篇講了使用ListView載入列表資料,本篇,我們講下列表項的點選,因為本篇的例子點選後是載入一個網頁,所以本篇也講下類似於Android的WebView和iOS的UIWebView載入網頁。效果如下:
在這裡插入圖片描述

item點選

在Android中,您可以通過呼叫方法setOnClickListener將OnClick繫結到按鈕等view上.
在Flutter中,新增觸控監聽器有兩種方法:
具體可以查閱我之前的部落格Flutter中的點選、拖動和其它手勢

上篇部落格中我們使用了Row、Column等Widget繪製了item,我們再在原來的Widget的外層包裝個GestureDetector,新增手勢,然後使用onTap處理點選,完整程式碼如下:

 new GestureDetector(
          child: Padding(
            padding: new EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
            child: new Column(
              children: <Widget>[
                new Row(
                  crossAxisAlignment: CrossAxisAlignment.start, //縱向對齊方式:起始邊對齊
                  mainAxisSize: MainAxisSize.max,
                  children: <Widget>[
                    new Expanded(
                      child: Container(
                        height: 95.0,
                        child: getImage(data.articleThumbnail),
                        alignment: FractionalOffset.center,
                      ),
                      flex: 1,
                    ),
                    new Expanded(
                      child: Container(
                        height: 95.0,
                        margin: new EdgeInsets.fromLTRB(5.0, 0.0, 0.0, 0.0),
                        child: new Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            new Container(
                              child: new Text(
                                articleTitle,
                                style: new TextStyle(
                                    fontSize: 20.0,
                                    fontWeight: FontWeight.w700),
                                maxLines: 1,
                                overflow: TextOverflow.ellipsis,
                              ),
                              alignment: FractionalOffset.topLeft,
                            ),
                            new Container(
                              child: new Text("${data.articleBrief}",
                                  style: new TextStyle(fontSize: 16.0),
                                  maxLines: 2,
                                  overflow: TextOverflow.ellipsis),
                              alignment: Alignment.topLeft,
                            ),
                            new Expanded(
                              child: new Container(
                                margin:
                                    new EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 0.0),
                                child: new Stack(
                                  children: <Widget>[
                                    new Container(
                                      child: new Text("${data.articleAuthor}",
                                          style: new TextStyle(fontSize: 10.0)),
                                      alignment: FractionalOffset.bottomLeft,
                                    ),
                                    new Container(
                                      child: new Text(time_str,
                                          style: new TextStyle(fontSize: 10.0)),
                                      alignment: FractionalOffset.bottomRight,
                                    ),
                                  ],
                                ),
                              ),
                            )
                          ],
                        ),
                      ),
                      flex: 3,
                    ),
                  ],
                ),
                new Divider(), //分割線
              ],
            ),
          ),
          onTap: () {
            onItemClick(i, articleTitle); //處理點選事件
          });

點選事件進行頁面跳轉

  /**
   * 列表點選
   */
  void onItemClick(int i, String articleTitle) {
    String h5_url = (listData[i].data as Data).url;
    Navigator.push(
        context,
        new MaterialPageRoute(
            builder: (context) => new NewsWebPage(h5_url, articleTitle)));
  }

網頁載入

網頁載入使用元件

flutter_webview_plugin
具體實現如下:

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

/**
 * @Description  新聞網頁,h5
 * @Author  zhibuyu
 * @Date 2018/10/19  9:09
 * @Version  1.0
 */
class NewsWebPage extends StatefulWidget{
  String  news_url;
  String title;

  NewsWebPage(this.news_url,this.title);

  @override
  State<StatefulWidget> createState()=>new NewsWebPageState(news_url,title);

}
class NewsWebPageState extends State<NewsWebPage>{
  String  news_url;
  String title;
  // 標記是否是載入中
  bool loading = true;
  // 標記當前頁面是否是我們自定義的回撥頁面
  bool isLoadingCallbackPage = false;
  GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey();
  // URL變化監聽器
  StreamSubscription<String> onUrlChanged;
  // WebView載入狀態變化監聽器
  StreamSubscription<WebViewStateChanged> onStateChanged;
  // 外掛提供的物件,該物件用於WebView的各種操作
  FlutterWebviewPlugin flutterWebViewPlugin = new FlutterWebviewPlugin();

  NewsWebPageState(this.news_url, this.title);

  @override
  void initState() {
    onStateChanged = flutterWebViewPlugin.onStateChanged.listen((WebViewStateChanged state){
      // state.type是一個列舉型別,取值有:WebViewState.shouldStart, WebViewState.startLoad, WebViewState.finishLoad
      switch (state.type) {
        case WebViewState.shouldStart:
        // 準備載入
          setState(() {
            loading = true;
          });
          break;
        case WebViewState.startLoad:
        // 開始載入
          break;
        case WebViewState.finishLoad:
        // 載入完成
          setState(() {
            loading = false;
          });
          if (isLoadingCallbackPage) {
            // 當前是回撥頁面,則呼叫js方法獲取資料
            parseResult();
          }
          break;
      }
    });
  }
  // 解析WebView中的資料
  void parseResult() {
//    flutterWebViewPlugin.evalJavascript("get();").then((result) {
//      // result json字串,包含token資訊
//
//    });
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> titleContent = [];
    titleContent.add(new Text(
//      title,
      "新聞詳情",
      style: new TextStyle(color: Colors.white),
    ));
    if (loading) {
      // 如果還在載入中,就在標題欄上顯示一個圓形進度條
      titleContent.add(new CupertinoActivityIndicator());
    }
    titleContent.add(new Container(width: 50.0));
    // WebviewScaffold是外掛提供的元件,用於在頁面上顯示一個WebView並載入URL
    return new WebviewScaffold(
      key: scaffoldKey,
      url:news_url, // 登入的URL
      appBar: new AppBar(
        title: new Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: titleContent,
        ),
        iconTheme: new IconThemeData(color: Colors.white),
      ),
      withZoom: true,  // 允許網頁縮放
      withLocalStorage: true, // 允許LocalStorage
      withJavascript: true, // 允許執行js程式碼
    );
  }

  @override
  void dispose() {
    // 回收相關資源
    // Every listener should be canceled, the same should be done with this stream.
    onUrlChanged.cancel();
    onStateChanged.cancel();
    flutterWebViewPlugin.dispose();
    super.dispose();
  }
}

專案原始碼地址,此專案為持續開發專案,歡迎Start和Fork