This article has authorized the public account “code egg”, please indicate the source of reprint

When I mentioned the basic components, I forgot to mention the input processing components, so I’ll add them here, and then I’ll show you the actual interface

TextField

const TextField({
    Key key,
    this.controller, // Define an instance of 'TextEditingController' to get the contents of the input box, etc
    this.focusNode, // Define an instance of 'FocusNode' to determine whether the current input box gets focus, etc
    this.decoration = const InputDecoration(), // Input field styles, including reminders, hints, and so on
    TextInputType keyboardType, // Enter a text type, such as number, email, etc
    this.textInputAction, // The event type of the keyboard confirm button
    this.textCapitalization = TextCapitalization.none,
    this.style, // Text style
    this.textAlign = TextAlign.start, // Alignment
    this.textDirection, // Text direction
    this.autofocus = false.// Whether to automatically get focus
    this.obscureText = false.// Whether the text is hidden
    this.autocorrect = true.this.maxLines = 1.//
    this.maxLength, // Maximum length
    this.maxLengthEnforced = true.// After the maximum length is set, whether to force no input if the input content exceeds the maximum length
    this.onChanged, // A callback when the input changes
    this.onEditingComplete, // Input completed callback
    this.onSubmitted, // A callback to the submitted content
    this.inputFormatters, // 
    this.enabled, False cannot be entered
    this.cursorWidth = 2.0.// Cursor width
    this.cursorRadius, // Cursor radius
    this.cursorColor, // Cursor color
    this.keyboardAppearance, // This property only works on iOS devices
    this.scrollPadding = const EdgeInsets.all(20.0),
    this.enableInteractiveSelection,
    this.onTap, // Click the event
  })
Copy the code

So, let’s take a simple example of an input field and show the result through Text

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // You can pass in an initial value
  TextEditingController _editController = TextEditingController();
  FocusNode _editNode = FocusNode();
  // Save the input value after the button is clicked
  String _content = ' ';
  // Listen for input changes to the content value
  String _spyContent = ' ';

  @override
  void initState() {
    super.initState();
    // This is called when the input box gets focus or loses focus
    _editNode.addListener(() {
      print('edit has focus? = >${_editNode.hasFocus}');
    });
  }

  @override
  void dispose() {
    // Remember to destroy to prevent memory overflow
    _editController.dispose();
    _editNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Input Content'),
      ),
      body: Container(
          padding: const EdgeInsets.symmetric(horizontal: 12.0),
          child: Column(
            children: <Widget>[
              TextField(
                controller: _editController,
                focusNode: _editNode,
                decoration: InputDecoration(
                    icon: Icon(Icons.phone_iphone, color: Theme.of(context).primaryColor),
                    labelText: 'Please enter your mobile phone number',
                    helperText: 'Mobile phone Number',
                    hintText: 'Mobile number... So I'm going to type in here '),
                keyboardType: TextInputType.number,
                // The input type is numeric
                textInputAction: TextInputAction.done,
                style: TextStyle(color: Colors.redAccent, fontSize: 18.0),
                textDirection: TextDirection.ltr,
                maxLength: 11.// The maximum length is 11
                maxLengthEnforced: true.// If the length exceeds the specified length, it will not be displayed
                onChanged: (v) { // Is called when the input changes
                  setState(() => _spyContent = v);
                },
                onSubmitted: (s) { // is called when the OK button is clicked
                  setState(() => _spyContent = _editController.value.text);
                },
              ),
              Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8.0),
                  child: RaisedButton(
                      onPressed: () { 
                        // Get the input
                        setState(() => _content = _editController.value.text);
                        // Clean up the input
                        _editController.clear();
                        setState(() => _spyContent = ' ');
                      },
                      child: Text('Get input'))),
              // Display the input. Click the button to display it
              Text(_content.isNotEmpty ? 'Get input: $_content' : 'Not getting anything yet... '),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                // Listen for changes in the input and change with the input
                child: Text('I'm text content monitor: $_spyContent'() [() () [() () ( }}Copy the code

The setState method is only available in StatefulWidget. When a value needs to be modified, you can use this method to change the value. The final result is as follows. The Text that gets the content changes when the button is clicked

This part of the code is viewedtext_field_main.dartfile

So if there is a need to check the rationality of the input content when the button is clicked, of course you can check the result of TextEditingController, but there is a more convenient way, you can directly use the component TextFormField to achieve this. But we need to add a Form widget to the outer layer. Next, we need to use TextFormField to create a login interface, but before that, there is a pit in front that needs to be solved first

Import a custom icon

How to import third-party custom ICONS? I’ll tell you the answer. First of all, we need to open “Ali Mom”, also known as iconfont. We can also directly log in through Github and other three parties, and then we can search for the icon we need. Next, we need to log in by clicking on an icon of user and password, select the icon we like, and then three buttons will appear when we place the mouse over the icon. Click the button of shopping cart directly. You can then view the added icon through the shopping cart button at the top and click on the Download code to download the resource file locally.

After decompression, you need to use two files, others can be ignored

  1. demo_index.htmlThis is for viewing ICONSunicode
  2. iconfont.ttfHere is the icon resource file

Go back to your project, create a folder — fonts, the same as images — and place the iconfont. TTF file in that folder. Then open the pubspec.ymal file, register the imported resources, and name the iconfont. For example, I named it third_part_icon.ttf and added it under the registration image

fonts:
  - family: ThirdPartIcons
    fonts:
    - asset: fonts/third_part_icon.ttf
Copy the code

After registering, please click Package Get, otherwise you will not find the resource. I’m going to create a new third_icons. Dart file

import 'package:flutter/material.dart';

class ThirdIcons {
  // The codePoint value can be obtained by opening 'demo_index.html'
  // replace '&#' with '0' and drop the last '; Can be `
  / / such as & # xe672; The corresponding icon is 0xe672
  static const IconData username = ThirdIconData(0xe672);
  static const IconData password = ThirdIconData(0xe62f);
}

class ThirdIconData extends IconData {
  // fontFamily is the family we registered in 'pubspec.yaml'
  const ThirdIconData(int codePoint) : super(codePoint, fontFamily: 'ThirdPartIcons');
}
Copy the code

This class is then used to import the required third-party ICONS.

Importing third-party Plug-ins

A plugin is the bridge between Flutter and native interaction. That is to say, to write a plugin for Flutter, you need to write code on both Android and iOS. Otherwise, only one of them can implement the function. Fortunately, many ready-made plug-ins are open source and can be searched through FlutterPackage. For example, we will need to use the plug-in FlutterToast for reminding later. After searching the plug-in in FlutterPackage, Open the pubspec.ymal file in the project and introduce the Fluttertoast plugin under the Dependencies class, as shown in the following figure:

Then click Package Get to import it, as do other plug-ins. Do your homework and we will have a login interface

A login interface

Before starting the game, let’s have a look at the final image, although it is a commonly used interface (since the image is made by myself, please don’t mind if it is ugly).

Because the two interfaces are similar, only the outer code and the login code are posted here. For the specific code, you can view the source code, which has been pushed to Github

void main() {
  runApp(LoginApp());

  if (Platform.isAndroid) {
    varstyle = SystemUiOverlayStyle(statusBarColor: Colors.transparent); SystemChrome.setSystemUIOverlayStyle(style); }}/// The outer interface, the package login interface and the registration interface are all used in the previous section
class LoginApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Login Demo',
      debugShowCheckedModeBanner: false, theme: ThemeData(primarySwatch: Colors.lightBlue), home: LoginHomePage(), ); }}class LoginHomePage extends StatefulWidget {
  @override
  _LoginHomePageState createState() => _LoginHomePageState();
}

class _LoginHomePageState extends State<LoginHomePage> with SingleTickerProviderStateMixin {
  TabController _tabController;
  List<String> _pageIndicators = ['login'.'registered'];
  List<Widget> _pages = [];
  int _position = 0;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: _pageIndicators.length, vsync: this);
    // Add the login and registration screens to the list for placing in the Children property of the IndexStack_pages.. add(LoginPage()).. add(RegisterPage()); _tabController.addListener(() {// When TAB is switched, the child page of the linkage IndexStack is also modified, using setState to change the value
      if (_tabController.indexIsChanging) setState(() => _position = _tabController.index);
    });
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Ignore...
    return Theme(
        data: ThemeData(primarySwatch: Colors.pink, iconTheme: IconThemeData(color: Colors.pink)),
        child: Scaffold(
          body: Container(
            padding: const EdgeInsets.all(20.0),
            alignment: Alignment.center,
            decoration:
                BoxDecoration(image: DecorationImage(image: AssetImage('images/login_bg.png'), fit: BoxFit.cover)),
            
            // Ignore... The following will be said, mainly to solve the soft keyboard pop-up, the interface content will overflow the problem
            child: SingleChildScrollView(
              child: SafeArea(
                  child: Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
                // Top page switch indicator, code can refer to 'app_bar_main.dart' file
                TabBar(
                    indicatorSize: TabBarIndicatorSize.label,
                    controller: _tabController,
                    indicatorWeight: 4.0,
                    indicatorColor: Colors.white,
                    // Return the TAB list
                    tabs: _pageIndicators
                        .map((v) => Text(v, style: TextStyle(color: Colors.white, fontSize: 24.0)))
                        .toList()),
                Padding(
                    padding: const EdgeInsets.only(top: 30.0),
                    child: SizedBox(
                        // Switch the interface list
                        child: IndexedStack(children: _pages, index: _position),
                        // Specify the height
                        height: MediaQuery.of(context).size.height / 2)))))))); }}Copy the code
/// Login interface
class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  // Is used later to determine whether the form content is valid
  GlobalKey<FormState> _formKey = GlobalKey();
  // Get the contents of the input box
  TextEditingController _usernameController = TextEditingController();
  TextEditingController _passwordController = TextEditingController();

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

  @override
  void dispose() {
    // To prevent memory overflow, remember to destroy.. Destroyed.. The destruction
    _usernameController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  _login() {
    // Remove focus
    FocusScope.of(context).requestFocus(FocusNode());

    // Determine if the form is valid
    if (_formKey.currentState.validate()) {
      // Get the contents of the input box
      var username = _usernameController.value.text;
      var password = _passwordController.value.text;

      // Determine the login condition
      if (username == 'kuky' && password == '123456')
        // Introduced the tripartite plugin method, 'Flutter' does not have its own 'Taost'
        Fluttertoast.showToast(msg: 'Login successful');
      else
        Fluttertoast.showToast(msg: 'Login failed'); }}@override
  Widget build(BuildContext context) {
    return Form(
        // Set the key to the form to determine whether the form is valid
        key: _formKey,
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 4.0),
              // Form input field with parameters similar to TextField
              child: TextFormField(
                controller: _usernameController,
                style: TextStyle(color: Colors.white, fontSize: 16.0),
                decoration: InputDecoration(
                    icon: Icon(ThirdIcons.username, size: 24.0, color: Colors.white),
                    labelText: 'Please enter a user name',
                    labelStyle: TextStyle(color: Colors.white),
                    helperStyle: TextStyle(color: Colors.white)),
                // Valid condition (if null, return prompt, return null)
                validator: (value) => value.trim().isEmpty ? 'User name cannot be empty' : null,
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 4.0),
              child: TextFormField(
                obscureText: true,
                controller: _passwordController,
                style: TextStyle(color: Colors.white, fontSize: 16.0),
                decoration: InputDecoration(
                    icon: Icon(ThirdIcons.password, size: 24.0, color: Colors.white),
                    labelText: 'Please enter your password',
                    labelStyle: TextStyle(color: Colors.white),
                    helperStyle: TextStyle(color: Colors.white)),
                validator: (value) => value.trim().length < 6 ? 'Password length must not be less than 6 characters' : null,
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(top: 20.0),
              child: SizedBox(
                // Mainly used to make RaisedButton the same width as the upper container
                width: MediaQuery.of(context).size.width,
                child: RaisedButton(
                    color: Colors.pink,
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
                    onPressed: _login,
                    child: Text(
                      'login',
                      style: TextStyle(color: Colors.white, fontSize: 20.0),),),)],)); }}Copy the code

If the contents of the input field do not match TextFormField’s Validator criteria, it will display an error message

If the user name is kuky and the password is 123456 according to the condition (the condition can be modified according to your own), the logon is successful

View the above codelogin_home_page.dartfile

The logic of the registration interface is almost the same as the logic of the login interface, which is the first time to practice, I hope my friends can write a good time

The final code address is still needed:

  1. The code covered in this article: Demos

  2. BLoC mode based on a project of Guo Shen Cool Weather interface to achieve state management: Flutter_weather

  3. One course (I bought the code specification at that time and wanted to see it, the code update would be slow, although I wrote the code following the lessons, I still made my own modifications, which made me uncomfortable in many places, and then changed it to my own implementation) : Flutter_shop

If it is helpful to you, please remember to give me a Star. Thank you in advance. Your recognition is the motivation to support me to continue writing