Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

Extract the Widget

When we open up the code for our previous example, we see that there are many widgets in Main.dart. We can extract the code, which is decoupling.

  • Extract listView: right-click on itNew->Dart FileCreate a new onelistview.dartFile, entersYou can quickly think of stateless and statelesswidgetThe block of code

Select Stless and enter

class  extends StatelessWidget {
  const ({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    returnContainer(); }}Copy the code

Extends Extends StatelessWidget Removes const ({Key? key}) : super(key: key); We don’t need it right now. Now the code in this file becomes

import 'package:flutter/material.dart';
import 'model/car.dart';

class ListViewDemo extends StatelessWidget {
  Widget _itemForRow(BuildContext context, int index) {
    return Container(
        color: Colors.white,
        margin: EdgeInsets.all(10), child: Column( children: [ Image.network(datas[index].imageUrl!), Text(datas[index].name!) ] )); }@override
  Widget build(BuildContext context) {
    returnListView.builder( itemBuilder: _itemForRow, itemCount: datas.length, ); }}Copy the code

Then cut all the ListView from main.dart to here, and change the body of the main project’s Home to the current ListViewDemo().

import 'package:flutter/material.dart';
import 'package:hello_flutter/base_widget.dart';
import 'package:hello_flutter/listview.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    returnMaterialApp( home: Home(), ); }}class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey,
      appBar: AppBar(
        title: Text(
            'flutterDemo'), ), body: ListViewDemo(), ); }}Copy the code
  • The extraction model,main.dartIn the fileList<Car> datasThe data source is placed to the currentcar.dartFile. This makes the code in the main file more concise.
  • Similarly, let’s take the originalMyWidgetI’m also pulling it outmain.dartIf you want to switch, you just need to change the corresponding component constructor.

Commonly used widgets

  1. Text component: String splicing use$
import 'package:flutter/material.dart';

class TextDemo extends StatelessWidget {

  final TextStyle _textStyle = TextStyle(
    fontSize: 16.0,
    backgroundColor: Colors.red,
  );
  final String _pre = 'the prefix';
  final String _end = 'the suffix';
  @override
  Widget build(BuildContext context) {
    return Text('$_pre1. Extract model: place the List<Car> datAS data source from the main.dart file into the current car.dart file. This makes the code in the main file more concise. 3. Similarly, extract the MyWidget you originally created so that if you want to switch to main.dart, you only need to change the corresponding component constructor.$_end',
    textAlign: TextAlign.center,
    style: _textStyle);  // The constructor of the TextStyle can also be extracted}}Copy the code

After running:

You can also set the maximum number of lines and use an ellipsis to indicate extra lines

Text(
    maxLines: 3.// Maximum 3 lines
    overflow: TextOverflow.ellipsis, // The suffix is omitted for more than 3 lines
);
Copy the code

  1. The rich textRichTextComponent: ThisRichTextThe component has oneTextSpanIt can be nested, with different styles for different texts
  @override
  Widget build(BuildContext context) {
    return RichText(text: TextSpan(
      children: <TextSpan>[
        TextSpan(
            text: '$_preDart List<Car> ',
            style: TextStyle(
                fontSize: 30,
                color: Colors.yellow
            )
        ),
        TextSpan(
            text: '$_preDart List<Car> ',
            style: TextStyle(
                fontSize: 20,
                color: Colors.red
            )
        ),
        TextSpan(
            text: '$_preDart List<Car> ',
            style: TextStyle(
                fontSize: 40,
                color: Colors.purpleAccent
            )
        ),
      ],
    ));
  }
Copy the code

3.Container Component: This component is often used for layout purposes. Because it has a Childen and ADAPTS to the layout. With the Row component you can have an infinite set of dolls and of course the Column from the previous article

class TextDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Row(
        children: [
          Container(
            color: Colors.red,
            child: Icon(Icons.add),
            //padding: EdgeInsets. All (30), // inner margin
           // margin: EdgeInsets. All (20), // margin: EdgeInsets)],),); }}Copy the code

The padding here is the inside margin, if it’s not set

Open the padding comment and you can clearly see the inside margin of the image

Continue to open the margin comment so that the comparison shows that margin is the outer margin of the image.

Row of Flutter layouts

Flexible box layout: horizontal Row, vertical Column, and collapsed Stack. The center of an Alignment in a flutter is the center of the parent control

import 'package:flutter/material.dart';
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('Layout Demo'),
      alignment: Alignment(0.0), / / [1, 1]); }}Copy the code

We studied the alignment method used with row. For easy observation, each Icon was packaged with a layer of Container to set the color

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment(0.0),
      child: Row(
        children: [
          Container(child: Icon(Icons.add, size: 60,), color: Colors.yellow,),
          Container(child: Icon(Icons.sort, size: 60,), color: Colors.red,),
          Container(child: Icon(Icons.ac_unit, size: 60,), color: Colors.purpleAccent,),
          Container(child: Icon(Icons.access_alarm, size: 60,), color: Colors.greenAccent,), ], ), ); }}Copy the code

Modify the x coordinate of Alignment(-1,-1) :

Modify the y-coordinate of Alignment(-1,-1) :

Change the alignment: the alignment (-1,0) changes its abscissa to either -1 or 1. But changing the y coordinate: y = -1 goes to the top, y = 1 goes to the bottom, so when using the Row layout, changing the x coordinate has no effect.

The Column of the Flutter layout

Modify the layout mode at this point

import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment(1.1),
      child: Column(
        children: [
          Container(child: Icon(Icons.add, size: 60,), color: Colors.yellow,),
          Container(child: Icon(Icons.sort, size: 60,), color: Colors.red,),
          Container(child: Icon(Icons.ac_unit, size: 60,), color: Colors.purpleAccent,),
          Container(child: Icon(Icons.access_alarm, size: 60,), color: Colors.greenAccent,), ], ), ); }}Copy the code

Similarly, if the layout is aligned with Column, changing the alignment (-1,0) to either -1 or 1 does not affect this. But if you change the x coordinate, the image goes to the far left when x = -1, and the image goes to the far right when x = 1, so it doesn’t matter if you change the y coordinate when Column is used.

The Stack of the Flutter layout

import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment(0.0),
      child: Stack(
        children: [
          Container(child: Icon(Icons.add, size: 120,), color: Colors.yellow,),
          Container(child: Icon(Icons.sort, size: 90,), color: Colors.red,),
          Container(child: Icon(Icons.ac_unit, size: 60,), color: Colors.purpleAccent,),
          Container(child: Icon(Icons.access_alarm, size: 30,), color: Colors.greenAccent,), ], ), ); }}Copy the code

Principal axis and cross axis

We need to know the spindle when using the above three orientation layouts! Spindle attributes: Center, Start, End Spindle direction:

  • Horizontal Row -> right
  • Vertical Column -> down
  • Layer Stack -> outside
  1. Spindle add attribute (start/ Center /end) : The default is to start from the left, if we want to start from the right we can add the spindle attributemainAxisAlignment: MainAxisAlignment.end. Similarly, start is on the left and Center is in the middle
import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment(0.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.end, // End position
        children: [
          Container(child: Icon(Icons.add, size: 120,), color: Colors.yellow,),
          Container(child: Icon(Icons.sort, size: 90,), color: Colors.red,),
          Container(child: Icon(Icons.ac_unit, size: 60,), color: Colors.purpleAccent,),
          Container(child: Icon(Icons.access_alarm, size: 30,), color: Colors.greenAccent,), ], ), ); }}Copy the code

Operation effect after setting the spindle direction:

  1. Spindle add propertiesMainAxisAlignment.spaceBetween: The remaining space is evenly divided between the widgets.

  1. Spindle add propertiesMainAxisAlignment.spaceAround: The remaining space is evenly distributed around the widgets.

  1. Spindle add propertiesMainAxisAlignment.spaceEvenly: Divide the rest of the space evenly with the widgets.

  1. The cross axis is the Y-axisCrossAxisAlignmentThere are also attributes (start/ Center /end) and one in addition to the basic threeCrossAxisAlignment.baselineWhen using the Text component, the obvious thing to see is the bottom alignment of the TexttextBaseline Use them together, otherwise an error will be reported
import 'package:flutter/material.dart';
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment(0.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly, // End position
        crossAxisAlignment: CrossAxisAlignment.baseline,
        textBaseline: TextBaseline.alphabetic,
        children: [
          Container(child: Icon(Icons.add, size: 120,), color: Colors.yellow,),
          Container(child: Icon(Icons.sort, size: 90,), color: Colors.red,),
          Container(child: Icon(Icons.ac_unit, size: 60,), color: Colors.purpleAccent,),
          Container(child: Icon(Icons.access_alarm, size: 30,), color: Colors.greenAccent,), ], ), ); }}Copy the code

Expanded

The panel using Expand fills the current spindle method, leaving no space in the spindle direction and wrapping lines when the horizontal layout is insufficient.

import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment(0.0),
      child: Row(
        children: [
          Expanded(child: Container(child: Icon(Icons.add, size: 120,), color: Colors.yellow,)),
          Expanded(child: Container(child: Icon(Icons.sort, size: 90,), color: Colors.red,)),
          Expanded(child: Container(child: Icon(Icons.ac_unit, size: 60,), color: Colors.purpleAccent,)),
          Expanded(child: Container(child: Icon(Icons.access_alarm, size: 30,), color: Colors.greenAccent,)), ], ), ); }}Copy the code