Flutter ListView 列表点击和网页加载

Posted 子不语归来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();
  


项目源代码地址,此项目为持续开发项目,欢迎Star和Fork

以上是关于Flutter ListView 列表点击和网页加载的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 在 ListView 中仅重建一行

安卓 怎么做下图所示效果,图片加文字,一列列的,点击一列会进入详情。列表图片加文字要怎么实现啊,

flutter学习ListView

Flutter 之列表和头部 (ListView + Header)

ListView 基础列表组件水平 列表组件图标组件

Flutter ListView 与不同的小部件和列表项