本地配置nginx数据返回给->Flutter RefreshIndicator 和 SliverList ListView 和 CustomScrollView NestedScrollView

文章来自:http://blog.csdn.net/intbird

主要是两个使用方式: 

1. RefreshIndicator 包裹 CustomScrollView ( appbar + pindHeader + sliverList)

  

2. NestedScrollView 包裹 AppBar + RefreshIndicator( ListView)

   

1.配置本地nginx返回接口数据

    方便在没有服务器配合的情况下,单端完成数据调试

 1.mac os 下载并配置nginx:

> brew update

> brew search nginx

> brew install nginx

2.软链接nginx文件目录,方便后续修改:

> open /usr/local/Cellar/nginx/     // 查看nginx版本,比如后续的 1.17.6

> ln -s /usr/local/Cellar/nginx/1.17.6/docs /Users/intbird/configs/nginx/docs    // 挂载新建的docs目录到指定目录下

> touch /Users/intbird/configs/nginx/docs/index.json   // 创建一个默认的json文件,写点东西进去做测试

3.修改nginx配置,配置接口url:

1 > open /usr/local/etc/nginx/

2 写入 nginx.conf 文件如图配置:

3 > sudo nginx  // 首次启动nginx

4  如果已经启动则可刷新配置:  sudo nginx -s reload ; 

    停止nginx: sudo nginx -s stop

5 访问nginx地址,配置完成:

  

  附:除了本地插件,也可以在线json转dartbean: https://javiercbk.github.io/json_to_dart/

 

2,flutter项目 RefreshIndicator + SliverList + ListView 刷新效果

1,页面内容由完全由CustomScrollView实现,列表为SliverList

 重点示意:

   

  效果示意:

RefreshIndicator + SliverList 下拉刷新 RefreshIndicator + SliverList 上拉
/// homepage.dart

void main() => runApp(new MaterialApp(
    debugShowCheckedModeBanner: false,
    theme:ThemeData(brightness: Brightness.light, primaryColor: Colors.blueGrey),
    home: _scaffoldRefreshFromStatusBar()));

Scaffold _scaffoldRefreshFromStatusBar() { 
  // 下拉刷新完成通知列表数据刷新
  SwipeValueNotifierData swipeValueNotifierData =
      new SwipeValueNotifierData(new List<ListBeans>());
  return new Scaffold(
    body: SwipeRefreshContainer(
        // 下拉刷新完成存储最新数据
        swipeValueNotifierData: swipeValueNotifierData,
        swipeRefreshBody: SliverAppBarContainer1(
          //使用最新数据
          swipeValueNotifierData: swipeValueNotifierData,
        )),
    floatingActionButton: _floatingActionButton(),
  );
}

///swiper-refresh-container.dart


import 'package:flutter/material.dart';

import 'api/HomePageApi.dart' as api;
import 'api/beans/list_beans_entity.dart';

class SwipeRefreshContainer extends StatefulWidget {
  final Widget swipeRefreshBody;
  final SwipeValueNotifierData swipeValueNotifierData;

  SwipeRefreshContainer(
      {Key key, this.swipeRefreshBody, this.swipeValueNotifierData})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _CreateState();
  }
}

class _CreateState extends State<SwipeRefreshContainer> {
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
      new GlobalKey<RefreshIndicatorState>();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => _refreshIndicatorKey.currentState.show());
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      key: _refreshIndicatorKey,
      onRefresh: _refresh,
      child: widget.swipeRefreshBody ?? new Text("EMPTY"),
    );
  }

  Future<Object> _refresh() {
    return api.getListBeans().then((_lists) {
      widget.swipeValueNotifierData.value = _lists;
    }).catchError((error) {
      print(error);
    });
  }
}

class SwipeValueNotifierData extends ValueNotifier<List<ListBeans>> {
  SwipeValueNotifierData(List<ListBeans> value) : super(value);
}
///sliver-appbar-container-1.dart

import 'package:flutter/material.dart';
import 'package:intbird_lean_flutter_project/homepage/ListSliverWidget.dart';
import 'package:intbird_lean_flutter_project/homepage/SwipeRefreshContainer.dart';

class SliverAppBarContainer1 extends StatefulWidget {
  final SwipeValueNotifierData swipeValueNotifierData;

  SliverAppBarContainer1({Key key, this.swipeValueNotifierData})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _SliverAppBarBodyState();
  }
}

class _SliverAppBarBodyState extends State<SliverAppBarContainer1> {
  List<Object> listItems = new List<Object>();

  @override
  void initState() {
    super.initState();
    widget.swipeValueNotifierData.addListener(_swipeRefreshDataChanged);
  }

  _swipeRefreshDataChanged() {
    setState(() {
      listItems = widget.swipeValueNotifierData.value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return _scaffoldRefreshFromStatusBar();
  }

  /// 自定义的CustomScrollView,他的body为三块指定区域,列表由sliverList实现
  Scaffold _scaffoldRefreshFromStatusBar() {
    return new Scaffold(
        body: CustomScrollView(slivers: <Widget>[
      sliverAppBar(context),
      persistentHeader(),
      sliverList(),
    ]));
  }

  SliverPersistentHeader persistentHeader() {
    return SliverPersistentHeader(
      delegate: _SliverHeaderDelegate(),
      pinned: false,
    );
  }

  SliverList sliverList() {
    return SliverList(delegate: ListSliverWidget(listItems).createDelegate());
  }

  Widget sliverAppBar(context) {
    return SliverAppBar(
      floating: false,
      title: const Text("intbird title"),
      expandedHeight: 130,
      flexibleSpace: FlexibleSpaceBar(
        title: new Text("intbird flexibleSpace"),
        collapseMode: CollapseMode.pin,
      ),
    );
  }

  Widget sliverAbsorber(context) {
    return SliverOverlapAbsorber(
        handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
        child: SliverSafeArea(
          top: false,
          sliver: SliverAppBar(
            expandedHeight: 200,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
                title: Text('Title'),
                background: Container(color: Colors.amber)),
          ),
        ));
  }
}

class _SliverHeaderDelegate extends SliverPersistentHeaderDelegate {
  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new Container(
        color: Colors.red,
        alignment: Alignment.center,
        child: new Text("SliverPersistentHeader"));
  }

  @override
  // TODO: implement maxExtent
  double get maxExtent => 100;

  @override
  // TODO: implement minExtent
  double get minExtent => 100;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}
//ListSliverWidget.dart

class ListSliverWidget {
  final List<Object> listItems;

  ListSliverWidget(this.listItems);

  SliverChildBuilderDelegate createDelegate() {
    return SliverChildBuilderDelegate((context, index) {
      Object object = null != listItems ? listItems[index] : null;
      if (object is ListBeans) {
        return new ListBeanWidget(object);
      }
      return new Text("--no defined item--");
    }, childCount: listItems?.length ?? 1);
  }
}

2,页面内容由NestedScrollView实现,列表为ListView

重点示意:  因为头部多加了两个组件,所以刷新指示条位置较低

效果示意: 

NestedScrollView + ( RefreshIndicator + listview) 上推

    

    

   

/// homepage.dart

// scrollview内部进行下拉刷新
Scaffold _scaffoldRefreshFromAppBar() {
  SwipeValueNotifierData swipeValueNotifierData =
      new SwipeValueNotifierData(new List<ListBeans>());
  return new Scaffold(
    body: SliverAppBarContainer2(
        child: SwipeRefreshContainer(
      // 下拉刷新赋值数据
      swipeValueNotifierData: swipeValueNotifierData,
      swipeRefreshBody: ListViewWidget(
        // Listview监听数据刷新列表
        swipeValueNotifierData: swipeValueNotifierData,
      ),
    )),
    floatingActionButton: _floatingActionButton(),
  );
}
///swipe-refresh-container.dart


import 'package:flutter/material.dart';

import 'api/HomePageApi.dart' as api;
import 'api/beans/list_beans_entity.dart';

class SwipeRefreshContainer extends StatefulWidget {
  final Widget swipeRefreshBody;
  final SwipeValueNotifierData swipeValueNotifierData;

  SwipeRefreshContainer(
      {Key key, this.swipeRefreshBody, this.swipeValueNotifierData})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _CreateState();
  }
}

class _CreateState extends State<SwipeRefreshContainer> {
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
      new GlobalKey<RefreshIndicatorState>();

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => _refreshIndicatorKey.currentState.show());
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      key: _refreshIndicatorKey,
      onRefresh: _refresh,
      child: widget.swipeRefreshBody ?? new Text("EMPTY"),
    );
  }

  Future<Object> _refresh() {
    return api.getListBeans().then((_lists) {
      widget.swipeValueNotifierData.value = _lists;
    }).catchError((error) {
      print(error);
    });
  }
}

class SwipeValueNotifierData extends ValueNotifier<List<ListBeans>> {
  SwipeValueNotifierData(List<ListBeans> value) : super(value);
}
/// sliver-appbar-container-2.dart


import 'package:flutter/material.dart';
import 'package:intbird_lean_flutter_project/homepage/ListSliverWidget.dart';
import 'package:intbird_lean_flutter_project/homepage/SwipeRefreshContainer.dart';

class SliverAppBarContainer2 extends StatefulWidget {
  final Widget child;

  SliverAppBarContainer2({Key key, this.child}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _SliverAppBarBodyState();
  }
}

class _SliverAppBarBodyState extends State<SliverAppBarContainer2> {

  @override
  Widget build(BuildContext context) {
    return _scaffoldRefreshFromAppBar();
  }

  /// 传统做法 NestedScrollView: body由外部传入,可以是一个list
  Scaffold _scaffoldRefreshFromAppBar() {
    return new Scaffold(
        body: NestedScrollView(
      headerSliverBuilder: (context, innerBoxIsScrolled) {
        return <Widget>[
          sliverAppBar(context),
          persistentHeader(),
        ];
      },
      body: widget.child,
    ));
  }

  SliverPersistentHeader persistentHeader() {
    return SliverPersistentHeader(
      delegate: _SliverHeaderDelegate(),
      pinned: false,
    );
  }

  Widget sliverAppBar(context) {
    return SliverAppBar(
      floating: false,
      title: const Text("intbird title"),
      expandedHeight: 130,
      flexibleSpace: FlexibleSpaceBar(
        title: new Text("intbird flexibleSpace"),
        collapseMode: CollapseMode.pin,
      ),
    );
  }

  Widget sliverAbsorber(context) {
    return SliverOverlapAbsorber(
        handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
        child: SliverSafeArea(
          top: false,
          sliver: SliverAppBar(
            expandedHeight: 200,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
                title: Text('Title'),
                background: Container(color: Colors.amber)),
          ),
        ));
  }
}

class _SliverHeaderDelegate extends SliverPersistentHeaderDelegate {
  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new Container(
        color: Colors.red,
        alignment: Alignment.center,
        child: new Text("SliverPersistentHeader"));
  }

  @override
  // TODO: implement maxExtent
  double get maxExtent => 100;

  @override
  // TODO: implement minExtent
  double get minExtent => 100;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}
/// list-view-widget.dart

class ListViewWidget extends StatefulWidget {
  final SwipeValueNotifierData swipeValueNotifierData;

  const ListViewWidget({Key key, this.swipeValueNotifierData})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return new _ListViewState();
  }
}

class _ListViewState extends State<ListViewWidget> {
  List<Object> listItems = new List<Object>();

  _ListViewState({Key key, this.listItems});

  @override
  void initState() {
    super.initState();
    widget.swipeValueNotifierData.addListener(_swipeRefreshDataChanged);
  }

  _swipeRefreshDataChanged() {
    setState(() {
      listItems = widget.swipeValueNotifierData.value;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new ListView.builder(
      padding: EdgeInsets.zero,
      itemCount: listItems?.length ?? 1,
      itemBuilder: (context, index) {
        Object object = null != listItems ? listItems[index] : null;
        print("ListList:$object");
         if (object is ListBeans) {
          return new ListBeanWidget(object);
        }
        return new Text("--no defined item--");
      },
    );
  }
}

3 资源

1. bean

// index.json

[
    {
        "title": "title",
        "subTitle": "subTitle",
        "imageUrl": "imageUrl",
        "schemeUrl": "schemeUrl"
    },
    {
        "title": "title",
        "subTitle": "subTitle",
        "imageUrl": "imageUrl",
        "schemeUrl": "schemeUrl"
    },
...
]

2,接口请求:

import 'dart:async';
import 'dart:convert';

import 'package:http/http.dart' as http;

import 'beans/list_beans_entity.dart';

const HOST_URL = "http://192.168.3.156:8080";
const CONFIG_URL = "$HOST_URL/homepage-config";

Future<List<ListBeans>> getListBeans() async {
  final response = await http.get(CONFIG_URL);
  final respJson = json.decode(new Utf8Decoder().convert(response.bodyBytes));
  return ListBeans.fromJsonList(respJson);
}

文章来自:http://blog.csdn.net/intbird

猜你喜欢

转载自blog.csdn.net/intbird/article/details/103507135