Summary of knowledge points of Flutter

Posted by notepad on Sun, 14 Jun 2020 02:48:02 +0200

1. Theme color setting

 

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',//Available for Android
      theme: ThemeData(
        primarySwatch: Colors.yellow,//Theme color setting, dark: time and battery color are white; light: time and battery color are black
        highlightColor: Color.fromRGBO(1, 0, 0, 0.0),//Remove the default selection effect of tabBar
        splashColor: Color.fromRGBO(1, 0, 0, 0.0),//Remove the default selection effect of tabBar
      ),
      home: RootPage(),
    );
  }
}

2. Remove iPhone x bangs from listview

MediaQuery.removePadding -> removeTop: true

 

Container(
  color: Color.fromRGBO(220, 220, 220, 1.0),
  child: MediaQuery.removePadding(
    removeTop: true,
    context: context,
    child: ListView(
      children: <Widget>[
        Container(
          color: Colors.white,
          height: 200,
        ),
        SizedBox(height: 10,),
        DiscoverCell(imageName: 'images/Wechat payment 1.png',title: 'payment',),
      ],
    ),
  ),
),

3.Image setting fillet

 

Row(
children: <Widget>[
  Container(
    width: 70,
    height: 70,
   // child: Image(image: AssetImage('images/Steven.png ',), / / it is invalid to set fillet here
    decoration: BoxDecoration(
      color: Colors.blue,
      borderRadius: BorderRadius.circular(10.0),
      image: DecorationImage(image:AssetImage('images/Steven.png'),
      fit: BoxFit.cover)//Set the fill mode for pictures
    ),
  ),//head portrait
  Container(),//Right section
],
)

Set up a circular picture

 

CircleAvatar(
          backgroundImage: new AssetImage('images/1.jpeg'),
          radius: 100.0,
        )

4. Width and height acquisition of equipment

 

width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,

5. Setting of text center direction

 

//Container properties
alignment: Alignment.centerLeft,

6. Loading of network pictures and local pictures

 

Container(
  width: 34,
  height: 34,
  margin: EdgeInsets.all(10),
  decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(6.0),
      image: DecorationImage(
        image: imageUrl != null
            ? NetworkImage(imageUrl) //Network picture
            : AssetImage(imageAssets),//Local picture
      )),
)

7. Chain programming - adding data

 

 @override
 //Data and object creation
  void initState() {
    super.initState();
    //Chain programming, call addAllData twice and return the array to_ listDatas
    _listDatas..addAll(datas)..addAll(datas);
    //Data sorting
    _listDatas.sort((Friends a, Friends b){
      return a.indexLetter.compareTo(b.indexLetter);
    });
    //print('_listDatas:$_listDatas');
  }

8. Division and rounding

~/

 

onVerticalDragUpdate: (DragUpdateDetails details){
  print(details.globalPosition.dy);//Values relative to the entire screen
  RenderBox box = context.findRenderObject();
  //Calculate the coordinate conversion of the current position and calculate the y value
  double y = box.globalToLocal(details.globalPosition).dy;
  //The y value divided by the height of each item is the current index
  //Height of each item
  var itemH = ScreenHeight(context)/2/INDEX_WORDS.length;
  int index = y ~/ itemH;//Divide and round
  print(box.globalToLocal(details.globalPosition));
},

9. Array out of bounds processing

 

//Using clamp
//Value range 0~INDEX_WORDS.length-1 add safety judgment 
int index = (y ~/ itemHeight).clamp(0, INDEX_WORDS.length - 1);

10. Define callback functions and calls

 

//Define callback function
final void Function(String str) indexBarCallBack;
//Construction method
const IndexBar({Key key, this.indexBarCallBack}) : super(key: key);
//Call the callBack
//Monitor location: calculate the current location
onVerticalDragUpdate: (DragUpdateDetails details){
  widget.indexBarCallBack(getIndex(context, details.globalPosition));
},
//External use
IndexBar(
    indexBarCallBack: (String str){
      print("I got it: $str");
    },
  ),

11.PopupMenuButton

 

Container(
    margin: EdgeInsets.only(right: 10),
    child: PopupMenuButton(
      offset: Offset(0, 60.0),
      child: Image(image: AssetImage('images/Circle plus.png'),width: 25,),
      itemBuilder: _buildPopupMenuItem,
    ),
  )
    //How to create an Item!
  PopupMenuItem<String> _buildItem(String imgAss, String title) {
    return PopupMenuItem(
      child: Row(
        children: <Widget>[
          Image(
            image: AssetImage(imgAss),
            width: 20,
          ),
          Container(
            width: 20,
          ),
          Text(
            title,
            style: TextStyle(color: Colors.white),
          ),
        ],
      ),
    );
  }

//Callback method
  List<PopupMenuItem<String>> _buildPopupMenuItem(BuildContext context) {
    return <PopupMenuItem<String>>[
      _buildItem('images/Initiate group chat.png', 'Initiate group chat'),
      _buildItem('images/Add a friend.png', 'Add a friend'),
      _buildItem('images/Sweep 1.png', 'scan'),
      _buildItem('images/Collection and payment.png', 'Collection and payment'),
    ];
  }

Set pop background color

 

//MaterialApp -> theme -> cardColor
MaterialApp(
  debugShowCheckedModeBanner: false,
  title: 'Flutter Demo',//Available for Android
  theme: ThemeData(
    primarySwatch: Colors.yellow,//Theme color setting, dark: time and battery color are white; light: time and battery color are black
    highlightColor: Color.fromRGBO(1, 0, 0, 0.0),//Remove the default selection effect of tabBar
    splashColor: Color.fromRGBO(1, 0, 0, 0.0),//Remove the default selection effect of tabBar
    cardColor: Color.fromRGBO(1, 1, 1, 0.65),//Set pop background color
  ),
  home: RootPage(),
)

design sketch:

PopupMenuButton

12. Slide ListView to make keyboard disappear

FocusScope.of(context).requestFocus(FocusNode());

 

//Listen to the ListView's slide event and make the keyboard disappear
Expanded(
    flex: 1, //Occupy the remaining space
    child: MediaQuery.removePadding(
      context: context,
      removeTop: true,
      child: NotificationListener(
        onNotification: (ScrollNotification note){
          FocusScope.of(context).requestFocus(FocusNode());
        },//Slide to make the keyboard disappear
        child: ListView.builder(
          itemCount: _models.length,
          itemBuilder: _itemForRow,
        ),
      ),
    ),
  )

13. Contact set partial fillet and shadow effect

 

 @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(top: 10, bottom: 10),
      decoration: BoxDecoration(
        color: Colors.white,
        // Set the shadow to add a contact outside the clipping, otherwise it will be invalid
        boxShadow: [
          BoxShadow(
              color: Color(0xff333333).withOpacity(0.05),
              offset: Offset(0, 1.0),
              blurRadius: 5),
        ],
      ),
      child: new ClipRRect(
        // Set local fillet
        borderRadius: BorderRadius.only(
          bottomLeft: Radius.circular(5),
          bottomRight: Radius.circular(5),
        ),
        child: Container(
          height: ScreenUtil().setHeight(147),
          child: Container(
            margin: EdgeInsets.only(left: 40, right: 40),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: navigatorList.map((item) {
                return _navigatorItem(context, item);
              }).toList(),
            ),
          ),
        ),
      ),
    );
  }

14. Remove the bottom shadow from the app bar of scaffold

 

return Scaffold(
  appBar: AppBar(
    backgroundColor: Colors.white,
    centerTitle: true,
    title: Text(
      "find",
      style: TextStyle(
          color: Color(0xff333333), fontSize: ScreenUtil().setSp(34)),
    ),
    bottomOpacity: 0,
    elevation: 0, // Remove bottom shadow
  ),
);

other

 

@override
  Widget build(BuildContext context) {
    return Scaffold(
      //Head elements such as: left return button middle title right menu
      appBar: AppBar(
        title: Text('Scaffold Example of scaffold components'),
      ),
      //The content part of the view is usually the main display area of the application page
      body: Center(
        child: Text('Scaffold'),
      ),
      //Bottom navigation bar
      bottomNavigationBar: BottomAppBar(
        child: Container(height: 50.0,),
      ),
      //Add FAB button
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        tooltip: 'increase',
        child: Icon(Icons.add),
      ),
      //FAB button center display
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );

15.Image image setting width adaptation

 

Container(
    margin: EdgeInsets.only(left: 15, right: 15),
    height: ScreenUtil().setHeight(243),
    decoration: BoxDecoration(
        image: DecorationImage(
      image: NetworkImage(
          'http://fdfs.xmcdn.com/group63/M0A/99/95/wKgMaFz_RD-BDyFjAAIO0iRtj0U176.jpg'),
      fit: BoxFit.fitWidth,
      alignment: Alignment.topCenter,
    )),
  ),

16.FlutterListView nested GridView rolling conflict

Both ListView and GirdView are scrolling widgets. If two widgets are nested, there will be scrolling conflicts. The solution is as follows

 

body: new ListView(
          shrinkWrap: true,
          padding: EdgeInsets.all(0),
          children: <Widget>[
            new GridView.count(
             padding: EdgeInsets.all(0),
            physics: new NeverScrollableScrollPhysics(),//increase
            shrinkWrap: true,//increase
            crossAxisCount: 3,
            children:<Widget>[]
          ],
        ),

① Processing listview nesting error

 

shrinkWrap: true,

② Handle sliding parent in GridView Listview cannot slide

 

physics: new NeverScrollableScrollPhysics();

17. Tailor TabBar and modify indiator width

1. Key code

 

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

class FriendsList extends StatefulWidget {
  @override
  _FriendsListState createState() => _FriendsListState();
}
class _FriendsListState extends State<FriendsList>
    with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(initialIndex: 0, length: 2, vsync: this);
  }

  @override
  void dispose() {
    super.dispose();
    _tabController.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Container(
              height: ScreenUtil().setHeight(73),
              alignment: Alignment.topLeft,
              child: TabBar(
                tabs: [
                  Tab(text: 'Friends'),
                  Tab(text: 'Beckoning'),
                ],
                controller: _tabController,
                indicatorWeight: 2,
                indicatorPadding: EdgeInsets.only(left: 10, right: 10),
                labelPadding: EdgeInsets.symmetric(horizontal: 10),
                isScrollable: true,
                indicatorColor: Color(0xffFF7E98),
                labelColor: Color(0xffFF7E98),
                labelStyle: TextStyle(
                  fontSize: ScreenUtil().setSp(36),
                  color: Color(0xffFF7E98),
                  fontWeight: FontWeight.w500,
                ),
                unselectedLabelColor: Color(0xffAAAAAA),
                unselectedLabelStyle: TextStyle(
                    fontSize: ScreenUtil().setSp(32), color: Color(0xffAAAAAA)),
                indicatorSize: TabBarIndicatorSize.label,
              )),
          backgroundColor: Colors.white,
          elevation: 0,
        ),
        body: TabBarView(
          children: [
            Container(
              child: Center(
                child: Text("Friends page"),
              ),
            ),
            Container(
              child: Center(
                child: Text("Heartbeat page"),
              ),
            ),
          ],
          controller: _tabController,
        ),
      ),
    );
  }
}

2. Renderings

Renderings.gif

18 the fluro plug-in implements the appBar without the return key

Application.router.navigateTo(context, "/index",replace: true);

19. Word overflow processing

①Expanded + TextOverflow.ellipsis Set ellipsis

 

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("LayoutPage")),
      body: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(
              Icons.star,
              size: 16.0,
              color: Colors.grey,
            ),
            Padding(padding: new EdgeInsets.only(left: 5.0)),
            Expanded(
              child: Text(
                "100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000",
                style: new TextStyle(color: Colors.grey, fontSize: 14.0),
                // Set ellipsis
                overflow: TextOverflow.ellipsis,
                // Set the maximum number of rows
                maxLines: 1,
              ),
            )
          ],
        ),
      ),
    );
  }

② Expanded + TextOverflow.ellipsis No effect

adopt

  • Limit Container width
  • Row layout nested Expanded to add constraints

TextOverflow.ellipsis No effect

20. Key do of data analysis error reporting

do is the key, cannot be set as the property of Model, and should be replaced with another name

 

class UserChatList {
  int doType;
  UserChatList({this.doType});
  UserChatList.fromJson(Map<String, dynamic> json) {
    doType = json['do'];
  }

21. Build chat message UI

design sketch

Chat message U

thinking

  • ① Positison settings

 

right: ScreenUtil().setWidth(20),
bottom: -ScreenUtil().setHeight(50),
  • ② Stack set overflow display

 

overflow: Overflow.visible

critical code

 

///Chat Widget
  Widget ChatWidget(String chatType, String msg) {
    // 1 sender
    if (chatType == 'send') {
      return Container(
        decoration: BoxDecoration(
          color: Colors.white,
          // Set shadow
          boxShadow: [
            BoxShadow(
              color: Color(0xffFF7E98),
              offset: Offset(0, 1),
              blurRadius: 8,
            )
          ],
          borderRadius: BorderRadius.only(
              topLeft: Radius.circular(15),
              topRight: Radius.circular(15),
              bottomRight: Radius.circular(15)),
        ),
        height: ScreenUtil().setHeight(80),
        margin: EdgeInsets.only(
          top: ScreenUtil().setHeight(40),
        ),
        padding: EdgeInsets.only(
            left: ScreenUtil().setWidth(40),
            right: ScreenUtil().setWidth(40),
            top: ScreenUtil().setHeight(10),
            bottom: ScreenUtil().setHeight(10)),
        child: Text(
          msg != null && msg.length > 0 ? msg : '',
          style: TextStyle(
              fontSize: ScreenUtil().setSp(30), color: Color(0xff333333)),
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
        ),
      );
    } else if (chatType == 'minisend') {
      return Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Stack(
            overflow: Overflow.visible,
            children: <Widget>[
              // news
              Container(
                decoration: BoxDecoration(
                  color: Colors.white,
                  // Set shadow
                  boxShadow: [
                    BoxShadow(
                      color: Color(0xffFF7E98),
                      offset: Offset(1, 1),
                      blurRadius: 8,
                    )
                  ],
                  borderRadius: BorderRadius.only(
                      topLeft: Radius.circular(15),
                      topRight: Radius.circular(15),
                      bottomRight: Radius.circular(15)),
                ),
                height: ScreenUtil().setHeight(80),
                margin: EdgeInsets.only(
                  top: ScreenUtil().setHeight(40),
                ),
                padding: EdgeInsets.only(
                    left: ScreenUtil().setWidth(40),
                    right: ScreenUtil().setWidth(40),
                    top: ScreenUtil().setHeight(10),
                    bottom: ScreenUtil().setHeight(10)),
                child: Text(
                  '😊I really want to know you😊',
                  style: TextStyle(
                      fontSize: ScreenUtil().setSp(30),
                      color: Color(0xff333333)),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ),
              Positioned(
                right: ScreenUtil().setWidth(20),
                bottom: -ScreenUtil().setHeight(50),
                child: // Applet path
                    Container(
                  margin: EdgeInsets.only(top: ScreenUtil().setHeight(16)),
                  child: Row(
                    children: <Widget>[
                      Text(
                        'Go to the applet to check',
                        style: TextStyle(
                            fontSize: ScreenUtil().setSp(22),
                            color: Color(0xffFF7E98)),
                      ),
                      Icon(
                        MyIcons.sex_boy,
                        size: ScreenUtil().setSp(16),
                        color: Color(0xffFF7E98),
                      )
                    ],
                  ),
                ),
              ),
            ],
          ),
        ],
      );
    } else if (chatType == 'mine') {
      return Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Container(
            decoration: BoxDecoration(
              color: Colors.white,
              // Set shadow
              boxShadow: [
                BoxShadow(
                  color: Color(0xffFF7E98),
                  offset: Offset(0, 1),
                  blurRadius: 8,
                )
              ],
              // Set gradient
              gradient: LinearGradient(
                colors: [Color(0xFFFF7E98), Color(0xFFFD7BAB)],
                begin: Alignment(-1, -1),
                end: Alignment(1.0, 0.56),
              ),
              // Set fillet
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(15),
                  topRight: Radius.circular(15),
                  bottomLeft: Radius.circular(15)),
            ),
            height: ScreenUtil().setHeight(80),
            margin: EdgeInsets.only(
              top: ScreenUtil().setHeight(40),
            ),
            padding: EdgeInsets.only(
                left: ScreenUtil().setWidth(40),
                right: ScreenUtil().setWidth(40),
                top: ScreenUtil().setHeight(10),
                bottom: ScreenUtil().setHeight(10)),
            child: Text(
              msg != null && msg.length > 0 ? msg : '',
              style: TextStyle(
                  fontSize: ScreenUtil().setSp(30), color: Colors.white),
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
            ),
          )
        ],
      );
    } else {
      return Container(
        margin: EdgeInsets.only(bottom:ScreenUtil().setHeight(40) ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Stack(
              overflow: Overflow.visible,
              children: <Widget>[
                Container(
                  decoration: BoxDecoration(
                    color: Colors.white,
                    // Set shadow
                    boxShadow: [
                      BoxShadow(
                        color: Color(0xffFF7E98),
                        offset: Offset(0, 1),
                        blurRadius: 8,
                      )
                    ],
                    // Set gradient
                    gradient: LinearGradient(
                      colors: [Color(0xFFFF7E98), Color(0xFFFD7BAB)],
                      begin: Alignment(-1, -1),
                      end: Alignment(1.0, 0.56),
                    ),
                    // Set fillet
                    borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(15),
                        topRight: Radius.circular(15),
                        bottomLeft: Radius.circular(15)),
                  ),
                  height: ScreenUtil().setHeight(80),
                  margin: EdgeInsets.only(
                    top: ScreenUtil().setHeight(40),
                  ),
                  padding: EdgeInsets.only(
                      left: ScreenUtil().setWidth(40),
                      right: ScreenUtil().setWidth(40),
                      top: ScreenUtil().setHeight(10),
                      bottom: ScreenUtil().setHeight(10)),
                  child: Text(
                    msg != null && msg.length > 0 ? msg : '',
                    style: TextStyle(
                        fontSize: ScreenUtil().setSp(30), color: Colors.white),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
                // Applet path
                Positioned(
                  left: ScreenUtil().setWidth(20),
                  bottom: -ScreenUtil().setHeight(50),
                  child: Container(
                    margin: EdgeInsets.only(top: ScreenUtil().setHeight(16),),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: <Widget>[
                        Text(
                          'Go to the applet to check',
                          style: TextStyle(
                              fontSize: ScreenUtil().setSp(22),
                              color: Color(0xffFF7E98)),
                        ),
                        Icon(
                          MyIcons.sex_boy,
                          size: ScreenUtil().setSp(16),
                          color: Color(0xffFF7E98),
                        )
                      ],
                    ),
                  ),
                ),
              ],
            )
          ],
        ),
      );
    }
  }

22. Flutter copy to clipboard

Copy operation through Clipboard

1. Declare the key and specify the key in Scaffold

 

///Shear Key
final clicpBoardKey  = new GlobalKey<ScaffoldState>();
return Scaffold(
key: clicpBoardKey,
);

2. Implement the copy operation and pop up the SnackBar

 

Clipboard.setData(ClipboardData(text: 'Life is like meeting each other for the first time'));
clicpBoardKey.currentState.showSnackBar(SnackBar(content: Text('Copied to clipboard')));

other

 

Scaffold.of(context).showSnackBar(SnackBar(
                //Content of prompt message
                content: Text("display SnackBar"),
              ));

23.Url escape decode

 

decodeURIComponent('%2Fpage%2Forigin%2Forigin%3Fuid%3D')

24. Get the size of widget control

  • Through Context
  • Via GlobalKey
  • Via layoutchangednotification (override)

 

// width
width: MediaQuery.of(context).size.width,
// height
height: MediaQuery.of(context).size.height * 0.05,
// Note: context is the context of the parent component

 

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class NewSizeChangedLayoutNotification extends LayoutChangedNotification{
  Size size;

  NewSizeChangedLayoutNotification(this.size);
}

class NewSizeChangedLayoutNotifier extends SingleChildRenderObjectWidget {
  const NewSizeChangedLayoutNotifier({
    Key key,
    Widget child,
  }) : super(key: key, child: child);

  @override
  _NewRenderSizeChangedWithCallback createRenderObject(BuildContext context) {
    return _NewRenderSizeChangedWithCallback(
        onLayoutChangedCallback: (Size size) {
          NewSizeChangedLayoutNotification(size).dispatch(context);
        }
    );
  }
}

typedef VoidCallbackWithParam = Function(Size size);

class _NewRenderSizeChangedWithCallback extends RenderProxyBox {
  _NewRenderSizeChangedWithCallback({
    RenderBox child,
    @required this.onLayoutChangedCallback,
  }) : assert(onLayoutChangedCallback != null),
        super(child);

  final VoidCallbackWithParam onLayoutChangedCallback;

  Size _oldSize;

  @override
  void performLayout() {
    super.performLayout();
    //Notify after the first layout
    if (size != _oldSize)
      onLayoutChangedCallback(size);
    _oldSize = size;
  }
}

25.decoration

1) Border

 

// Set 4 borders at the same time: 1px thick black solid line border
BoxDecoration(
  border: Border.all(color: Colors.black, width: 1, style: BorderStyle.solid)
)

// Set single border: top border is 1px thick black solid line border, right border is 1px thick red solid line border
BoxDecoration(
  border: Border(
    top: BorderSide(color: Colors.black, width: 1, style: BorderStyle.solid),
    right: BorderSide(color: Colors.red, width: 1, style: BorderStyle.solid),
  ),
)

2) Fillet

 

// Set the fillet of 4 corners to 5 at the same time
BoxDecoration(
  borderRadius: BorderRadius.circular(5),
)

// Set single fillet: the fillet in the upper left corner is 5, and the fillet in the upper right corner is 10
BoxDecoration(
  borderRadius: BorderRadius.only(
    topLeft: Radius.circular(5),
    topRight: Radius.circular(10),
  ),
)

3) Shadow

 

BoxDecoration(
  boxShadow: [
    BoxShadow(
      offset: Offset(0, 0),
      blurRadius: 6,
      spreadRadius: 10,
      color: Color.fromARGB(20, 0, 0, 0),
    ),
  ],
)

4) Gradient

 

// Linear gradient from left to right, red to blue
BoxDecoration(
  gradient: LinearGradient(
    begin: Alignment.centerLeft,
    end: Alignment.centerRight,
    colors: [Colors.red, Colors.blue],
  ),
)

// From center to all around, red to blue radial gradient
BoxDecoration(
  gradient: RadialGradient(
    center: Alignment.center,
    colors: [Colors.red, Colors.blue],
  ),
)
// Set angle
final gradient = Utils.parseAngleToAlignment(90);
BoxDecoration(
    gradient: LinearGradient(
        colors: [
            Color(0xFFFFA3AD),
            Color(0xFFFC5E72)
        ],
        begin: Alignment(gradient['beginX'], gradient['beginY']),
        end: Alignment(gradient['endX'], gradient['endY'])
    ),
    borderRadius: BorderRadius.circular(2)
)

26. Introduction to the use of materialapp

 

Field type

home Widget
 routes map < string, widgetbuilder >
Theme theme data
 debugShowMaterialGrid bool

navigatorKey globalkey < navigatorstate >
Ongeneraterote RouteFactory
 onUnknownRoute RouteFactory
 navigatorObservers list < navigatorobserver >
initialRoute String
 Builder transition builder
 title String
 On generatetitle GenerateAppTitle
 Color color
 Locale (place)
localizationsDelegates (localizationsDelegates) Iterable < localizationsdelegate < dynamic > >
LocaleResolutionCallback localeresolutioncallback
 supportedLocales (supportable < locale >
Show performance overlay bool
 checkerboardRasterCacheImages bool
 Checkerboard off screen layers bool
 showSemanticsDebugger bool
 debugShowCheckedModeBanner bool

27. Use FutureBuilder to request future again every time setState is called

Solution: extract future as a variable

 

Future<int> future;

  @override
  void initState() {
    super.initState();
    future=getInt();
  }

  FutureBuilder<int>(
    future: future,
    builder: (context, snapshot) {
      return ...;
    }
  ),

  Future<int> getInt(){
    return Future.value(1);
  }

28. When the content of the input box is empty, long press does not display the paste toolbar

Remove the autoFocus attribute from the input box as true

29. Return button callback in the upper left corner of the flutter

1.1 async await implementation

 

///Await when you jump to a lower level page Navigator.pushNamed
onTap: () async {
    await Navigator.pushNamed(context, '/account');
    //Perform refresh data operation
    refrshData();
  },

2. Nesting encapsulation will lead to the failure of await

 

class NavigatorUtil{
  ///General jump
  static push(BuildContext context,Widget widget ) {
    Navigator.push(context, PageRouteBuilder(transitionDuration: Duration(milliseconds: 300),
        pageBuilder: (context, animation, secondaryAnimation){
          return new FadeTransition( //Use fade in transitions,
            opacity: animation,
            child:widget,
          );
        })
    );
  }
}

//Use causes await to fail
onTap: () async {
    // other
     await NavigatorUtil.push(context, widget);
     //Perform refresh operation
  },

Solution
Package layer nesting async await

 

class NavigatorUtil{
  ///General jump
  static push(BuildContext context,Widget widget ) async {
    await Navigator.push(context, PageRouteBuilder(transitionDuration: Duration(milliseconds: 300),
        pageBuilder: (context, animation, secondaryAnimation){
          return new FadeTransition( //Use fade in transitions,
            opacity: animation,
            child:widget,
          );
        })
    );
  }
}

30.GestureDetector gesture conflict

Resolve gesture conflict - IgnorePointer

 

IgnorePointer(
  child: GestureDetector(
    child: Container(
      height: ScreenUtil().setHeight(300),
      width: Screen.width,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(ScreenUtil().setWidth(20)),
          topRight: Radius.circular(ScreenUtil().setWidth(20)),
        ),
        gradient: LinearGradient(
          colors: [
            Color(0xFFFFFFFF),
            Colors.white.withOpacity(.2),
            Colors.white.withOpacity(0),
            Colors.white.withOpacity(0),
            Colors.white.withOpacity(0)
          ],
          begin: Alignment(
              topGradient['beginX'], topGradient['beginY']),
          end: Alignment(topGradient['endX'], topGradient['endY']),
        ),
      ),
    ),
    onTap: () {
      backToTop();
    },
  ),
),

31.TextField sets border color (black line changes color)

 

///Input box
Container(
    child: Theme(
        data: ThemeData(
                primaryColor: Colors.white, hintColor: Colors.white),
        child: TextField(
            style: TextStyle(
                fontSize: ScreenUtil().setSp(36),
                color: Colors.white,
            ),
            controller: inputController,
            onChanged: handlePhoneInput,
            autofocus: true,
            decoration: new InputDecoration(
                border: const UnderlineInputBorder(
                    borderSide: BorderSide(style: BorderStyle.solid,color: Colors.white,),
                ),
                contentPadding: EdgeInsets.only(
                    left: ScreenUtil().setWidth(100),
                    right: ScreenUtil().setWidth(20),
                    top: ScreenUtil().setWidth(20),
                    bottom: ScreenUtil().setWidth(20),
                ),
                hintText: 'Enter phone number',
                hintStyle: TextStyle(
                    color: Color.fromRGBO(255, 255, 255, .7),
                    fontSize: ScreenUtil().setSp(36),
                ),
            ),
        ),
    ),
),

32.decoration shadow setting borderless

Set the stop node and colors combination through Opacity and LinearGradient

 

// Top shadow
Opacity(
  opacity: 0.23,
  child: Container(
    height: ScreenUtil().setHeight(129),
    decoration: BoxDecoration(
      gradient: LinearGradient(
          stops: [
            0,
            .8
          ],
          colors: [
            Color(0xff565656),
            Color(0xFF030303).withOpacity(0),
          ],
          begin:
              Alignment(gradient['beginX'], gradient['beginY']),
          end: Alignment(gradient['endX'], gradient['endY'])),
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(10.0),
        topRight: Radius.circular(10.0),
      ),
    ),
    child: Container(
      margin: EdgeInsets.only(
        left: ScreenUtil().setWidth(10),
        right: ScreenUtil().setWidth(17),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Container(
            margin: EdgeInsets.only(
                top: ScreenUtil().setHeight(17)),
            child: Row(
              children: <Widget>[
                Icon(
                  MyIcons.heart,
                  size: ScreenUtil().setSp(40),
                  color: Colors.white,
                ),
                Container(
                  margin: EdgeInsets.only(
                    left: ScreenUtil().setWidth(5),
                    top: ScreenUtil().setWidth(5),
                  ),
                  child: Text(
                    this.widget.item != null &&
                            this.widget.item.praises != null
                        ? this.widget.item.praises.toString()
                        : '',
                    style: TextStyle(
                      fontSize: ScreenUtil().setSp(20),
                      color: Colors.white,
                    ),
                    textAlign: TextAlign.center,
                  ),
                )
              ],
            ),
          ),
        ],
      ),
    ),
  ),
)

33.Dart List.asMap () get subscript

 

 this.list.asMap().keys.map((i) {
   // i is the subscript
    return _itemUI(context, i);
  }).toList()

34.indexWhere get array index

 

int currentIndex = this.renderList.indexWhere((item) => item.id == feed.id);

35. Use of build runner plug-in

build runner plug-in build property shortcut

 

flutter packages run build_runner build --delete-conflicting-outputs

36. Click area of container is too small

Container in GestureDetector does not set color. Click area will be determined according to content size

37.xcrun instruments open simulator

xcrun instruments -w "iPhone 8 Plus (13.1)"

39. GestureDetector handles gesture operation behavior

  • HitTestBehavior.opaque Handle events by yourself

  • HitTestBehavior.deferToChild Child handles events

  • HitTestBehavior.translucent You and your child can receive events

40.Widget cannot be centered, aligned

 

 Row(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
          Container(
              width: ScreenUtil().setHeight(114),
              height: ScreenUtil().setHeight(114),
              margin: EdgeInsets.only(
                left: ScreenUtil().setWidth(10),
              ),
              child: Center(child: FailedDot(),),
            )
          : Container()
    ],
  ),

41. The click area of the shuttle container is too small

When using GestureDetector to wrap the Container, it is found that when clicking in the area where the content of the Container is empty, the onTap click event cannot be captured.
Solution: Add Attribute: behavior: HitTestBehavior.opaque , you can:

 

GestureDetector(
          behavior: HitTestBehavior.opaque,
          child: Container( width: ScreenUtil().setHeight(114),
              height: ScreenUtil().setHeight(114),child:Text('Point me')),
          onTap: () {
            this.handlePlayVoice();
          },
        )

42. Monitor page return event (return button click + sideslip to return)

Sideslip does not trigger the onBack callback, so use the onWillPop of WillPopScope to implement

 

 @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        // Setting up the scratchpad
        this.setCraft();
        return true;
      },
      child: Container()
  }

43precautions for using pageview

Problem Description: the first time you specify to load the second page, you need to switch twice to display normal

Cause analysis:
When PageView is not initialized, the default index = 0. When you forcibly modify it, the two indexes will be inconsistent

terms of settlement:

 

 _controller = PageController(initialPage: currentIndex);
///Switch
_controller.animateToPage(
                                  currentIndex,
                                  duration: Duration(
                                    milliseconds:
                                        (pageSwitchAnimatedTime + 100),
                                  ),
                                  curve: Curves.ease,
                                );

44 ClipOval component details

  • Round clipping (the out part is hidden, which is equivalent to Stack's overFlow being clip)

 

Center(
      child: ClipOval(
        child: Image.asset(
          "images/app.png",
          width: 100.0,
          height: 100.0,
          fit: BoxFit.cover,
        ),
      ),
    )

How to judge whether the device is an iPad

 

// 1. Import device information plug-in
# Device information
device_info: ^0.4.0

// 2. Use
Future<bool> isIpad() async{
  DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
  IosDeviceInfo info = await deviceInfo.iosInfo;
  if (info.name.toLowerCase().contains("ipad")) {
    return true;
  }
  return false;
}

46 memory leak caused by setstate -- setState() called after dispose()

Error reason

  • Timer not destroyed (dispose destroy cancel)

resolvent

Interim programme

  • The asynchronous message is not returned, so the mouted property is called before the setState method can be judged.

 

if (mounted) {
  setState(() {
    //refreshData
  });
}

Final solution

 

@override
  void dispose() {
    _countdownTimer?.cancel();
    super.dispose();
  }

47. Setup fillet image for flutter

Realized by cliprrect + borderaradius

 

Container(
      child: ClipRRect(
        borderRadius: BorderRadius.circular(10),
        child: Image.network(
          this.matchedUser.user.avatar,
          fit: BoxFit.cover,
        ),
      ),
      width: AdaptationUtils.px(140),
      height: AdaptationUtils.px(140),
    )

48.clamp syntax

As the name implies, clamping, the result will not exceed this range, similar to the closed interval []
For example:

 

int origen = 10;
int result = origen.clamp(2, 11);
print(result);//MARK: the result is 10
//////////////////////////////////
int origen = 10;
int result = origen.clamp(2, 9);
print(result);//MARK: the result is 9

49. Expanded click area (Container)

design sketch

Expand click area.gif

Code encapsulation

 

///Expand the click area (Container)
///
/// created by hujintao
/// created at 2020-03-19
//
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class EnlargeWrapper extends StatefulWidget {
  Widget child;
  EdgeInsetsGeometry enlarge;

  EnlargeWrapper({
    this.child,
    this.enlarge,
  });

  @override
  _EnlargeWrapperState createState() => _EnlargeWrapperState();
}

class _EnlargeWrapperState extends State<EnlargeWrapper> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: this.widget.child,
      padding: this.widget.enlarge ??
          EdgeInsets.fromLTRB(
            ScreenUtil().setWidth(40),
            ScreenUtil().setWidth(40),
            ScreenUtil().setWidth(40),
            ScreenUtil().setWidth(40),
          ),
//      color: Colors.yellow , / / test
      color: Colors.transparent,
    );
  }
}

use

 

Center(
    child: GestureDetector(
      child: EnlargeWrapper(
        child: Container(
          width: 100,
          height: 100,
          color: Colors.red,
          child: Center(
            child: Text('Point me s Scatter'),
          ),
        ),
        enlarge: EdgeInsets.all(50),
      ),
      onTap: () {
        Toast.show('Click');
      },
    ),
  )

50. Read file by name

 

//Read file by name
import 'dart:io';

readFile(name) async {
  //Create a file object
  var file = File(name);
  try {
    //Judge whether it exists
    bool exists = await file.exists();
    if (exists) {
      //If present
      print(await file.length()); //File size (bytes) --- 137
      print(await file.lastModified()); //Last modified on December 21, 2018 13:49:35.000
      print(file.parent.path); //Get the path of the parent folder -- C:\Users\Administrator\Desktop\dart
      return await file.readAsString(); //Read file and return
    } else {
      await file.create(recursive: true); //Create file if it does not exist
      return "No files found,Created for you!Dart robot:2333";
    }
  } catch (e) {
    //exception handling
    print(e);
  }
}

use

 

var result = await readFile("\Users\XXX\Desktop\dart\test.txt");
  print(result);

Add all SD card file names

 

// Add all SD card file names
  localPath() {
    try {
      var perm =
          SimplePermissions.requestPermission(Permission.ReadExternalStorage);
      var sdPath = getExternalStorageDirectory();
      sdPath.then((file) {
        perm.then((v) {
          file.list().forEach((i) {
            _files.add(i.path);
          });
          setState(() {});
        });
      });
    } catch (err) {
      print(err);
    }
  }

51 flitter wechat sharing and payment callback

Through fluwx wechat SDK plug-in
Download plug-ins

 

# Wechat sdk
fluwx: ^1.2.1+1

1. Wechat share callback

 

import 'package:fluwx/fluwx.dart' as fluwx;
///Wechat sharing and monitoring
StreamSubscription wxShareListener;
 @override
  void initState() {
    super.initState();
    this.track();
    initWxShareListener();
  }
  ///Initialize wechat sharing monitoring
  void initWxShareListener() {
    wxShareListener =
        fluwx.responseFromShare.listen(this.onWxShareResponse);
  }
  ///Wechat share response
  void onWxShareResponse(fluwx.WeChatShareResponse response) {
    print(
        'pay success: ${response.errStr}, ${response.type}, ${response.errCode}, ${response.androidOpenId}');
    if (response.errCode == 0) {
     Toast.show('Share back~~~~');
    } 
  }
  // Destroy monitor
  @override
  void dispose() {
    wxShareListener.cancel();
    super.dispose();
  }

2. Wechat payment callback

 

import 'package:fluwx/fluwx.dart' as fluwx;
///Wechat payment monitoring
StreamSubscription fluwxPaymentListener;
 @override
  void initState() {
    super.initState();
    this.track();
    initWxPayListener();
  }
  ///Initialize wechat payment monitoring
  void initWxPayListener() {
    fluwxPaymentListener =
        fluwx.responseFromPayment.listen(this.onWxPayResponse);
  }
  ///Wechat payment response
  void onWxPayResponse(fluwx.WeChatPaymentResponse response) {
    print(
        'pay success: ${response.errStr}, ${response.type}, ${response.errCode}, ${response.androidOpenId}');

    // After wechat response, windows cannot be closed
    if (this.canClose) {
      this.canClose = false;
      setState(() {});
    }

    if (response.errCode == 0) {
      this.checkOrderStatus();
    } else {
      if (response.errCode == -1) {
        this.onError(PayErrorEnum.WxPayError);
      } else if (response.errCode == -2) {
        this.onError(PayErrorEnum.WxPayCanceled);
      } else {
        this.onError(PayErrorEnum.WxPayUnKnowError);
      }
    }
  }
  // Destroy monitor
  @override
  void dispose() {
    fluwxPaymentListener.cancel();
    super.dispose();
  }

52. Database operation abstract class (interface encapsulation)

 

//Database operation abstract class
abstract class DateBaseOperate {

  void insert(); //Define how to insert

  void delete(); //Define how to delete

  void update(); //Define how to update

  void query(); //Define a query method
}

//Database operation implementation class
class DateBaseOperateImpl extends DateBaseOperate {

  //The method of inserting is realized
  void insert(){
    print('The method of inserting is realized');
  }

  //The method of deletion is realized
  void delete(){
    print('The method of deletion is realized');
  }

  //Implementation of the update method
  void update(){
    print('Implementation of the update method');
  }

  //A query method is implemented
  void query(){
    print('A query method is implemented');
  }

}


main() {

  var db = new DateBaseOperateImpl();
  db.insert();
  db.delete();
  db.update();
  db.query();

}

53. Succession

 

//Zoology
class Animal {

  //Animals can eat
  void eat(){
    print('Animals can eat');
  }

  //Animals can run
  void run(){
    print('Animals can run');
  }
}
//human beings
class Human extends Animal {

  //People will say
  void say(){
    print('People will say');
  }

  //Human beings can learn
  void study(){
    print('Human beings can learn');
  }
}

main() {
  print('Instantiate an animal class');
  var animal = new Animal();
  animal.eat();
  animal.run();

  print('Instantiate a human');
  var human = new Human();
  human.eat();
  human.run();
  human.say();
  human.study();
}

54. Process control statement

 

void test(){

    //if else example
//    String today = 'Monday';
//    if (today == 'Monday') {
//      print('today is Monday ');
//    } else if (today == 'Tuesday') {
//      print('today is Tuesday ');
//    } else {
//      print('today is a good day ');
//    }


    //for loop example
    var message = new StringBuffer("Hello Dart");
    for (var i = 0; i < 5; i++) {
      message.write('!');
    }
    print(message);

    //forEach example
//    var arr = [0, 1, 2, 3, 4, 5, 6];
//    for (var v in arr) {
//      print(v);
//    }

    //while loop example
//    var _temp = 0;
//    while(_temp < 5){
//
//      print("this is a loop:" + (_ temp).toString());
//      _temp ++;
//    }

    //Do while loop example
//    var _temp = 0;
//
//    do{
//      print("this is a loop:" + (_ temp).toString());
//      _temp ++;
//    }
//    while(_temp < 5);

    //break continue example
    var arr = [0, 1, 2, 3, 4, 5, 6];
    for (var v in arr) {
      if(v == 2 ){
        //break;
        continue;
      }
      print(v);
    }


    //switch case example
    String today = 'Monday';
    switch (today) {
      case 'Monday':
        print('Monday');
        break;
      case 'Tuesday':
        print('Tuesday');
        break;
    }

    //Exception handling example
    try {
      // ···
    } on Exception catch (e) {
      print('Exception details:\n $e');
    } catch (e, s) {
      print('Exception details:\n $e');
      print('Stack trace:\n $s');
    } finally {
      print('Do some thing:\n');
    }
  }

54. Getters and Setters methods

 

class Rectangle {
  num left;
  num top;
  num width;
  num height;

  Rectangle(this.left, this.top, this.width, this.height);

  //Get right value
  num get right         => left + width;

  //Setting the right value also changes left
  set right(num value)  => left = value - width;

  //Get the bottom value
  num get bottom        => top + height;

  //Setting the bottom value also changes the top
  set bottom(num value) => top = value - height;
}

55. Text set underline, dotted line and strikethrough

 

TextStyle(
              //Font color
              color: const Color(0xffff0000),
              //Text decorator (strikeout)
              decoration: TextDecoration.lineThrough,
              //Text finisher color (strikethrough color)
              decorationColor: const Color(0xff000000),
              //font size
              fontSize: 18.0,
              //Whether the font style is italicized
              fontStyle: FontStyle.italic,
              //Font weight
              fontWeight: FontWeight.bold,
              //Text spacing
              letterSpacing: 2.0,
            )
// Underline
color: const Color(0xffff9900),
decoration: TextDecoration.underline,
// Dotted line
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.dashed,
// Italics
fontStyle: FontStyle.italic,
fontWeight: FontWeight.bold,

56.PopupMenuButton component example

 

//Master menu item
enum ConferenceItem { AddMember, LockConference, ModifyLayout, TurnoffAll }
FlatButton(
    onPressed: () {},
    child: PopupMenuButton<ConferenceItem>(
      onSelected: (ConferenceItem result) {},
      itemBuilder: (BuildContext context) =>//Menu item builder
      <PopupMenuEntry<ConferenceItem>>[
        const PopupMenuItem<ConferenceItem>(//menu item
          value: ConferenceItem.AddMember,
          child: Text('Add member'),
        ),
        const PopupMenuItem<ConferenceItem>(
          value: ConferenceItem.LockConference,
          child: Text('Lock meeting'),
        ),
        const PopupMenuItem<ConferenceItem>(
          value: ConferenceItem.ModifyLayout,
          child: Text('Modify layout'),
        ),
        const PopupMenuItem<ConferenceItem>(
          value: ConferenceItem.TurnoffAll,
          child: Text('Hang up all'),
        ),
      ],
    ),
  )

57.TextField component details

 

TextField(
      //Bind controller
      controller: controller,
      //Maximum length. Setting this item will make TextField have a statistical string of input quantity in the lower right corner
      maxLength: 30,
      //Maximum rows
      maxLines: 1,
      //AutoCorrect or not
      autocorrect: true,
      //Auto focus or not
      autofocus: true,
      //Is it a password
      obscureText: false,
      //text alignment
      textAlign: TextAlign.center,
      //Style of input text
      style: TextStyle(fontSize: 26.0, color: Colors.green),
      //Callback when text content changes
      onChanged: (text) {
        print('Callback when text content changes $text');
      },
      //Callback on content submission
      onSubmitted: (text) {
        print('Callback on content submission $text');
      },
      enabled: true, //Disable or not
      decoration: InputDecoration(//Add decoration effect
          fillColor: Colors.grey.shade200,//Add a gray fill color
          filled: true,
          helperText: 'user name',
          prefixIcon: Icon(Icons.person),//Left Icon
          suffixText: 'user name'),//Right text prompt
    )

58. Example of sliding deletion

design sketch

Slide delete.gif

code

 

import 'package:flutter/material.dart';
void main() {
  runApp(new MaterialApp(
    title: 'Slide delete example',
    home: new MyApp(),
  ));
}

class MyApp extends StatelessWidget {

  //Build 30 list data
  List<String> items = new List<String>.generate(30, (i) => "List item ${i + 1}");

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Slide delete example'),
      ),
      //Build list
      body: new ListView.builder(
        itemCount: items.length,//Specify list length
        itemBuilder: (context, index) {//Build list

          //Extract deleted items
          final item = items[index];

          //Returns a list item that can be deleted
          return new Dismissible(
              key: new Key(item),
              //Deleted callback
              onDismissed: (direction) {
                //Remove specified index entry
                items.removeAt(index);
                //The bottom pop-up message indicates that the current item has been deleted
                Scaffold.of(context).showSnackBar(
                    new SnackBar(content: new Text("$item Deleted")));
              },
              child: new ListTile(title: new Text('$item'),)
          );
        },
      ),
    );
  }
}

59 adding and using custom fonts

  • 1. place font resources

     

    Place font resources

  • 2. In pubspec.yaml Configuration path

 

fonts:
    - family: myfont
      fonts:
        - asset: fonts/myfont.ttf
  • 3. Use

 

Center(
    child: new Text(
      'Hello flutter',
      style: new TextStyle(fontFamily: 'myfont',fontSize: 36.0),
    ),
  )
  • design sketch

design sketch

60. Page Jump return data

 

//Stack operation and wait for page return operation
final result = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondPage()),
);
//Read and display return value
Scaffold.of(context).showSnackBar(SnackBar(content: Text("$result")));

//Go back to the previous page with the parameters on the stack
Navigator.pop(context, 'hi flutter');

61.fluro enterprise level routing

  • Import dependency

 

fluro: ^1.5.0
  • Component encapsulation

 

// 1. Define Application class
import 'package:fluro/fluro.dart';

//Define Application class
class Application{
  //Creating a Router object with static variables
  static Router router;
}

// 2. Define route set and handler
/// 2.1 handler
import 'package:fluro/fluro.dart';
import '../pages/second_page.dart';
import 'package:flutter/material.dart';

//Create a Handler to receive route parameters and return a second page object
Handler secondPageHandler = Handler(
  handlerFunc: (BuildContext context,Map<String,List<String>> params){
    //Reading the goodId parameter first is the first data
    String goodId = params['goodId'].first;
    return SecondPage(goodId);
  }
);

///2.2 route set 
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'router_handler.dart';


//Routing set
class Routes{
  //Root path
  static String root = '/';
  //Second page path
  static String secondPage = '/secondPage';

  //Configure routing objects
  static void configureRoutes(Router router){

    //No callback method found for route
    router.notFoundHandler = Handler(
      handlerFunc: (BuildContext context,Map<String,List<String>> params){
        print('error::: router Can't find');
      }
    );

    //Define the Handler for the second page route
    router.define(secondPage, handler: secondPageHandler);

  }

}

  • First page

 

import 'package:flutter/material.dart';
import '../routers/application.dart';
import 'package:fluro/fluro.dart';


//First page
class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Fluro Route navigation example"),
      ),
      body: Center(
        child: RaisedButton(
          //Click to process
          onPressed: () {
            _navigateToSecondPage(context);
          },
          child: Text('Open the second page'),
        ),
      ),
    );
  }

  //Route to second page
  _navigateToSecondPage(BuildContext context) async {
    //Parameters of routing band
    String goodId  = '001';
    //Navigate to the second page through the routing router in the Application class to specify the page switching animation type
    Application.router.navigateTo(context, "/secondPage?goodId=$goodId",transition: TransitionType.fadeIn).then((result) {//Return value
      //When the second page returns, the parameter with it is the result value
      if (result != null) {
        print(result);
      }
    });
  }
}
  • Second page

 

import 'package:flutter/material.dart';

//Second page
class SecondPage extends StatelessWidget {
  //Pass parameter values
  final String goodId;

  SecondPage(this.goodId);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second page"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            //Show pass through parameter values
            Text(
              '$goodId',
              style: TextStyle(
                fontSize: 28.0,
                color: Colors.red,
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  //Return to the first page with the parameters on the stack
                  Navigator.pop(context, 'Second page return parameters($goodId)');
                },
                child: Text('Click back'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
  • Configure routing

 

import 'package:flutter/material.dart';
import './routers/routes.dart';
import 'package:fluro/fluro.dart';
import './routers/application.dart';
import './pages/first_page.dart';


void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    //Create routing object
    final router = Router();
    //Configure routing objects for route set Routes
    Routes.configureRoutes(router);
    //Specify the routing object for Application
    Application.router = router;

    return Container(
      child: MaterialApp(
        title: "Fluro Route navigation example",
        debugShowCheckedModeBanner: false,
        //Generate the route callback function, which will be used to generate the interface when the named route is navigated
        onGenerateRoute: Application.router.generator,
        //Home page designated as first page
        home: FirstPage(),
      ),
    );
  }
}

62. Database operation ('Sqlite ')

Model

 

//Customer data model class
class Client {
  //id
  int id;
  //full name
  String name;
  //Age
  int age;
  //Gender
  bool sex;

  Client({this.id, this.name, this.age, this.sex,});

  //Convert JSON data to data model
  factory Client.fromMap(Map<String, dynamic> json) => Client(
        id: json["id"],
        name: json["name"],
        age: json["age"],
        sex: json["sex"] == 1,
      );

  //Convert data model to JSON
  Map<String, dynamic> toMap() => {
        "id": id,
        "name": name,
        "age": age,
        "sex": sex,
      };
}

Component encapsulation

 

import 'dart:async';
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'client.dart';
import 'package:sqflite/sqflite.dart';

//Database operation encapsulation class
class DBProvider {
  DBProvider._();

  static final DBProvider db = DBProvider._();

  Database _database;

  //Get Database object
  Future<Database> get database async {
    //Using singleton mode to create Database objects
    if (_database != null) {
      return _database;
    }
    _database = await initDB();
    return _database;
  }

  //Initialize database
  initDB() async {
    //Get document catalog object
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    //Get the default database location (on Android, it is usually data / data / < package_ Name > / databases, on iOS, it is the Documents directory)
    String path = join(documentsDirectory.path, "client.db");
    //Open database incoming path version No. open completion callback function
    return await openDatabase(path, version: 1, onOpen: (db) {},
        onCreate: (Database db, int version) async {
          //Create Client table after database creation
          await db.execute("CREATE TABLE Client ("
              "id INTEGER PRIMARY KEY,"
              "name TEXT,"
              "age INTEGER,"
              "sex BIT"
              ")");
    });
  }

  //New Client
  insertClient(Client newClient) async {
    final db = await database;
    //Get the largest id in the table and add 1 as the new id
    var table = await db.rawQuery("SELECT MAX(id)+1 as id FROM Client");
    int id = table.first["id"];
    //Insert a piece of data into the table
    var raw = await db.rawInsert(
        "INSERT Into Client (id,name,age,sex)"
        " VALUES (?,?,?,?)",
        [id, newClient.name, newClient.age, newClient.sex]);
    return raw;
  }

  //Modify gender
  updateSex(Client client) async {
    final db = await database;
    Client newClient = Client(
        id: client.id,
        name: client.name,
        age: client.age,
        sex: !client.sex);
    //Update the gender of the current Client
    var res = await db.update("Client", newClient.toMap(),
        where: "id = ?", whereArgs: [client.id]);
    return res;
  }

  //Update Client
  updateClient(Client newClient) async {
    final db = await database;
    var res = await db.update("Client", newClient.toMap(),
        where: "id = ?", whereArgs: [newClient.id]);
    return res;
  }

  //Get Client according to id
  getClient(int id) async {
    final db = await database;
    //Query table records according to id
    var res = await db.query("Client", where: "id = ?", whereArgs: [id]);
    //Convert the data returned by the query to a Client object and return
    return res.isNotEmpty ? Client.fromMap(res.first) : null;
  }

  //Get all clients
  Future<List<Client>> getAllClients() async {
    final db = await database;
    var res = await db.query("Client");
    List<Client> list = res.isNotEmpty ? res.map((c) => Client.fromMap(c)).toList() : [];
    return list;
  }

  //Delete Client according to id
  deleteClient(int id) async {
    final db = await database;
    return db.delete("Client", where: "id = ?", whereArgs: [id]);
  }

  //Delete all clients
  deleteAll() async {
    final db = await database;
    db.rawDelete("Delete * from Client");
  }
}

Component use

 

// Get all data
DBProvider.db.getAllClients(),
//Delete Client object according to id
DBProvider.db.deleteClient(item.id);
//Update gender
DBProvider.db.updateSex(item);
//Randomly take one piece of test data as Client object
Client rnd = clients[math.Random().nextInt(clients.length)];
//Add a new Client object
await DBProvider.db.insertClient(rnd);



By Steven Hu_ Sir
Link: https://www.jianshu.com/p/286c8beacb11
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Topics: Database JSON Android network