1. 程式人生 > >Flutter佈局錦囊---帶彩條的文字欄位

Flutter佈局錦囊---帶彩條的文字欄位

設計給的效果如下:

UI佈局圖

拿到設計後,先把整體拆分成幾個部分:

  1. “文字輸入框”,使用文字欄位(TextField)元件實現的輸入框。
  2. “狀態指示條”,使用容器(Container)元件實現帶顏色的長方形。

然後就可以開始進行編碼了。

第1步:繪製元件樹

帶彩條的文字欄位的元件樹.png

第2步:實現“文字輸入框”

Flutter的佈局程式碼巢狀非常深,為了程式碼的可讀性,你可以先把一部分沒有依賴的純樣式程式碼提取出來。

import 'package:flutter/material.dart';

// 文字樣式(`TextStyle`)元件,一個不透明的物件,用於確定文字的大小,位置和呈現。
/// 文字域(`TextField`)元件使用的樣式。 final TextStyle _textFieldStyle = TextStyle( // 字型大小。 fontSize: 22.0, // 字母間距。 letterSpacing: 0.78, // 字體系列。 fontFamily: 'BebasNeueBold', // 顏色。 color: const Color(0xFF4A4A4A), ); /// 輸入裝飾(`InputDecoration`)元件的提示樣式(`hintStyle`)屬性值。 final TextStyle _hintStyle = TextStyle
( fontSize: 16.0, color: const Color(0xFF9B9B9B), );

定義一下該自定義元件構建時需要的成員變數,並在預設構建函式中傳遞一下呼叫者提供的引數。

/// 自定義的登入表單欄位元件。
class LoginFormField extends StatefulWidget {
  /// 欄位內的提示文字。
  final String hintText;
  /// 文字欄位的控制器。
  final TextEditingController textEditingController;
  /// 文字欄位的最大長度。
  final int maxLength;
/// 文字欄位的最小長度。 final int minLength; /// 文字欄位長度合理時的回撥函式。 final Function legitimateCallback; /// 文字欄位長度不合理時的回撥函式。 final Function illegalCallback; LoginFormField({ @required this.hintText, this.textEditingController, this.maxLength, this.minLength, this.legitimateCallback, this.illegalCallback, }); @override _LoginFormFieldState createState() => _LoginFormFieldState(); }

先寫好一個垂直(Column)元件,接下來會在垂直(Column)元件中具體實現“文字輸入框”和“狀態指示條”。

/// 與自定義的登入表單欄位元件關聯的狀態子類。
class _LoginFormFieldState extends State<LoginFormField> {
  /// 文字欄位下方的提示顏色。
  Color inputColor;

  @override
  void initState() {
    super.initState();
    inputColor = Color(0xFFC5C5C5);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        // TODO: 實現“文字輸入框”。
        // TODO: 第3步:實現“狀態指示條”。
      ],
    );
  }
}

通過設定文字欄位(TextField)元件的屬性和方法,實現UI圖的效果。同時通過簡單的文字長度來校驗資料是否合法,當前你可以新增更多的校驗邏輯,來滿足業務需求。

        // TODO: 實現“文字輸入框”。
        // 文字欄位(`TextField`)元件,允許使用者使用硬體鍵盤或螢幕鍵盤輸入文字。
        TextField(
          // 控制器屬性,控制正在編輯的文字。
          controller: widget.textEditingController,
          // 游標顏色屬性,繪製游標時使用的顏色。
          cursorColor: const Color(0xFFFF6B47),
          // 游標寬度屬性,游標的厚度,預設是2.0。
          cursorWidth: 2.0,
          // 樣式屬性,用於正在編輯的文字的樣式。
          style: _textFieldStyle,
          // 鍵盤型別屬性,用於編輯文字的鍵盤型別。
          keyboardType: TextInputType.number,
          // 裝飾(`decoration`)屬性,在文字欄位周圍顯示的裝飾。
          // 輸入裝飾(`InputDecoration`)元件。
          decoration: InputDecoration(
            // 邊框屬性,裝飾的容器周圍繪製的形狀。
            border: InputBorder.none,
            // 填充屬性,如果為`true`,則裝飾的容器將填充fillColor顏色。
            filled: true,
            // 填充顏色屬性,填充裝飾容器的顏色。
            fillColor: const Color(0xFFF4F3F4),
            // 是密集屬性,輸入子項是否是密集形式的一部分(即使用較少的垂直空間)。
            isDense: true,
            // 提示樣式屬性,用於提示文字(`hintText`)的樣式。
            hintStyle: _hintStyle,
            // 提示文字屬性,提示欄位接受哪種輸入的文字。
            hintText: widget.hintText,
          ),
          // 在改變屬性,當正在編輯的文字發生更改時呼叫。
          onChanged: (value) {
            // 當前文字欄位中值的長度。
            int fieldValue = value.trim().length;
            if (fieldValue == 0) {
              inputColor = Color(0xFFC5C5C5);
            } else if (fieldValue > widget.maxLength) {
              inputColor = Color(0xFFFF3E44);
            } else {
              inputColor = Color(0xFF00CED2);
            }
            setState(() {});
            // 當前文字欄位中值的長度符合給定範圍時呼叫回撥函式。
            if (fieldValue > widget.minLength-1 && fieldValue < widget.maxLength+1) {
              widget.legitimateCallback();
            } else {
              widget.illegalCallback();
            }
          },
        ),

第3步:實現“狀態指示條”

最後使用容器(Container)元件實現2條簡單的帶顏色的長方形。

        // TODO: 第3步:實現“狀態指示條”。
        Container(
          height: 2.0,
          color: const Color(0xFF242406),
        ),
        Container(
          height: 2.0,
          color: inputColor,
        ),

第4步:還原效果

帶彩條的文字欄位的還原效果