Flutter_学习记录_实现列表上下拉加载 +实现加载html的数据

1. 效果图

2. 下拉加载的实现RefreshIndicator

在Flutter官方sdk中给我们提供了下拉刷新的组件RefreshIndicator。

dart 复制代码
// 显示内容列表
  Widget _showNewsListWidget() {
    if (_newsDataList.isNotEmpty) {
      //  RefreshIndicator 来实现下拉加载的功能
      return RefreshIndicator(
        onRefresh: () async {
          print("下拉加载");
     		// 网络数据的请求
          _getNewDataRequest();
        },
        child: ListView.builder(
          itemCount: _newsDataList.length,
          itemBuilder: (context, index) {
            return Column(
              children: [
                ListTile(
                  title: Text(_newsDataList[index]["title"]),
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(builder: (context) => NewsdetailDemo(cid: _newsDataList[index]["aid"])),
                    );
                  },
                )
              ],
            );
          }, 
        )
      );
    } else {
    	// loading
      return Center(
        child: CircularProgressIndicator(),
      );
    }
  }

3. 上拉加载的实现

flutter是没有提供上拉分页加载更多的组件,但是在Flutter ListView中有一个ScrollController组件,它就是专门来控制ListView滑动事件,在

这里我们可以根据ListView的位置来判断是否滑动到了底部来做加载更多的处理

上拉分页加载更多主要通过ListView监听 ScrollController 实现
_scrollController.position.pixels 滚动的距离
_scrollController.position.maxScrollExtent 总距离

核心代码,就是在 initState方法中,添加监听:

dart 复制代码
	_scrollController = ScrollController(); //listview的控制器

	_scrollController.addListener((){
      double scrollOffsetY =  _scrollController.position.pixels;
      double scrollContentHeight =  _scrollController.position.maxScrollExtent;
      if (scrollOffsetY > scrollContentHeight + 20) { 
        print("上拉加载更多");
        _getNewDataRequest();
      }
    });

ListView中的controller中 关联_scrollController, 代码如下:

dart 复制代码
ListView.builder(
          // controller 关联_scrollController
          controller: _scrollController,
          itemCount: _newsDataList.length,
          itemBuilder: (context, index) {
            return Column();
          })
        )

4. 实现列表上下拉加载的完整代码

dart 复制代码
import 'dart:convert';
import 'package:demoapp/Demo/NewsDemo/NewsDetail_demo.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';


class NewsDemo extends StatefulWidget {
  const NewsDemo({super.key});

  @override
  State<NewsDemo> createState() => _NewsDemoState();
}

class _NewsDemoState extends State<NewsDemo> {
  final ScrollController _scrollController = ScrollController();
  List _newsDataList = [];
  int _page = 1;
  bool _isLoadingData = false;
  bool _hasMoreData = true;

  // 获取网络请求的数据
  void  _getNewDataRequest() async {
    if (_isLoadingData == true ) {
      print("数据加载中,请勿重新加载");
      return;
    }
    if (_hasMoreData == false) {
      print("没有更多的数据了");
      return;
    }
    _isLoadingData = true;
    var apiUri = "https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$_page";
    print("apiUri = $apiUri");

    final response = await Dio().get(apiUri);
    List resultList = json.decode(response.data)["result"];
    setState(() {
      print("数据请求成功");
      if (_page == 1) {
        _newsDataList = resultList;
      } else {
        _newsDataList.addAll(resultList);
      }
      
      _isLoadingData = false;
      if (resultList.isNotEmpty) {
        _page += 1;
      }

      if (resultList.length < 20) {
        _hasMoreData = false;
      }
    });
  }

  // cell 底部视图的设置
  Widget _newsListCellBottomWidget(int index) {
    if (index == _newsDataList.length - 1) {
      if (_hasMoreData) {
        return CircularProgressIndicator();
      } else {
        return Text("---我也是有底线的---");
      }
    } else {
      return Divider();
    }
  }

  // 显示内容列表
  Widget _showNewsListWidget() {
    if (_newsDataList.isNotEmpty) {
      //  RefreshIndicator 来实现下拉加载的功能
      return RefreshIndicator(
        onRefresh: () async {
          print("下拉加载");
          _page = 1;
          _hasMoreData = true;
          _getNewDataRequest();
        },
        child: ListView.builder(
          controller: _scrollController,
          itemCount: _newsDataList.length,
          itemBuilder: (context, index) {
            return Column(
              children: [
                ListTile(
                  title: Text(_newsDataList[index]["title"]),
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(builder: (context) => NewsdetailDemo(cid: _newsDataList[index]["aid"])),
                    );
                  },
                ),
                _newsListCellBottomWidget(index)
              ],
            );
          }, 
        )
      );
    } else {
      return Center(
        child: CircularProgressIndicator(),
      );
    }
  }

  @override
  void initState() {
    super.initState();

    _scrollController.addListener((){
      double scrollOffsetY =  _scrollController.position.pixels;
      double scrollContentHeight =  _scrollController.position.maxScrollExtent;
      if (scrollOffsetY > scrollContentHeight + 20) { 
        print("上拉加载更多");
        _getNewDataRequest();
      }
    });

    _getNewDataRequest();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("模拟新闻列表上下拉加载 + 加载html的数据"),
      ),
      body: _showNewsListWidget(),
    );
  }
}

5. 加载 Html 的数据

  1. 第三方插件:flutter_widget_from_html_core: ^0.16.0
  2. 引入头文件:
dart 复制代码
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
  1. 使用代码
dart 复制代码
           return HtmlWidget(
              "xxxx==> Html 的数据",
              onTapImage: (imageMetadata) {
                print(imageMetadata);
              },
              onTapUrl: (url) {
                print(url);
                return true;
              },
            );

6. 实现加载html的数据,完整代码

dart 复制代码
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';

class NewsdetailDemo extends StatefulWidget {
  final String cid;
  const NewsdetailDemo({super.key, required this.cid});

  @override
  State<NewsdetailDemo> createState() => _NewsdetailDemoState();
}

class _NewsdetailDemoState extends State<NewsdetailDemo> {

  List _resultDetailList = [];

  // 获取详情的数据
  void _getNewsDetailRequest() async {
    String apiUri = "https://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=${widget.cid}";
    final response = await Dio().get(apiUri);
    final result = json.decode(response.data)["result"];
    setState(() {
      _resultDetailList = result;
    });
  }

  // 内容视图
  Widget _newsDetailWidget() {
    if (_resultDetailList.isNotEmpty) {
      Map resultInfo = _resultDetailList.isNotEmpty ?  _resultDetailList[0] : {};
      return Padding(
        padding: EdgeInsets.all(10),
        child: ListView(
          children: [
            Text(resultInfo["title"], textAlign: TextAlign.center, style: TextStyle(fontSize: 24),),
            SizedBox(height: 20),
            HtmlWidget(
              resultInfo["content"],
              onTapImage: (imageMetadata) {
                print(imageMetadata);
              },
              onTapUrl: (url) {
                print(url);
                return true;
              },
            )
          ],
        ),
      );
    } else {
      return Center(child: CircularProgressIndicator());
    }
  }

  @override
  void initState() {
    super.initState();

    _getNewsDetailRequest();
  }

  @override
  Widget build(BuildContext context) {
    
    return Scaffold(
      appBar: AppBar(
        title: Text("详情"),
      ),
      body: _newsDetailWidget(),
    );
  }
}
相关推荐
moton201711 小时前
Flutter开发避坑指南:高频问题排查与性能调优实战
mqtt·flutter·性能优化·前端框架·自动化·dart
云水-禅心11 小时前
Flutter中网络图片加载显示Image.network的具体用法
flutter
云水-禅心11 小时前
flutter的HTTP headers用法介绍
flutter·httpclient
前端 贾公子19 小时前
Vue.js 3 的设计思路:从声明式UI到高效渲染机制
vue.js·flutter·ui
帅次21 小时前
Flutter:StatelessWidget vs StatefulWidget 深度解析
android·flutter·ios·小程序·swift·webview·android-studio
pengyu1 天前
系统化掌握Flutter开发之GestureDetector(一):筑基之旅
android·flutter·dart
帅次1 天前
Flutter Widget 体系结构解析
android·flutter·ios·小程序·xcode·web app·dalvik
秋月华星1 天前
【flutter】TextField输入框工具栏文本为英文解决(不用安装插件版本
前端·javascript·flutter
程序员老刘·1 天前
Flutter开发者 3.29版本关注要点
flutter·跨平台开发·客户端开发