The text

  • Common Configurations

    class TextTest extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            body: Padding(
          padding: EdgeInsets.all(30),
          child: Column(
            children: <Widget>[
              Text("hello "),
              // The maximum number of lines is one, textoverflow. ellipsis: ellipsis instead
              Text(
                "hello! I'm 345 " * 5,
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
              // Text scaling factor
              Text("hello 345", textScaleFactor: 2),
              //
              Text("hello 345",
                  style: TextStyle(
                      / / color
                      color: Colors.red,
                      // The size is 14 by default
                      fontSize: 18./ / the thickness
                      fontWeight: FontWeight.w800,
                      / / italics
                      fontStyle: FontStyle.italic,
                      //underline: underline, overline, lineThrough: underline
                      decoration: TextDecoration.underline,
                      decorationColor: Colors.black,
                      // Solid: the solid line, double: the dotted line, dotted line, the wavy: the wavy linedecorationStyle: TextDecorationStyle.wavy)) ], ), )); }}Copy the code

TextAlign: Alignment of text; You can choose to align left, right, or center. Notice that the reference frame for alignment is the Text widget itself

  • DefaultTextStyle

    In the Widget tree, text styles are inheritable by default, so if you set a default style to a node in the Widget tree, all text in the interface’s subtrees will default to that style

    Widget build(BuildContext context) {
      return Scaffold(
          body: Padding(
              padding: EdgeInsets.all(30),
              child: DefaultTextStyle(
                  style: TextStyle(
                    / / color
                    color: Colors.red,
                    // The size is 14 by default
                    fontSize: 20./ / the thickness
                    fontWeight: FontWeight.w900,
                  ),
                  child: Column(
                    children: [
                      Text("hello "),
                      Text("hello! I'm 345 " * 5, maxLines: 1,overflow: TextOverflow.ellipsis,),
                      // Replace the default text
                      Text("hello 345",style: TextStyle(fontSize: 25, color: Colors.black))
                    ],
                  ))));
    }
    Copy the code

  • TextSpan

    If you need to display different parts of a Text, you can use TextSpan, which represents a fragment of the Text

      const TextSpan({
      	TextStyle style, 
      	Sting text,
      	List<TextSpan> children,
      	GestureRecognizer recognizer,
      });
    Copy the code

    Style and text represent style and content, and children are an array, which means that TextSpan can contain other TextSpans, and the recognizer recognises that text fragment with gestures

    Widget _richText() {
    var textSpan = TextSpan(text: "hello", children: [
        TextSpan(text: "3", style: TextStyle(color: Colors.blueAccent)),
      TextSpan(text: "4", style: TextStyle(color: Colors.black)),
        TextSpan(text: "5", style: TextStyle(color: Colors.green))
    ]);
      return Text.rich(textSpan);
    }
    Copy the code

    We used the text. rich method above to add TextSpan to Text because Text itself is a wrapper around RichText, which is a widget that displays a variety of styles (rich Text) as follows:

    • The font

      Using fonts in FLUTTER requires two steps, first declaring them in a pubspec.yaml file and then using the font via the textStyle property

      flutter:
        fonts:
          - family: Raleway
            fonts:
              - asset: assets/fonts/Raleway-Regular.ttf
              - asset: assets/fonts/Raleway-Medium.ttf
                weight: 500
              - asset: assets/fonts/Raleway-SemiBold.ttf
                weight: 600
          - family: AbrilFatface
            fonts:
              - asset: assets/fonts/abrilfatface/AbrilFatface-Regular.ttf
      Copy the code

      Use the font

      // Declare a text style
      const textStyle = const TextStyle(
        fontFamily: 'Raleway',);// Use text styles
      var buttonText = const Text(
        "Use the font for this text",
        style: textStyle,
      );
      Copy the code

button

The Material component library provides many button components, such as RaisedButton, FlatButton, OutlineButton, etc., which are indirect or direct packaging customization of RawMaterialButton components. So most of them are properties just like RawMaterialButton

Additionally, buttons in all Material libraries have the following in common:

1. “Water ripple Animation” will appear when pressed.

Both have an onPressed property to set the callback of the click event. Without this callback, the button will be disabled and the disabled state will not respond to user clicks

All kinds of common buttons

class Button extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
      padding: EdgeInsets.all(20),
      child: Column(
        children: [
          // Float button with shadow and grey background by default
          RaisedButton(
            child: Text("RaisedButton"),
            onPressed: () => print('RaisedButton'),),// Flat button, default background transparent without shadow
          FlatButton(
            child: Text("flatButton"),
            onPressed: () => print('flatButton'),),// There is a border by default, with no shadow and a transparent background
          OutlineButton(
            child: Text("OutlineButton"),
            onPressed: () => print('OutlineButton'),),// Clickable Icon
          IconButton(
            icon: Icon(Icons.thumb_up_alt),
            onPressed: () => print('thumb up'),),// An icon button is created using the icon constructor
          RaisedButton.icon(
            icon: Icon(Icons.send),
            label: Text("Send"),
            onPressed: () => print('send'),
          ),
          FlatButton.icon(
            icon: Icon(Icons.live_help),
            label: Text("Doubt"),
            onPressed: () => print('doubt'() [() [() (). }}Copy the code

Some buttons are defined by the icon constructor by default, and the same constructor can easily create a button with an icon, such as RaisedButton, etc

Customize the appearance of buttons

The appearance of a button can be defined by properties. Different button properties are almost the same. Take FlatButton as an example, take a look at the commonly used button properties and see the API for details

const FlatButton({
  ...  
  @required this.onPressed, // Button click callback
  this.textColor, // Button text color
  this.disabledTextColor, // Text color when the button is disabled
  this.color, // Button background color
  this.disabledColor,// The background color of the button when disabled
  this.highlightColor, // The background color when the button is pressed
  this.splashColor, // When clicked, the color of the wave in the wave animation
  this.colorBrightness,// Button theme, default is light color theme
  this.padding, // Button padding
  this.shape, / / shape
  @required this.child, // The contents of the button
})
Copy the code

Chestnut: Define a submit button

FlatButton(
  color: Colors.blue,
  child: Text("Submit"),
  splashColor: Colors.grey,
  highlightColor: Colors.red,
  shape:
      RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
  onPressed: () => print('submit'),Copy the code

There is no setting to remove the background in Flutter. If you want to remove the background, you can do this by setting the background color to transparent. Replace color: color. blue with color: color (0x000000)

FlatButton has no shadow, so it always feels a little bit worse. If you need a shadow, just use RaisedButton

const RaisedButton({
  ...
  this.elevation = 2.0.// Shadow in normal state
  this.highlightElevation = 8.0.// Shadow when pressed
  this.disabledElevation = 0.0.// Shadow when disabled. }Copy the code

Elevation, which is used to control shadows, is found in many components

The picture

In Flutter, images can be loaded and displayed via the Image component. The loading sources of images can be asset, file, memory, or network

  • ImageProvider

    ImageProvider is an abstract class that defines the interface for retrieving images, load. Retrieving images from different data sources requires implementing different ImageProviders. For example, AssetImage implements the ImageProvider for loading images from Asset. NetWorkImage S implements the ImageProvider to load images from the network.

  • Image

    The Image Widget has a mandatory parameter that corresponds to an ImageProvider

  • Loading pictures

    Load images and other resources refer to this article

    1. Load the pictures in Assets

    Image(
      image: AssetImage("images/avatar.png"),
      width: 100.0
    );
    Image.asset("images/avatar.png",
      width: 100.0.)Copy the code

    2. Load network images

    Image(
      image: NetworkImage(
          "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
      width: 100.0,
    )
    Image.network(
      "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
      width: 100.0.)Copy the code

    3. Load the local image file

    Image.file
    Copy the code

    4. Load the memory image

    Image.memory
    Copy the code
  • parameter

    const Image({
      ...
      this.width, // Width of the image
      this.height, // Image height
      this.color, // The mixed color value of the image
      this.colorBlendMode, // Mix mode
      this.fit,// Zoom mode
      this.alignment = Alignment.center, // Alignment
      this.repeat = ImageRepeat.noRepeat, // Repeat mode. })Copy the code
    • Width, height: Sets the width and height of the image. If not specified, the image will display its original size as much as possible according to the limits of the current parent container. If only one of the images is set, the other one will be scaled, but you can use the fit property to fit the rules

    • Fit: Used to specify the fit mode of an image when the display space of the image differs from the size of the image itself

      fit nature
      BoxFit.fill Fill, ignoring the original aspect ratio, until filled
      BoxFit.contain Contain, do not change the original scale of the container to contain the entire image, the rest of the container to fill the background
      BoxFit.cover Overwrite, do not change the original proportion, let the picture fill the whole container, the redundant part of the picture cut
      BoxFit.fitWidth Image landscape fill
      BoxFit.fitHeight Image portrait fill
      BoxFit.none There is no style, the original size is centered, and if the image is larger than the display space, only the middle part of the image will be displayed
      BoxFit.scaleDown Contain none if the size of an image is smaller than its container
    • Color and colorBlendMode: you can mix the colors of each pixel when drawing the picture. Color specifies the blend color and colorBlenMode specifies the blend mode

      Image(
        image:NetworkImage("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.houpao.com%2Fdy%2Fdyrs%2F20200711%2F94fb713a5985aa0c0c6f29a20 357880 f.jpeg&refer=http%3a%2f%2fimg.houpao.com & app = 2002 & size = f9999, 10000 & q = a80 & n = 0 & g = 0 n & FMT = jpeg? = 1614828035 & t = cf5430 the SEC f8cc9a51b7000cde9c9cc30b5a"),
        width: 500,
        height: 300,
        fit: BoxFit.cover,
        color: Colors.red,
        colorBlendMode: BlendMode.difference,
      )
      Copy the code

    • Repeat: Specifies a repeat rule for the image when the image itself is smaller than the display space

  • The Image cache

    The Flutter framework has a cache (memory) for loading images. By default, the maximum cache size is 1000 and the maximum cache space is 100M

  • Commonly used picture components

    • CircleAvatar

      CircleAvatar(
      backgroundImage:NetworkImage("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.houpao.com%2Fdy%2Fdyrs%2F20200711%2F94fb713a5985aa0c0c6f29a20 357880 f.jpeg&refer=http%3a%2f%2fimg.houpao.com & app = 2002 & size = f9999, 10000 & q = a80 & n = 0 & g = 0 n & FMT = jpeg? = 1614828035 & t = cf5430 the SEC f8cc9a51b7000cde9c9cc30b5a"),
        radius: 50,),Copy the code

      Circular images

    • FadeInImage

    FadeInImage(
      image: NetworkImage("https://gimg2.baidu.com/i......."),
      placeholder: AssetImage("images/icon.png"),Copy the code

    Loading images directly from the network and then displaying them would be a bit awkward. Using FadeInImage will display a placeholder during the image loading process and fade in after the image is loaded

ICON

In Flutter, font ICONS can be used directly. They are made into font files and created into different images by specifying different characters

In font files, each character corresponds to a code, and each code corresponds to a display glyph. Different fonts mean different glyph, and characters correspond to different glyph. Iconfont, on the other hand, just makes the glyphs corresponding to the bitcodes into ICONS, so different characters end up rendering different ICONS

Iconfont has the following advantages over images in Flutter

1. Small volume

2, vector icon, magnification will not affect the clarity

3, you can apply text style, you can change font icon color, size alignment and so on like text

4. You can mix TextSpan with text

Use the Material Design font icon

Flutter by default contains a library of Font ICONS for Material Design, as configured in the pubspec.yaml file

flutter:
  uses-material-design: true
Copy the code

Look at a simple chestnut

String icons = "";
icons += "\uE814";
icons += " \uE200";
icons += " \uE80D";

 Text(
 	icons,
 	style: TextStyle(
 	fontFamily: "MaterialIcons", fontSize: 40, color: Colors.green),
 )
Copy the code

As can be seen above, ICONS are used just like text, but this requires a code point for each Icon, which is not developer-friendly. Therefore, Flutter encapsulates IconData and Icon to display font ICONS

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Icon(Icons.accessible, color: Colors.green),
    Icon(Icons.error, color: Colors.green),
    Icon(Icons.fingerprint, color: Colors.green)
  ],
)
Copy the code

Use custom icon libraries

1. Import the TTF file

fonts:
  - family: myIcon  # specify a font name
    fonts:
      - asset: fonts/iconfont.ttf
Copy the code

2. Custom icon class, which functions like the Icons above, defining all the files in the font file as static variables

class MyIcons{
  static const IconData book = const IconData(
      0xe614, 
      fontFamily: 'myIcon', 
      matchTextDirection: true
  );
  static const IconData wechat = const IconData(
      0xec7d,  
      fontFamily: 'myIcon', 
      matchTextDirection: true
  );
}
Copy the code

3, the use of

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Icon(MyIcons.book,color: Colors.purple,),
    Icon(MyIcons.wechat,color: Colors.green,),
  ],
)
Copy the code

Radio buttons and check boxes

The Material component library provides radio switches and checkboxes, which themselves are inherited from StatefulWidget. They do not store the current selection state themselves. The selected state is managed by the parent component.

When the Switch or CheckBox is clicked, the onChanged callback is triggered, and we can change the logic in the callback

class SwitchAndCheckboxTest extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return_SwitchAndCheckboxTest(); }}class _SwitchAndCheckboxTest extends State<SwitchAndCheckboxTest> {
  bool _switchSelected = true; // Single mode
  bool _checkboxSelected = true; // Check box status
  var groupValue = 0; // The default value is selected
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Radio switches and check boxes"),
      ),
      body: Column(
        children: [
          Switch(
            value: _switchSelected,
            activeColor: Colors.red,
            onChanged: (value) {
              setState(() {
                _switchSelected = value;
              });
            },
          ),
          Checkbox(
            value: _checkboxSelected,
            activeColor: Colors.red,
            onChanged: (value) => setState(() => _checkboxSelected = value),
          ),
          Row(
            children: [
              Radio(
                activeColor: Colors.red,
                // The value bound by this single box
                value: 0.// Click the state change callback
                onChanged: (value) => setState(() => this.groupValue = value),
                // The selected value in the current component
                groupValue: groupValue,
              ),
              Radio(
                // The value bound by this single box
                activeColor: Colors.red,
                value: 1.// Click the state change callback
                onChanged: (value) => setState(() => this.groupValue = value),
                // The selected value in the current component
                groupValue: groupValue,
              ),
              Radio(
                activeColor: Colors.red,
                // The value bound by this single box
                value: 2.// Click the state change callback
                onChanged: (value) => setState(() => this.groupValue = value),
                // The selected value in the current componentgroupValue: groupValue, ) ], ) ], ), ); }}Copy the code

In the above code, you need to maintain the state of the component, so inherit from the StatefulWidget. In build, you build the checkBox and Switch and Radio, modify the state when clicked, and then rebuild the UI

attribute

  • The common property activeColor sets the color of the active state
  • Width height: The Checkbox cannot be customized, and the Switch can only be customized
  • Checkbox has a tristate attribute that indicates whether the Checkbox is tristate. The default value is false. If true, valude is automatically added to the value of null

conclusion

Switch, Checkbox, and Radio do not maintain state themselves, but require the parent component to manage state. When the user clicks, the parent component is notified of the state through events, so whether or not the user data is selected is associated with the user data, and the user data is not their private state. Therefore, we should consider which approach makes the most sense when customizing components

Input fields and forms

The Material component library provides the input field component TextField and the form component From, which we’ll look at in detail

TextField

For text input, it provides a number of attributes, but first let’s take a quick look at the key attributes

const TextField({
  ...
  TextEditingController controller, 
  FocusNode focusNode,
  InputDecoration decoration = const InputDecoration(),
  TextInputType keyboardType,
  TextInputAction textInputAction,
  TextStyle style,
  TextAlign textAlign = TextAlign.start,
  bool autofocus = false.bool obscureText = false.int maxLines = 1.int maxLength,
  bool maxLengthEnforced = true,
  ValueChanged<String> onChanged,
  VoidCallback onEditingComplete,
  ValueChanged<String> onSubmitted,
  List<TextInputFormatter> inputFormatters,
  bool enabled,
  this.cursorWidth = 2.0.this.cursorRadius,
  this.cursorColor,
  ...
})
Copy the code
  • Controller: The controller of the edit box, through which you can set/obtain the content of the edit box, select the content of the edit box, and listen to the text change event of the edit box. In most cases we need to explicitly provide a Controller to interact with the TextField; if not, TextField will automatically create one

  • FocusNode: Controls whether the TextField takes focus of the current keyboard input. It is a handle (handler) for our interaction with the keyboard.

  • InputDecoration: Used to control the appearance of the TextField, such as prompt text, background color, border, etc

  • KeyboardType: sets the keyboard input type of the input box. The value can be:

    TextInputType enumerated values meaning
    text Text input keyboard
    multiline Multi-line text, used with maxLines (set to null or greater than 1)
    number Digital; A numeric keypad will pop up
    phone Optimized phone number input keyboard; Numeric keypad will pop up and display “* #”
    datetime Optimized date input keyboard; Android will display “: -“
    emailAddress Optimized email address; Will display “@.”
    url Optimized URL input keyboard; Will display “/.”
  • TextInputAction: keyboard action button icon, it is an enumerated value, there are multiple optional values, the specific can be viewed API

  • Style: The style of the text being edited

  • TextAlign: Horizontal alignment of edited text in an input box

  • Autofocus: Indicates whether to automatically obtain the focus.

  • ObscureText: Whether to hide the text being edited, such as entering a password.

  • MaxLines: Indicates the maximum number of input lines. The default value is 1. If the value is null, the value is unlimited maxLength and maxLengthEnforced. The latter determines whether to block input if its length exceeds maxLength

  • OnChange: Callback to change the content of the input box, also monitored by controller

  • OnEditingComplete and onSubmitted: Both of these are triggered when typing is complete, such as keyboard completion, or search, etc. The difference is that the latter callback is ValueChanged

    and the former takes no arguments

  • InputFormatters: Specifies the input format. When the input changes, it is validated against the specified format

  • Enable: If the value is false, the input box is disabled

  • CursorWidth, cursorRadius, and cursorColor: defines the cursorWidth, rounded corners, and color

chestnuts

class InputText extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return_InputText(); }}class _InputText extends State<InputText> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Input field"),
      ),
      body: Column(
        children: [
          TextField(
            autocorrect: true,
            decoration: InputDecoration(
                labelText: "Username",
                hintText: "Username or email address",
                prefixIcon: Icon(Icons.person)),
          ),
          TextField(
            decoration: InputDecoration(
                labelText: "Password",
                hintText: "Your login password",
                prefixIcon: Icon(Icons.lock)),
            obscureText: true() [(), (); }}Copy the code

  • Get input

    1, define two variables, then save when onChange is triggered

    2. Obtain the IP address from controler

    // Define a controller
    TextEditingController _nameController = TextEditingController();
    Copy the code
    TextField(
        autofocus: true,
        controller: _nameController, / / set the controller...).Copy the code
    // You can print it directly
    print(_nameController.text)
    Copy the code

    Controller can also be used to set default values, select text, and so on

    _nameController.text="hello world!";
    _nameController.selection=TextSelection(
        baseOffset: 2,
        extentOffset: _nameController.text.length
    );
    
    TextField(
      controller: _nameController,
    )
    Copy the code
  • Control the focus

    Focus can be controlled by FocusNode and FocusScopeNode. By default, focus is managed by FocusScope, which represents the focus control range within which FocusScopeNode can be used to move focus between input boxes, set the default focus, and so on. We can get the default FocusScope.of(context) in the Widget tree.

  • Simple focus state change events

    / / create focusNode
    FocusNode focusNode = newFocusNode(); .// focusNode binds the input boxTextField(focusNode: focusNode); .// Listen for focus changes
    focusNode.addListener((){
       print(focusNode.hasFocus);
    });
    Copy the code
  • Custom styles

    • Hidden text

       TextField(
           obscureText: true.)Copy the code

      After hiding, the input content will not be visible and become the password type

    • The keyboard type

      TextField(
      	keyboardType: TextInputType.number,
      ),
      Copy the code

      For example, “number” can only be entered as a number, and there are many other values, such as the following, which you can check for yourself

    • The keyboard button

      That is, the lower right corner of the keyboard button, common such as finish, is a tick button, etc

    • case

      Control the case of English letters, such as uppercase letters, etc

      TextField(
      	textCapitalization: TextCapitalization.words,
      ),
      Copy the code

      TextCapitalization options

      1, Words: capitalize the first letter of a word

      2. Capitalize the first letter of the sentence

      3, characters: capitalize all letters

      4, None: default none

    • The cursor

      TextField(
      	cursorColor: Colors.orange,/ / color
      	cursorWidth: 15./ / width
      	cursorRadius: Radius.circular(15),/ / the rounded
      ),
      Copy the code
    • counter

      TextField(
        maxLength: 11,
      ),
      Copy the code

      Set the maximum length counter to display

      Custom counters/ICONS

         TextField(
                  autocorrect: true,
                  maxLength: 11,
                  controller: _nameController,
                  decoration: InputDecoration(
                      labelText: "Username",
                      hintText: "Username or email address",
                      counter: Text("Counter 0/100"),
                      prefixIcon: Icon(Icons.person)),
                ),
      Copy the code

      Implement custom counters through counter

      PrefixIcon allows you to set the left inner icon, and icon allows you to set the left outer icon

      decoration: InputDecoration( suffixIcon: IconButton( icon: Icon(Icons.close), onPressed: () { controller.clear(); },),Copy the code

      SuffixIcon allows you to set the inside icon on the right and click events

    • Error text prompt

      TextField(
      	controller: controller,
      	decoration: InputDecoration(
      		errorText: "Please enter the content",),),Copy the code
    • Remove underline

      decoration: InputDecoration.collapsed(hintText: "Username or email address")),
      Copy the code
    • A border

        decoration: InputDecoration(
                    border: OutlineInputBorder(
                        borderRadius: BorderRadius.all(Radius.circular(15)),/ / the rounded
                        borderSide: BorderSide(color: Colors.red, width: 2.0)),// Color, width
                  ),
      Copy the code

      The color is theme color, //TODO Settings do not take effect, will be resolved later

Form the Form

In practice, Flutter validates the data in the input field before making a request to the interface. It would be cumbersome to validate each TextField. To this end, Flutter provides a Form component that groups the input fields together and performs operations such as content validation, resetting, and saving

Form inherits from the StatefulWidget class and corresponds to a FormState, defined as follows:

Form({
  @required Widget child,
  bool autovalidate = false,
  WillPopCallback onWillPop,
  VoidCallback onChanged,
})
Copy the code
  • Autovalidate: Indicates whether the input is automatically validated. If this parameter is true, each FormField automatically validates the input and displays an error message. Otherwise, passFormState.validate()To check manually
  • OnWillPop: decisionFormIf the Future is false, the current route will not return. If true, the previous route will return. This property is usually used to block buttons
  • OnChange: Any word of FormFormFieldThis callback is triggered whenever the content changes

FormField

FormField is an abstract class with several attributes through which FormState performs operations. The FormField section is defined as follows:

const FormField({
  ...
  FormFieldSetter<T> onSaved, // Save the callback
  FormFieldValidator<T>  validator, // Validate the callback
  T initialValue, / / initial value
  bool autovalidate = false.// Whether to check automatically.
})
Copy the code

For ease of use, Flutter provides a TextFormField component that inherits from the FormField class and is also a wrapper class, so it also includes the properties of TextField in addition to the FormField

FormState

FormState is the Form’s State class, which can be obtained via form.of () or Globalkey, which we can use to operate on FormField, the Form’s descendant.

  • Formstate.validate () : this method calls the 1 validate callback of the Form descendant FormFile, which returns false if one of the validations fails and an error message if any validations fail
  • Formstate.save () : This method calls the save callback of the Form descendant FormField to save the Form content
  • Formsata.reset () : This method clears the descendant FormField

chestnuts

class InputText extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return_InputText(); }}class _InputText extends State<InputText> {
  // Define a controller
  TextEditingController _nameController = TextEditingController();

  GlobalKey _formKey = new GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
    _nameController.addListener(() => print("Account number:" + _nameController.text));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Input field"),
        ),
        body: Padding(
          padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
          child: Form(
            key: _formKey,// Set globalKey to get FormState later
            autovalidate: true.// Enable automatic verification
            child: Column(
              children: [
                TextFormField(
                  autocorrect: true,
                  maxLength: 11,
                  controller: _nameController,
                  decoration: InputDecoration.collapsed(hintText: "Username or email address"),
                  validator: (v) {
                    return v.trim().length > 0 ? null : "User name cannot be empty";
                  },
                ),
                TextFormField(
                  decoration: InputDecoration.collapsed(hintText: "Your login password"),
                  validator: (v) {
                    return v.trim().length > 5 ? null : "Password must be no less than six characters.";
                  },
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 28),
                  child: Row(
                    children: [
                      Expanded(
                        child: RaisedButton(
                          padding: EdgeInsets.all(15),
                          child: Text("Login"),
                          color: Theme.of(context).primaryColor,
                          textColor: Colors.white,
                          onPressed: () {
                            // Get formState, call validate,
                            if ((_formKey.currentState as FormState)
                                .validate()) {
                              print('Verification successful'); }},),),),),),),)); }}Copy the code

Form. Of (context) cannot be retrieved in the login button onPressed method because the context is the InputText context**, Form.of(context) looks at the root of the specified context, and FormState is in the InputText subtree, so it doesn’t work. 支那

The correct way to build the login button is through the Builder, which takes the widget node’s context as a callback argument:

Expanded(
  child: Builder(builder: (context) {
    return RaisedButton(
      padding: EdgeInsets.all(15),
      child: Text("Login"),
      color: Theme.of(context).primaryColor,
      textColor: Colors.white,
      onPressed: () {
        // Get formState, call validate,
        if ((Form.of(context)).validate()) {
          print('Verification successful'); }}); }),)Copy the code

Use this method


Refer to self Flutter actual combat