Preface:

I haven’t updated my article for a long time. Recently, I have read the pull-down refresh and pull-up loading of down Flutter. Today, I would like to share with you the half-finished movie app of flutter, which I helped my friend to make in my graduation design, with the functions of pull-down refresh and pull-up loading

Preparations:

Install a Flutter development environment for Windows. Install the flutter development environment for Windows.

www.jianshu.com/p/152447bc8…

2 MAC flutter development environment installed tutorial: www.jianshu.com/p/bad2c35b4…

Tripartite libraries to use:

Dio: ^ 3.0.9 toast: ^ 0.1.5

Please add dependencies in the pubspec.yaml file

As shown in figure:

Then enter flutter pub get on the console to download dependencies

Effect:

Concrete implementation:

Bottom TAB switch

bottomNavigationBar:Container( decoration: BoxDecoration( color: Colors.black ), height: 50, child: TabBar( labelStyle: TextStyle(height: 0, fontSize: 10), tabs: <Widget>[Tab(icon: icon (Icons. Movie_filter),text: "iS hot ",), Tab(icon: Icon(Icons. Movie_creation),text: "coming soon ", Tab(Icon: Icon(Icons. Local_movies),text: "Top250",),),), body: TabBarView( children: <Widget>[ Movielist(mt: "in_theaters",), Movielist(mt:"coming_soon"), Movielist(mt:"top250"), ], ),Copy the code

So here we’re using the bottomNavigationBar component to have three tabs nested inside it to switch the bottom TAB as I mentioned before, and then we’re adding three widgets inside the body to handle the movie list display page above

    body: TabBarView(
          children: <Widget>[
            Movielist(mt: "in_theaters",),
            Movielist(mt:"coming_soon"),
            Movielist(mt:"top250"),
          ],
        ),
Copy the code

Since the structure of the three list pages is the same, we can use one page to pass in different parameters to achieve it

The sidebar implements:

Effect:We added a Drawer component sidebar to the Scaffold Scaffold and then nested a ListView component inside the Drawer component and used the listView layout to implement the sidebar layout

drawer:new Drawer( child: ListView.builder( padding: EdgeInsets.all(0), itemCount: 5, itemBuilder: (BuildContext context, int position){ if(position==0){ return item1(position); }else{ return item2(position); }}),),Copy the code

Of course, you can do this with other components (Column linear layout component for layout, for example)

Movie list (pull-down refresh pull-up load implementation)

Effect:

The drop-down refresh

To refresh, we need to nest a RefreshIndicator around the ListView and then implement onRefresh inside the RefreshIndicator.

@override Widget build(BuildContext context) { // TODO: implement build return Container( child:RefreshIndicator( onRefresh:_refresh , child: ListView.builder( controller: ItemCount: data==null? 0:data.length, itemBuilder: (BuildContext context, int position){ return itemWidget(position); },),)); }Copy the code

The onRefresh method is implemented _refresh. Note that async must be used or an error will be reported

Future _refresh()async {print(" pull load "); page=0; data.clear(); getMovielist(); return null; }Copy the code

Asynchronously loading data We use DIO to do network requests to get data and then override setState to refresh the UI

getMovielist()async { this.page++; int offset=(page-1)*pagesize; Dio dio=new Dio(); Response response=await dio.get("http://www.liulongbin.top:3005/api/v2/movie/${widget.mt}? start=$offset&count=$pagesize"); setState(() { var result=response.data.toString(); Print ("result ---- "+result); movieBean =MovieBean.fromJson(response.data); data.addAll(movieBean.subjects); }); }Copy the code

Here we’re using the MovieBean data model class to convert json data into entities to get the data inside, and we’re calling addAll in the list to addAll the returned lists to Listdata=new list () for each load; The data set we define completes the purpose of pull-up loading data

Pull on loading

Loading more requires listening on the ListView, so you need to set up the listener and initialize the listener in State.

// initialize the scrolllistener and load more scrollController_controller = new ScrollController();Copy the code

Set up the listener in the constructor

_MovielistState() {// Initialize scrolllistener, Load more use _controller. AddListener (() {var maxScroll = _controller. Position. MaxScrollExtent; var pixel = _controller.position.pixels; // if (maxScroll == pixel&& data.length < total) {setState(() {loadMoreText = "loading..." ; LoadMoreTextStyle = new TextStyle(color: const color (0xFF4483f6), fontSize: 14.0); }); getMovielist(); } else {setState(() {loadMoreText = "No more data "; LoadMoreTextStyle = new TextStyle(color: const color (0xFF999999), fontSize: 14.0); }); }}); }Copy the code

Then we add the listener Controller method to the ListView

Child: Listview. builder(Controller: _controller, itemCount: data==null? 0:data.length, itemBuilder: (BuildContext context, int position){ return itemWidget(position); },Copy the code

So far our flutter pull-down refresh and pull-up load have covered the entire movie_list class code example

import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'movie_bean.dart'; import '.. /toast_util.dart'; */ class Movielist extends StatefulWidget {final String mt; Movielist({Key key,this.mt}) : super(key: key); @override _MovielistState createState() { return _MovielistState(); } } class _MovielistState extends State<Movielist> { int page=1; int pagesize=5; var mlist=[]; var total=0; int datasize=0; MovieBean movieBean; Subject _subject; List<Subject>data=new List(); String loadMoreText; ScrollController _controller = new ScrollController(); _MovielistState() {// Initialize scrolllistener, Load more use _controller. AddListener (() {var maxScroll = _controller. Position. MaxScrollExtent; var pixel = _controller.position.pixels; If (maxScroll == pixel&& data.length < total&&datasize<=5) {loadMoreText = "Loading..." ; ToastUtil.showInfo(context, loadMoreText); getMovielist(); } else {loadMoreText = "No more data "; ToastUtil.showInfo(context, loadMoreText); }}); } @override void initState() { super.initState(); getMovielist(); } @override void dispose() { super.dispose(); } getMovielist()async { this.page++; int offset=(page-1)*pagesize; Dio dio=new Dio(); Response response=await dio.get("http://www.liulongbin.top:3005/api/v2/movie/${widget.mt}?start=$offset&count=$pagesize"); setState(() { var result=response.data.toString(); Print ("result ---- "+result); movieBean =MovieBean.fromJson(response.data); data.addAll(movieBean.subjects); total=movieBean.total; datasize=movieBean.subjects.length; print("datasize --- > "+datasize.toString()); }); } @override Widget build(BuildContext context) { // TODO: implement build return data.length==0? new Center(child: new CircularProgressIndicator()) :Container( child:RefreshIndicator( onRefresh:_refresh , child: ItemCount: data==null? Listview. builder(Controller: _controller, // itemCount: data==null? 0:data.length, itemBuilder: (BuildContext context, int position){ return itemWidget(position); },),)); } Future _refresh()async {print(" pull load "); page=0; data.clear(); getMovielist(); return null; } /** * item layout ** / Widget itemWidget(int index){_subject=data[index]; Rating rating=_subject.rating; If (_subject==null){return Container(child: Center(child: Text),style: TextStyle(color: color. red,fontSize: 30),),),); }else{ return GestureDetector( child:Container( height: 200, decoration: BoxDecoration(color: Colors.white,border: Border( top: BorderSide( color: Colors.black ) )), child:Row( children: <Widget>[ Image.network(_subject.images.small, width: 130, height: 180, fit: BoxFit.fill,), Container( height: 200, child:Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: < widgets > [Text (" movie name: "+ _subject. The title), Text (" release date" + _subject. Year), Text (" film type: "+ _subject. Genres. Join (",")), "+_subject.rating. Average +"分"), Row(children: <Widget>[children: <Widget>], Container(width: 30, height: 30) 30, child: Image.network(_subject.images.small), ), Container( width: 30, height: 30, child: Image.network(_subject.images.large), ), Container( width: 30, height: 30, child: Image.network(_subject.images.medium) ) ], ) ], ), ) ], ) , ) ); }}}Copy the code

Conclusion:

The onRefresh refresh method in the RefreshIndicator and the controller slide listener in the listview component can be implemented in a flutter, which is much simpler than native. Of course, we can also use some tripartite libraries to refresh and pull up loading, such as (dynamic_list_view component), etc. Students who are interested in learning can exchange more privately. Finally, I hope my article can help you solve the problem, and I will contribute more useful code to share with you in the future. If you think the article is good, please pay attention to it and star. Thank you and you can also add my personal QQ/ wechat (1693891473).

Project Address:

Yards cloud: gitee.com/qiuyu123/fl…