Flutter TextField詳解 | 掘金技術徵文

Realank Liu發表於2018-08-09

實現TextField說簡單也簡單,說有坑,坑也不小,下面從易到難介紹一下使用

1.最簡單的就是無引數呼叫構造方法:

TextField()
複製程式碼

Flutter TextField詳解 | 掘金技術徵文

2.光有輸入框還不行,還得獲取其中的內容,所以需要傳遞controller:

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField(TextEditingController controller) {
    return TextField(
      controller: controller,
    );
  }

  @override
  Widget build(BuildContext context) {
    final controller = TextEditingController();
    controller.addListener(() {
      print('input ${controller.text}');
    });
    return Scaffold(
      appBar: AppBar(
        title: Text('TextField'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: buildTextField(controller),
      ),
    );
  }
}
複製程式碼

我通過給controller新增通知來獲取TextField的值,這種使用場景不一定合適,更多的時候是在點選按鈕的時候直接讀取controller.text的值

3.另外TextFiled還有一下小的屬性:

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

class TextFieldPage extends StatelessWidget {
  Widget buildTextField(TextEditingController controller) {
    return TextField(
      controller: controller,
      maxLength: 30,//最大長度,設定此項會讓TextField右下角有一個輸入數量的統計字串
      maxLines: 1,//最大行數
      autocorrect: true,//是否自動更正
      autofocus: true,//是否自動對焦
      obscureText: true,//是否是密碼
      textAlign: TextAlign.center,//文字對齊方式
      style: TextStyle(fontSize: 30.0, color: Colors.blue),//輸入文字的樣式
      inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],//允許的輸入格式
      onChanged: (text) {//內容改變的回撥
        print('change $text');
      },
      onSubmitted: (text) {//內容提交(按回車)的回撥
        print('submit $text');
      },
      enabled: true,//是否禁用
    );
  }

  @override
  Widget build(BuildContext context) {
    final controller = TextEditingController();
    controller.addListener(() {
      print('input ${controller.text}');
    });
    return Scaffold(
      appBar: AppBar(
        title: Text('TextField'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: buildTextField(controller),
      ),
    );
  }
}
複製程式碼

Flutter TextField詳解 | 掘金技術徵文

4.接著我還能顯示placeholder

decoration可以給TextField新增裝飾

TextField(
      decoration:
          InputDecoration(fillColor: Colors.blue.shade100, filled: true, labelText: 'Hello'),
    );
複製程式碼

fillColor設定填充顏色,labelText設定標籤文字,這個標籤在沒有輸入的時候是佔滿輸入框的,當輸入聚焦以後,就會縮小到輸入框左上角:

Flutter TextField詳解 | 掘金技術徵文
Flutter TextField詳解 | 掘金技術徵文

TextField(
      decoration: InputDecoration(
          fillColor: Colors.blue.shade100, filled: true, hintText: 'Hello', errorText: 'error'),
    );
複製程式碼

hintText就是普通的placeholder,輸入後就不顯示了,errorText是錯誤提示

Flutter TextField詳解 | 掘金技術徵文
Flutter TextField詳解 | 掘金技術徵文

5.還能顯示一些別的裝飾

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return TextField(
      decoration: InputDecoration(
          fillColor: Colors.blue.shade100,
          filled: true,
          helperText: 'help',
          prefixIcon: Icon(Icons.local_airport),
          suffixText: 'airport'),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TextField'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: buildTextField(),
      ),
    );
  }
}

複製程式碼

Flutter TextField詳解 | 掘金技術徵文

6.這些還不過癮,我不喜歡這個安卓風格的下面的裝飾線,我想變成圓角矩形的邊框

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return TextField(
      decoration: InputDecoration(
          contentPadding: EdgeInsets.all(10.0),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(15.0),
//            borderSide: BorderSide(color: Colors.red, width: 3.0, style: BorderStyle.solid)//沒什麼卵效果
          )),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TextField'),
      ),
      body: Container(
        color: Colors.blue.shade100,
        child: Padding(
          padding: const EdgeInsets.all(30.0),
          child: buildTextField(),
        ),
      ),
    );
  }
}

複製程式碼

Flutter TextField詳解 | 掘金技術徵文

7.改變裝飾線顏色

無論是下面的裝飾線,還是矩形邊框裝飾線,對焦後顯示的顏色,都是主題顏色的primaryColor,失去焦點以後就是黑色,這顯然不能滿足自定義的需求,但是通過各種努力發現,改變邊框顏色很困難,最後發現了這個答案:https://stackoverflow.com/questions/49600139/how-to-change-textfield-underline-color

所以正確的設定邊框顏色的方式是這樣的:

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return Theme(
      data: new ThemeData(primaryColor: Colors.red, hintColor: Colors.blue),
      child: TextField(
        decoration: InputDecoration(
            contentPadding: EdgeInsets.all(10.0),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(15.0),
//            borderSide: BorderSide(color: Colors.red, width: 3.0, style: BorderStyle.solid)//沒什麼卵效果
            )),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TextField'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(30.0),
        child: buildTextField(),
      ),
    );
  }
}
複製程式碼

Flutter TextField詳解 | 掘金技術徵文

8.改變邊框的粗細

這些TextField的decoration徹底不能滿足要求了,需要重構成這種方式:


import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return Container(
      padding: const EdgeInsets.all(8.0),
      alignment: Alignment.center,
      height: 60.0,
      decoration: new BoxDecoration(
          color: Colors.blueGrey,
          border: new Border.all(color: Colors.black54, width: 4.0),
          borderRadius: new BorderRadius.circular(12.0)),
      child: new TextFormField(
        decoration: InputDecoration.collapsed(hintText: 'hello'),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('TextField'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(30.0),
        child: buildTextField(),
      ),
    );
  }
}

複製程式碼

Flutter TextField詳解 | 掘金技術徵文

InputDecoration.collapsed可以禁用裝飾線,而是使用外面包圍的Container的裝飾線

致此,所有的輸入框的坑都趟完了,歡迎大家多多交流

從 0 到 1:我的 Flutter 技術實踐 | 掘金技術徵文,徵文活動正在進行中

相關文章