With this understanding and exposure to Flutter, you can learn how to develop a project using Flutter in its entirety.In fact, in Flutter, everything is a widget, and our interface is stacked with widgets.
A Flutter project involves the following points:
- Project Code Layering
- Theme Style
- Plug-in unit
- Route
- Network Data Interaction
- Interface Layout and Refresh
1. Layering of project code
A formal project whose code must be hierarchical reflects the architectural capabilities of the initiator.
Main working lib directory and pubspec.yaml for Flutter project:
- main.dart:Flutter's entry function
- Load.dart: Startup page, average lifetime 3-5 seconds
- app.dart: Project master file
- conf: Configuration file current or some macro-defined data file directory
- Model: Data model catalog
- pages: each UI, the Widget file
- service: network request directory
- Style: Custom style file (color, font, etc.)
- utils: Tools directory
The unreasonable design of code hierarchy directly affects the maintainability and stability of code.
2. Theme Style
Flutter defaults to blue and white themes, while other themes need to be configured.Depending on the project, configure a red-grey style for the current needs:
#main.dart void main() => runApp(MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter actual combat', //Custom Theme theme: mDefaultTheme, )); //Custom Theme final ThemeData mDefaultTheme = ThemeData( primaryColor: Colors.redAccent, );
Colors.redAccent is the system theme, defined in colors.dart:
static const MaterialAccentColor redAccent = MaterialAccentColor( _redAccentValue, <int, Color>{ 100: Color(0xFFFF8A80), 200: Color(_redAccentValue), 400: Color(0xFFFF1744), 700: Color(0xFFD50000), }, ); static const int _redAccentValue = 0xFFFF5252;
Of course, you can also customize some styles or colors, in the project style color.dart:
//Product color class ProductColors{ static const Color bgColor = Color(0xFFFFFFFF); static const divideLineColor = Color.fromRGBO(245, 245, 245, 1.0); static const typeColor = Color.fromRGBO(182, 9, 9, 1.0); static const piontColor = Color.fromRGBO(132, 95, 63, 1.0); }
3. Plug-ins
It is impossible for developers to make their own wheels for each function and choose the right one. For a project, you can get twice the result with half the effort.
3.1 Add third-party libraries
Open the pubspec.yaml file to add a tripartite library, which you can use in https://pub.dev/flutter Many open source packages were found on (FQ required)
dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 http: ^0.12.0 flutter_webview_plugin: ^0.3.0 flutter_swiper: 1.1.4
- http: Network Request Plugin
- flutter_webview_plugin: Some static page loads, using WebView
- flutter_swiper: Animation Relay Effect
3.2 Import
swiper plug-in
Click Packages get to get the package you just added.
This allows you to use the library.
4. Routing
Routing is mainly used for interface switching and jumping, which is divided into static routing and dynamic routing
- Static routing: interface jumps without additional parameters
- Dynamic routing: interface jumps can carry additional parameters
4.1 Routing Initialization
void main() => runApp(MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter actual combat', //Custom Theme theme: mDefaultTheme, //Add Route routes: <String,WidgetBuilder>{ "app": (BuildContext context) => App(), "company_info":(BuildContext context) => WebviewScaffold( url: "https://www.baidu.com", appBar: AppBar( title: Text('Company Introduction'), leading: IconButton( icon: Icon(Icons.home), onPressed: (){ //Route to Home Interface Navigator.of(context).pushReplacementNamed('app'); }, ), ), ), }, //Specify Load Page home: LoadingPage(), ));
4.2 Static Routing
Navigator.of(context).pushReplacementNamed('company_info');
4.3 Dynamic Routing
Navigator.push(context,MaterialPageRoute(builder: (context) => AboutContactPage()));
perhaps
Navigator.push(context,MaterialPageRoute(builder: (context) => NewsDetailPage(item: item)),
Data Receive Processing:
class NewsDetailPage extends StatelessWidget{ final NewsItemModal item; NewsDetailPage({Key key,@required this.item}) : super(key:key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(item.title), ), body: Padding( padding: EdgeInsets.all(16.0), child: Text(item.content), ), ); } }
V. Network Data Interaction
Network data interaction generally involves URL s, data models, data interaction modes (Get, Post), etc.
5.1 URL Definition
Define macro variables in configuration
class Config{ static const String IP = '192.168.2.5'; static const String PORT = '8080'; }
5.2 Data Model
//News List Item Data Conversion class NewsItemModal{ String author;//author String title;//Title String content;//content NewsItemModal({ this.author, this.title, this.content, }); factory NewsItemModal.fromJson(dynamic json){ return NewsItemModal( author: json['author'], title: json['title'], content: json['content'], ); } } //News List Data Conversion class NewsListModal{ List<NewsItemModal> data; NewsListModal(this.data); factory NewsListModal.fromJson(List json){ return NewsListModal( json.map((i) => NewsItemModal.fromJson((i))).toList() ); } }
5.3 Data Interaction Mode
import 'package:http/http.dart' as http; import 'dart:convert'; import '../conf/configure.dart'; //Get news data getNewsResult() async { String url = 'http://' + Config.IP + ':' + Config.PORT + '/?action=getNews'; var res = await http.get(url); String body = res.body; var json= jsonDecode(body); print(json); return json['items'] as List; }
6. Interface Layout and Refresh
6.1 Startup Page Loading
An interface that lasts 3-5 seconds
class LoadingPage extends StatefulWidget{ @override _LoadingState createState() => _LoadingState(); } class _LoadingState extends State<LoadingPage>{ @override void initState(){ super.initState(); //Pause on load page for 3 seconds Future.delayed(Duration(seconds: 3),(){ print('Flutter Enterprise Station Startup...'); Navigator.of(context).pushReplacementNamed("app"); }); } @override Widget build(BuildContext context) { return Center( child: Center( child: Stack( children: <Widget>[ //Load Page Background Map Image.asset( 'assets/images/loading.jpeg' ), Center( child: Text( 'Flutter', style: TextStyle( color: Colors.white, fontSize: 36.0, decoration: TextDecoration.none ), ), ), ], ), ), ); } }
6.2 Relay Pictures
Roadcasting pictures are widely used, such as advertising.
In the Resource Configuration Picture, add a picture
# To add assets to your application, add an assets section, like this: assets: - assets/images/loading.jpeg - assets/images/company.jpg #Roadcast Pictures - assets/images/banners/1.jpeg - assets/images/banners/2.jpeg - assets/images/banners/3.jpeg - assets/images/banners/4.jpeg
Using the Swiper plug-in
import 'package:flutter/material.dart'; import 'package:flutter_swiper/flutter_swiper.dart'; class BannerWidget extends StatelessWidget{ //Picture Path List<String> banners = <String>[ 'assets/images/banners/1.jpeg', 'assets/images/banners/2.jpeg', 'assets/images/banners/3.jpeg', 'assets/images/banners/4.jpeg', ]; @override Widget build(BuildContext context) { //Calculate proportionate width to height double width = MediaQuery.of(context).size.width; double height = width * 540.0 / 1080.0; return Container( width: width, height: height, //Roadcasting Component child: Swiper( itemBuilder: (BuildContext context, index){ return Container( //Left and right margins margin: EdgeInsets.only(left: 5, right: 5), child: Image.asset( banners[index], width: width, height: height, fit: BoxFit.cover, ), ); }, //Number of Rolls itemCount: banners.length, //direction scrollDirection: Axis.horizontal, //Whether to Play Automatically autoplay: true, ), ); } }
6.3 Main interface (with navigation bar)
import 'package:flutter/material.dart'; import 'pages/about_us_page.dart'; import 'pages/home_page.dart'; import 'pages/news_page.dart'; import 'pages/product_page.dart'; class App extends StatefulWidget { @override AppState createState() => AppState(); } class AppState extends State<App> { //Currently Selected Page Index var _currentIndex = 0; HomePage homePage; ProductPage productPage; NewsPage newsPage; AboutUsPage aboutUsPage; //Return different pages based on the current index currentPage(){ switch(_currentIndex){ case 0: if(homePage == null){ homePage = HomePage(); } return homePage; case 1: if(productPage == null){ productPage = ProductPage(); } return productPage; case 2: if(newsPage == null){ newsPage = NewsPage(); } return newsPage; case 3: if(aboutUsPage == null){ aboutUsPage = AboutUsPage(); } return aboutUsPage; } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Flutter Enterprise Station Actual Warfare'), leading: Icon(Icons.home), actions: <Widget>[ //Right margin Padding( padding: EdgeInsets.only(right: 20.0), child: GestureDetector( onTap: () {}, child: Icon( Icons.search, ), ), ), ], ), body: currentPage(), //Bottom navigation bar bottomNavigationBar: BottomNavigationBar( //Set the color of the selected item by fixedColor type: BottomNavigationBarType.fixed, currentIndex: _currentIndex, onTap: ((index) { setState(() { _currentIndex = index; }); }), //Bottom navigation bar items: [ BottomNavigationBarItem( title: Text( 'home page', ), icon: Icon(Icons.home), ), BottomNavigationBarItem( title: Text( 'product', ), icon: Icon(Icons.apps), ), BottomNavigationBarItem( title: Text( 'Journalism', ), icon: Icon(Icons.fiber_new), ), BottomNavigationBarItem( title: Text( 'About us', ), icon: Icon(Icons.insert_comment), ), ]), ); } }
6.4 Application of ListView
import 'package:flutter/material.dart'; import '../model/news.dart'; import '../services/news.dart'; import 'news_detail_page.dart'; //News Page class NewsPage extends StatefulWidget { @override NewsPageState createState() => NewsPageState(); } class NewsPageState extends State<NewsPage> { NewsListModal listData = NewsListModal([]); //Get News List Data void getNewsList() async { var data = await getNewsResult(); NewsListModal list = NewsListModal.fromJson(data); setState(() { listData.data.addAll(list.data); }); } @override void initState() { getNewsList(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( //List with Separator body: ListView.separated( //Arrangement Direction Vertical and Horizontal scrollDirection: Axis.vertical, //Separator builder separatorBuilder: (BuildContext contex, int index) => Divider( height: 1.0, color: Colors.grey, ), itemCount: listData.data.length, //List Item Builder itemBuilder: (BuildContext contex, int index) { //News List Item Data NewsItemModal item = listData.data[index]; return ListTile( title: Text(item.title), subtitle: Text(item.content), leading: Icon(Icons.fiber_new), trailing: Icon(Icons.arrow_forward), contentPadding: EdgeInsets.all(10.0), enabled: true, //Jump to the news details page onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => NewsDetailPage(item: item)), ); }, ); }, ), ); } }
6.5 Text Box Operation
Contains text box configuration and data manipulation
import 'package:flutter/material.dart'; import '../services/contact.dart'; class AboutContactPage extends StatefulWidget{ @override AboutContactPageState createState() => AboutContactPageState(); } class AboutContactPageState extends State<AboutContactPage>{ //Text Editing Controller TextEditingController controller = TextEditingController(); //Submit data void commit(){ if(controller.text.length == 0){ showDialog(context: context,builder: (context) => AlertDialog(title: Text('Please enter content'),),); } else{ var info = contactCompany(controller.text); print(info); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Leave a message for me'), ), body: Container( color: Colors.white, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Image.asset( 'assets/images/company.jpg', fit: BoxFit.cover, ), SizedBox( height: 40.0, ), SizedBox( width: 380.0, child: TextField( controller: controller, decoration: InputDecoration( hintText: 'Please leave a message', labelText: 'Please leave a message', border: OutlineInputBorder(), prefixIcon: Icon(Icons.person), ), ), ), SizedBox( height: 40.0, ), SizedBox( width: 220.0, height: 48.0, child: RaisedButton( child: Text('Leave us a message',style: TextStyle(fontSize: 16.0),), color: Theme.of(context).primaryColor,//Colors.redAccent, colorBrightness: Brightness.dark, textColor: Colors.white, padding: EdgeInsets.only( left: 20.0, right: 20.0, top: 5.0, bottom: 5.0, ), shape: RoundedRectangleBorder( side: BorderSide( width: 1.0, color: Colors.white, style: BorderStyle.solid, ), borderRadius: BorderRadius.only( topRight: Radius.circular(4.0), topLeft: Radius.circular(4.0), bottomLeft: Radius.circular(4.0), bottomRight: Radius.circular(4.0), ), ), onPressed: (){ commit(); }, ), ), ], ), ), ); } }
7. Points of Attention
- =>is an abbreviation of one-line function in Dart
- StatelessWidget represents a component with only one state, corresponding to StatefulWidget (indicating that there may be multiple states).
- Widget components are built to describe their internal structure.Here, build means that the system components used to build MyApp are MaterialApp.
- Home tag value: Scaffold is a component provided in Material library where we can set the navigation bar, title, and body properties that contain the home screen widget tree.You can see here that AppBar and a Text are added to the page.
- Center is a component that can center subcomponents