关于Flutter下拉刷新和上拉分页

在Flutter官方sdk中给我们提供了下拉刷新的组件RefreshIndicator。但是没有提供上拉分页加载更多的组件。但是在Flutter ListView中有一个ScrollController属性,它就是专门来控制ListView滑动事件,在这里我们可以根据ListView的位置来判断是否滑动到了底部来做加载更多的处理。

教程涉及Api接口:

https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1

Flutter RefreshIndicator组件实现下拉刷新

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List _list = [];
  _getData() async {
    String apiUri =
        "https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1";
    var response = await Dio().get(apiUri);
    var result = json.decode(response.data);
    setState(() {
      _list = result["result"];
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return _list.isNotEmpty
        ? RefreshIndicator(
          onRefresh: () async { 
            print('下拉刷新');
            await _getData();
          },
          child: ListView(
            children: _list.map((e) {
              return ListTile(
                title: Text(e["title"]),
              );
            }).toList(),
          ),
        )
        : const Center(child: CircularProgressIndicator());
  }
}

Flutter 上拉分页加载更多

上拉分页加载更多主要通过ListTile监听 ScrollController 实现

_scrollController.position.pixels 滚动的距离

_scrollController.position.maxScrollExtent 总距离

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  ScrollController _scrollController = ScrollController(); //listview的控制器
  List _list = [];
  int _page=1;
  bool _flag = true; // 解决重复请求的问题
  bool _hasMore = true; // 是否有更多数据的标志
  _getData() async {
    if(_flag && _hasMore){
      _flag = false;
      String apiUri =
        "https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=$_page";
        print(apiUri);
    var response = await Dio().get(apiUri);
    var result = json.decode(response.data);
    if(result["result"].length < 20){
      setState(() {
        _hasMore = false;
      });
    }
    setState(() {
      _list.addAll(result["result"]);
      _page++;
      _flag = true;
    });
  }
    }


  @override
  void initState() {
    super.initState();
    _getData();
    // 监听滚动事件
    _scrollController.addListener(() {
      // 判断是否滚动到底部
      if (_scrollController.position.pixels > _scrollController.position.maxScrollExtent-20) {
        print('滑动到了底部');
        _getData();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return _list.isNotEmpty
        ? RefreshIndicator(
          onRefresh: () async { 
            print('下拉刷新');
            await _getData();
          },
          child: ListView.builder(
            itemBuilder: (context, index) {
              if (index == _list.length - 1) {
                return Column(
                  children: [
                    ListTile(
                      title: Text(_list[index]["title"]),
                    ),
                    _getMoreWidget(),
                  ],
                );
              } else {
                return Column(
                  children: [
                    ListTile(
                      title: Text(_list[index]["title"]),
                    ),
                  ],
                );
              }
            },
            itemCount: _list.length,
            controller: _scrollController,
          ),
        )
        :  _getMoreWidget();
  }

  // 自定义加载更多的组件
  Widget _getMoreWidget() {
    if (_hasMore) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: const [
                Text('加载中...',style: TextStyle(fontSize: 16.0),),
              CircularProgressIndicator(
                strokeWidth: 1.0,
              )
            ],
          ),
        ),
      );
    } else {
      return const Center(
        child: Text(
          '没有更多数据了',
          style: TextStyle(fontSize: 16.0),
        ),
      );
    }
  }
}

Flutter实现一个简单的新闻系统

涉及的api接口

新闻列表: https://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1

新闻详情:https://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=20

flutter_html 解析html

flutter_html官方文档:https://pub.flutter-io.cn/packages/flutter_html

flutter_html示例demo: https://github.com/Sub6Resources/flutter_html/tree/master/example

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:flutter_html/flutter_html.dart';

class NewsContentPage extends StatefulWidget {
  final Map arguments;
  const NewsContentPage({super.key, required this.arguments});

  @override
  State<NewsContentPage> createState() => _NewsContentPageState();
}

class _NewsContentPageState extends State<NewsContentPage> {
  List _list = [];

  _getData() async {
    String apiUri =
        "https://www.phonegap100.com/appapi.php?a=getPortalArticle&aid=${widget.arguments['aid']}";
        print(apiUri);
    var response = await Dio().get(apiUri);
    var result = json.decode(response.data);
    setState(() {
      _list = result['result'];
    });
    print(_list);
  }

  @override
  void initState() {
    super.initState();
    print(widget.arguments);
    _getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('新闻详情页'),
      ),
      body: _list.isNotEmpty ? ListView(
        children: [
          Text(_list[0]['title']),
          Padding(
            padding: const EdgeInsets.all(10),
            child: Html(data: _list[0]['content']),
          )

        ],
      ) : const Center(
        child:  CircularProgressIndicator(),
      ),
    );
  }
}

flutter_inappwebview 插件的使用

插件地址:https://pub.dev/packages/flutter_inappwebview

Example地址:https://github.com/pichillilorenzo/flutter_inappwebview/tree/master/example/lib

results matching ""

    No results matching ""