Flutter complete example

After this period of understanding and contact with Flutter, Flutter learn how to use the complete development of a project. In fact, Flutter, the Everything widget, our interface are stacked up by the various widget.

Flutter complete example

A Flutter project involves the following points:

  • Project Code stratified
  • Theme style
  • Plug
  • routing
  • Network data exchange
  • Interface layout and refresh
    Flutter complete example

    A project code is stratified

A formal project, its code must be done stratified, hierarchical code reflects the architecture's ability to start.
Flutter complete example

Flutter engineering major work lib directory and pubspec.yaml:

  • main.dart: Flutter entry function
  • loading.dart: Start page, the general life cycle of 3-5 seconds
  • app.dart: Project Master File
  • conf: configuration files or macros currently defined data file directory
  • model: data model directory
  • pages: each UI, ie the Widget file
  • service: network requests directory
  • style: custom style file (colors, fonts, etc.)
  • utils: Tool Catalog

Code hierarchical design design is reasonable, directly affects the stability and maintainability of the code.

Second, the theme style

Flutter default theme is  blue and white  style, you need to configure other topics. According to the project may be, according to current needs, configure a  Red Gray  Style:

#main.dart
void main() => runApp(MaterialApp(
  debugShowCheckedModeBanner: false,
  title: 'Flutter实战',
  //自定义主题
  theme: mDefaultTheme,

));

//自定义主题
final ThemeData mDefaultTheme = ThemeData(
  primaryColor: Colors.redAccent,
);

Colors.redAccent theme for the system, as defined in colors.dart in:

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 of the style or color, color.dart in style in the project:

//产品颜色
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);
}

Third, the plug-in

Developers can not create their own functions for each wheel, select the appropriate wheels for the project, it can achieve a multiplier effect.

3.1 Adding third-party libraries

Open the file pubspec.yaml add tripartite libraries, can be https://pub.dev/flutter  find many open source packages 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: Plug network requests
  • flutter_webview_plugin: Some add static pages, using webview
  • flutter_swiper: animated carousel effect

3.2 Import

swiper plug

Click Packages get get the package just added.

Flutter complete example

This enables the use of this library.

Fourth, routing

The main interface for routing and switching jump, divided into static and dynamic routing

  • Static Routing: Jumps interface with no additional parameters
  • Dynamic Routing: Jump interface may carry additional parameters

4.1 Routing initialization

void main() => runApp(MaterialApp(
  debugShowCheckedModeBanner: false,
  title: 'Flutter实战',
  //自定义主题
  theme: mDefaultTheme,

  //添加路由
  routes: <String,WidgetBuilder>{
    "app": (BuildContext context) => App(),
    "company_info":(BuildContext context) => WebviewScaffold(
      url: "https://www.baidu.com",
      appBar: AppBar(
        title: Text('公司介绍'),
        leading: IconButton(
            icon: Icon(Icons.home),
            onPressed: (){
              //路由到主界面
              Navigator.of(context).pushReplacementNamed('app');
            },
        ),
      ),
    ),
  },
  //指定加载页面
  home: LoadingPage(),

));

4.2 Static Routing

Navigator.of(context).pushReplacementNamed('company_info');

4.3 Dynamic Routing

Navigator.push(context,MaterialPageRoute(builder: (context) => AboutContactPage()));

or

Navigator.push(context,MaterialPageRoute(builder: (context) => NewsDetailPage(item: item)),

Data reception 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),
      ),
    );
  }
}

5, the network data exchange

Network data exchange generally involves URL, data model, data exchange mode (Get, Post), etc.

5.1 URL defined

Macro variables defined in the configuration

class Config{
  static const String IP = '192.168.2.5';
  static const String PORT = '8080';
}

5.2 Data Model

//新闻列表项数据转换
class NewsItemModal{
  String author;//作者
  String title;//标题
  String content;//内容

  NewsItemModal({
    this.author,
    this.title,
    this.content,
  });

  factory NewsItemModal.fromJson(dynamic json){
    return NewsItemModal(
      author: json['author'],
      title: json['title'],
      content: json['content'],
    );
  }
}

//新闻列表数据转换
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 Interactive mode

import 'package:http/http.dart' as http;
import 'dart:convert';
import '../conf/configure.dart';

//获取新闻数据
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;
}

Sixth, the interface layout and refresh

6.1 start page load

Interface 5 seconds - 3 present a

class LoadingPage extends StatefulWidget{
  @override
  _LoadingState createState() => _LoadingState();
}

class _LoadingState extends State<LoadingPage>{

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

    //在加载页面停顿3秒
    Future.delayed(Duration(seconds: 3),(){
      print('Flutter企业站启动...');
      Navigator.of(context).pushReplacementNamed("app");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Center(
        child: Stack(
          children: <Widget>[
            //加载页面背景图
            Image.asset(
              'assets/images/loading.jpeg'
            ),

            Center(
              child: Text(
                'Flutter',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 36.0,
                  decoration: TextDecoration.none
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

6.2 broadcast pictures

Carousel picture which is widely used, such as advertising and the like.

In resource allocation in the 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

  #轮播图片
  - assets/images/banners/1.jpeg
  - assets/images/banners/2.jpeg
  - assets/images/banners/3.jpeg
  - assets/images/banners/4.jpeg

Use Swiper plug

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

class BannerWidget extends StatelessWidget{

  //图片路径
  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) {

    //计算宽高 按比例
    double width = MediaQuery.of(context).size.width;
    double height = width * 540.0 / 1080.0;
    return Container(
      width: width,
      height: height,
      //轮播组件
      child: Swiper(
        itemBuilder: (BuildContext context, index){
          return Container(
            //图片左右内边距
            margin: EdgeInsets.only(left: 5, right: 5),
            child: Image.asset(
              banners[index],
              width: width,
              height: height,
              fit: BoxFit.cover,
            ),
          );
        },
        //轮播数量
        itemCount: banners.length,
        //方向
        scrollDirection: Axis.horizontal,
        //是否自动播放
        autoplay: true,
      ),
    );
  }
}

6.3 The main interface (including navigation)

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> {
  //当前选择页面索引
  var _currentIndex = 0;

  HomePage homePage;
  ProductPage productPage;
  NewsPage newsPage;
  AboutUsPage aboutUsPage;

  //根据当前索引返回不同的页面
  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企业站实战'),
        leading: Icon(Icons.home),
        actions: <Widget>[
          //右侧内边距
          Padding(
            padding: EdgeInsets.only(right: 20.0),
            child: GestureDetector(
              onTap: () {},
              child: Icon(
                Icons.search,
              ),
            ),
          ),
        ],
      ),

      body: currentPage(),

      //底部导航栏
      bottomNavigationBar: BottomNavigationBar(
          //通过fixedColor设置选中item 的颜色
          type: BottomNavigationBarType.fixed,
          currentIndex: _currentIndex,
          onTap: ((index) {
            setState(() {
              _currentIndex = index;
            });
          }),
          //底部导航栏
          items: [
            BottomNavigationBarItem(
              title: Text(
                '首页',
              ),
              icon: Icon(Icons.home),
            ),
            BottomNavigationBarItem(
              title: Text(
                '产品',
              ),
              icon: Icon(Icons.apps),
            ),
            BottomNavigationBarItem(
              title: Text(
                '新闻',
              ),
              icon: Icon(Icons.fiber_new),
            ),
            BottomNavigationBarItem(
              title: Text(
                '关于我们',
              ),
              icon: Icon(Icons.insert_comment),
            ),
          ]),
    );
  }
}

6.4 ListView applications

import 'package:flutter/material.dart';
import '../model/news.dart';
import '../services/news.dart';
import 'news_detail_page.dart';

//新闻页面
class NewsPage extends StatefulWidget {
  @override
  NewsPageState createState() => NewsPageState();
}

class NewsPageState extends State<NewsPage> {
  NewsListModal listData = NewsListModal([]);

  //获取新闻列表数据
  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
      body: ListView.separated(
        //排列方向 垂直和水平
        scrollDirection: Axis.vertical,
        //分隔线构建器
        separatorBuilder: (BuildContext contex, int index) => Divider(
              height: 1.0,
              color: Colors.grey,
            ),
        itemCount: listData.data.length,
        //列表项构建器
        itemBuilder: (BuildContext contex, int index) {

          //新闻列表项数据
          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,
            //跳转至新闻详情页面
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (context) => NewsDetailPage(item: item)),
              );
            },
          );
        },
      ),
    );
  }
}

6.5 text box operations

And a text box containing the configuration data operation

import 'package:flutter/material.dart';
import '../services/contact.dart';

class AboutContactPage extends StatefulWidget{
  @override
  AboutContactPageState createState() => AboutContactPageState();
}

class AboutContactPageState extends State<AboutContactPage>{

  //文本编辑控制器
  TextEditingController controller = TextEditingController();

  //提交数据
  void commit(){
    if(controller.text.length == 0){
      showDialog(context: context,builder: (context) => AlertDialog(title: Text('请输入内容'),),);
    } else{
      var info = contactCompany(controller.text);
      print(info);
    }
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text('给我留言'),
      ),
      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: '请留言',
                  labelText: '请留言',
                  border: OutlineInputBorder(),
                  prefixIcon: Icon(Icons.person),
                ),
              ),
            ),
            SizedBox(
              height: 40.0,
            ),
            SizedBox(
              width: 220.0,
              height: 48.0,
              child: RaisedButton(
                child: Text('给我们留言',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();
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Seven, pay attention to points

  • => Is shorthand for the one-way function of Dart
  • Representative StatelessWidget only one state of assembly, the corresponding StatefulWidget (showing a variety of possible state).
  • Widget components are in their internal structure to describe a method through the build. MyApp build herein represent constructs used in the system component MaterialApp.
  • home label values: Scaffold is a component Material library provided, we can set the navigation bar on the inside, and the title attribute contains the body home screen widget tree. Here you can see on the page is added AppBar and a Text.
  • Center is a component may be placed in the center of the sub-components

Guess you like

Origin blog.51cto.com/14541311/2437729
Recommended