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…