Định cấu hình trường văn bản

TextField cho phép người dùng nhập và sửa đổi văn bản. Bạn có thể sử dụng hai loại trường văn bản: trường văn bản dựa trên trạng tháitrường văn bản dựa trên giá trị. Chọn loại nội dung mà bạn muốn hiển thị:

Bạn nên sử dụng các trường văn bản dựa trên trạng thái vì các trường này cung cấp phương pháp quản lý trạng thái của TextField một cách đầy đủ và đáng tin cậy hơn. Bảng sau đây trình bày những điểm khác biệt giữa các loại trường văn bản này, đồng thời nêu các lợi thế chính mà trường văn bản dựa trên trạng thái mang lại:

Tính năng

Trường văn bản dựa trên giá trị

Trường văn bản dựa trên trạng thái

Lợi ích dựa trên trạng thái

Quản lý trạng thái

Cập nhật trạng thái trường văn bản bằng lệnh gọi lại onValueChange. Bạn chịu trách nhiệm cập nhật value ở trạng thái của riêng mình dựa trên những thay đổi do onValueChange báo cáo.

Sử dụng rõ ràng đối tượng TextFieldState để quản lý trạng thái nhập văn bản (giá trị, lựa chọn, thành phần). Trạng thái này có thể được ghi nhớ và chia sẻ.

  • Lệnh gọi lại onValueChange đã bị xoá, khiến bạn không thể giới thiệu các hành vi không đồng bộ.
  • Trạng thái này vẫn tồn tại sau khi kết hợp lại, cấu hình và quá trình bị gián đoạn.

Biến đổi hình ảnh

Sử dụng VisualTransformation để sửa đổi cách hiển thị văn bản. Phương thức này thường xử lý cả định dạng đầu vào và đầu ra trong một bước.

Sử dụng InputTransformation để sửa đổi dữ liệu đầu vào của người dùng trước khi dữ liệu đó được xác nhận cho trạng thái và OutputTransformation để định dạng nội dung trường văn bản mà không thay đổi dữ liệu trạng thái cơ bản.

  • Bạn không cần cung cấp mối liên kết độ dời giữa văn bản thô ban đầu và văn bản đã chuyển đổi bằng OutputTransformation nữa.

Giới hạn dòng

Chấp nhận singleLine: Boolean, maxLines: IntminLines: Int để kiểm soát số dòng.

Sử dụng lineLimits: TextFieldLineLimits để định cấu hình số dòng tối thiểu và tối đa mà trường văn bản có thể chiếm.

  • Loại bỏ sự mơ hồ khi định cấu hình giới hạn dòng bằng cách cung cấp tham số lineLimits thuộc loại TextFieldLineLimits.

Trường văn bản bảo mật

Không áp dụng

SecureTextField là một thành phần kết hợp được tạo dựa trên các trường văn bản dựa trên trạng thái để ghi trường mật khẩu.

  • Cho phép bạn tối ưu hoá cho tính bảo mật và đi kèm với giao diện người dùng được xác định trước bằng textObfuscationMode.

Trang này mô tả cách triển khai TextField, nhập kiểu TextField và định cấu hình các tuỳ chọn TextField khác, chẳng hạn như tuỳ chọn bàn phím và biến đổi trực quan dữ liệu đầu vào của người dùng.

Chọn phương thức triển khai TextField

Có hai cấp độ triển khai TextField:

  1. TextField là cách triển khai Material Design. Bạn nên chọn cách triển khai này vì cách này tuân theo các nguyên tắc Material Design:
  2. BasicTextField cho phép người dùng chỉnh sửa văn bản thông qua bàn phím phần cứng hoặc phần mềm, nhưng không cung cấp đồ trang trí như gợi ý hoặc phần giữ chỗ.

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

Một trường văn bản có thể chỉnh sửa chứa từ

OutlinedTextField(
    state = rememberTextFieldState(),
    label = { Text("Label") }
)

Một trường văn bản có thể chỉnh sửa với đường viền và nhãn màu tím.

Kiểu TextField

TextFieldBasicTextField có chung nhiều thông số phổ biến để tuỳ chỉnh. Danh sách đầy đủ cho TextField có trong mã nguồn TextField. Đây là danh sách không đầy đủ một vài thông số hữu ích:

  • textStyle
  • lineLimits

TextField(
    state = rememberTextFieldState("Hello\nWorld\nInvisible"),
    lineLimits = TextFieldLineLimits.MultiLine(maxHeightInLines = 2),
    placeholder = { Text("") },
    textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
    label = { Text("Enter text") },
    modifier = Modifier.padding(20.dp)
)

Một TextField nhiều dòng, có hai dòng có thể chỉnh sửa cùng với nhãn

Bạn nên sử dụng TextField thay vì BasicTextField khi thiết kế yêu cầu một Material TextField hoặc OutlinedTextField. Tuy nhiên, bạn nên sử dụng BasicTextField khi xây dựng các thiết kế không cần trang trí từ thông số Material.

Nhập kiểu bằng Brush API

Bạn có thể sử dụng Brush API để tạo kiểu nâng cao hơn trong TextField. Phần sau đây mô tả cách bạn có thể sử dụng Bút vẽ để thêm hiệu ứng chuyển màu vào dữ liệu đầu vào TextField.

Để biết thêm thông tin về cách sử dụng Brush API để tạo kiểu văn bản, hãy xem phần Bật tính năng tạo kiểu nâng cao bằng Brush API.

Triển khai hiệu ứng chuyển màu bằng TextStyle

Để triển khai hiệu ứng chuyển màu khi bạn nhập trong TextField, hãy đặt bút vẽ bạn chọn là TextStyle cho TextField. Trong ví dụ này, chúng ta sử dụng một bút vẽ tích hợp với linearGradient để xem hiệu ứng chuyển màu cầu vồng khi văn bản được nhập vào TextField.

val brush = remember {
    Brush.linearGradient(
        colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta)
    )
}
TextField(
    state = rememberTextFieldState(), textStyle = TextStyle(brush = brush)
)

Sử dụng buildAnnotatedString và SpanStyle, cùng với linearGradient, để chỉ tuỳ chỉnh một đoạn văn bản.
Hình 1. Hiệu ứng chuyển màu cầu vồng cho nội dung TextField.

Quản lý trạng thái trường văn bản

TextField sử dụng một lớp phần tử giữ trạng thái chuyên dụng có tên là TextFieldState cho nội dung và lựa chọn hiện tại. TextFieldState được thiết kế để chuyển lên trên bất cứ khi nào phù hợp với cấu trúc của bạn. TextFieldState cung cấp 2 thuộc tính chính:

  • initialText: Nội dung của TextField.
  • initialSelection: Cho biết vị trí hiện tại của con trỏ hoặc lựa chọn.

Điểm khác biệt giữa TextFieldState với các phương pháp khác, chẳng hạn như lệnh gọi lại onValueChange, là TextFieldState đóng gói đầy đủ toàn bộ luồng đầu vào. Điều này bao gồm việc sử dụng đúng cấu trúc dữ liệu sao lưu, trình lọc và trình định dạng nội tuyến, đồng thời đồng bộ hoá tất cả nội dung chỉnh sửa đến từ nhiều nguồn.

Bạn có thể sử dụng TextFieldState() để chuyển trạng thái lên trên trong TextField. Để làm được điều này, bạn nên sử dụng hàm rememberTextFieldState(). rememberTextFieldState() tạo thực thể TextFieldState trong thành phần kết hợp, đảm bảo đối tượng trạng thái được ghi nhớ và cung cấp chức năng lưu và khôi phục tích hợp:

val usernameState = rememberTextFieldState()
TextField(
    state = usernameState,
    lineLimits = TextFieldLineLimits.SingleLine,
    placeholder = { Text("Enter Username") }
)

rememberTextFieldState có thể có tham số trống hoặc có giá trị ban đầu được truyền vào để biểu thị giá trị của văn bản khi khởi chạy. Nếu một giá trị khác được truyền trong quá trình kết hợp lại tiếp theo, thì giá trị của trạng thái sẽ không được cập nhật. Để cập nhật trạng thái sau khi khởi chạy, hãy gọi các phương thức chỉnh sửa trên TextFieldState.

TextField(
    state = rememberTextFieldState(initialText = "Username"),
    lineLimits = TextFieldLineLimits.SingleLine,
)

Một TextField có văn bản Username (Tên người dùng) xuất hiện bên trong trường văn bản.
Hình 2. TextField với "Tên người dùng" làm văn bản ban đầu.

Sửa đổi văn bản bằng TextFieldBuffer

TextFieldBuffer đóng vai trò là vùng chứa văn bản có thể chỉnh sửa, có chức năng tương tự như StringBuilder. Nó chứa cả nội dung văn bản và thông tin về lựa chọn hiện tại.

Bạn thường gặp TextFieldBuffer dưới dạng phạm vi trình nhận trên các hàm như TextFieldState.edit, InputTransformation.transformInput hoặc OutputTransformation.transformOutput. Trong các hàm này, bạn có thể đọc hoặc cập nhật TextFieldBuffer nếu cần. Sau đó, các thay đổi này sẽ được thực hiện với TextFieldState hoặc được chuyển xuống quy trình kết xuất trong trường hợp OutputTransformation.

Bạn có thể sử dụng các hàm chỉnh sửa chuẩn như append, insert, replace hoặc delete để sửa đổi nội dung của vùng đệm. Để thay đổi trạng thái lựa chọn, hãy trực tiếp đặt biến selection: TextRange hoặc sử dụng các hàm tiện ích như placeCursorAtEnd hoặc selectAll. Bản thân lựa chọn được biểu thị bằng một TextRange, trong đó chỉ mục bắt đầu là bao gồm và chỉ mục kết thúc là loại trừ. TextRange có giá trị bắt đầu và kết thúc giống hệt nhau, chẳng hạn như (3, 3), biểu thị vị trí con trỏ không có ký tự nào được chọn.

val phoneNumberState = rememberTextFieldState()

LaunchedEffect(phoneNumberState) {
    phoneNumberState.edit { // TextFieldBuffer scope
        append("123456789")
    }
}

TextField(
    state = phoneNumberState,
    inputTransformation = InputTransformation { // TextFieldBuffer scope
        if (asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    },
    outputTransformation = OutputTransformation {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
)

Chỉnh sửa văn bản trong TextFieldState

Có một số phương thức cho phép bạn chỉnh sửa trạng thái trực tiếp thông qua biến trạng thái:

  • edit: Cho phép bạn chỉnh sửa nội dung trạng thái và cung cấp cho bạn các hàm TextFieldBuffer để bạn có thể sử dụng các phương thức như insert, replace, append, v.v.

    val usernameState = rememberTextFieldState("I love Android")
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    usernameState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    usernameState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

  • setTextAndPlaceCursorAtEnd: Xoá văn bản hiện tại, thay thế bằng văn bản đã cho và đặt con trỏ ở cuối.

    usernameState.setTextAndPlaceCursorAtEnd("I really love Android")
    // textFieldState.text : I really love Android
    // textFieldState.selection : TextRange(21, 21)

  • clearText: Xoá tất cả văn bản.

    usernameState.clearText()
    // textFieldState.text :
    // textFieldState.selection : TextRange(0, 0)

Đối với các hàm TextFieldState khác, hãy xem tài liệu tham khảo về TextFieldState.

Sửa đổi dữ liệu đầu vào của người dùng

Các phần sau đây mô tả cách sửa đổi dữ liệu đầu vào của người dùng. Biến đổi đầu vào cho phép bạn lọc dữ liệu đầu vào TextField trong khi người dùng đang nhập, trong khi biến đổi đầu ra định dạng dữ liệu đầu vào của người dùng trước khi hiển thị trên màn hình.

Lọc dữ liệu đầu vào của người dùng bằng phép biến đổi đầu vào

Biến đổi đầu vào cho phép bạn lọc dữ liệu đầu vào của người dùng. Ví dụ: nếu TextField nhận số điện thoại của Hoa Kỳ, bạn chỉ muốn chấp nhận 10 chữ số. Kết quả của InputTransformation được lưu trong TextFieldState.

Có các bộ lọc tích hợp cho các trường hợp sử dụng InputTransformation phổ biến. Để giới hạn chiều dài, hãy gọi InputTransformation.maxLength():

TextField(
    state = rememberTextFieldState(),
    lineLimits = TextFieldLineLimits.SingleLine,
    inputTransformation = InputTransformation.maxLength(10)
)

Biến đổi dữ liệu đầu vào tuỳ chỉnh

InputTransformation là một giao diện hàm đơn. Khi triển khai InputTransformation tuỳ chỉnh, bạn cần ghi đè TextFieldBuffer.transformInput:

class CustomInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
    }
}

Đối với số điện thoại, hãy thêm một phép biến đổi đầu vào tuỳ chỉnh chỉ cho phép nhập chữ số vào TextField:

class DigitOnlyInputTransformation : InputTransformation {
    override fun TextFieldBuffer.transformInput() {
        if (!TextUtils.isDigitsOnly(asCharSequence())) {
            revertAllChanges()
        }
    }
}

Chuỗi phép biến đổi đầu vào

Để thêm nhiều bộ lọc vào dữ liệu đầu vào văn bản, hãy tạo chuỗi InputTransformation bằng cách sử dụng hàm mở rộng then. Các bộ lọc được thực thi tuần tự. Bạn nên áp dụng các bộ lọc chọn lọc nhất trước tiên để tránh các phép biến đổi không cần thiết đối với dữ liệu cuối cùng sẽ bị lọc ra.

TextField(
    state = rememberTextFieldState(),
    inputTransformation = InputTransformation.maxLength(6)
        .then(CustomInputTransformation()),
)

Sau khi thêm các phép biến đổi đầu vào, đầu vào TextField chấp nhận tối đa 10 chữ số.

Định dạng dữ liệu đầu vào trước khi hiển thị

OutputTransformation cho phép bạn định dạng dữ liệu đầu vào của người dùng trước khi dữ liệu đó được hiển thị trên màn hình. Không giống như InputTransformation, định dạng được thực hiện thông qua OutputTransformation sẽ không được lưu trong TextFieldState. Dựa trên ví dụ về số điện thoại trước đó, bạn cần thêm dấu ngoặc đơn và dấu gạch ngang vào các vị trí thích hợp:

Số điện thoại ở Hoa Kỳ, được định dạng đúng cách bằng dấu ngoặc đơn, dấu gạch ngang và chỉ mục tương ứng.
Hình 3. Số điện thoại ở Hoa Kỳ có định dạng và chỉ mục tương ứng.

Đây là cách cập nhật để xử lý VisualTransformation trong TextField dựa trên giá trị, với điểm khác biệt chính là bạn không phải tính toán các ánh xạ độ dời của chúng.

OutputTransformation là một giao diện phương thức trừu tượng đơn. Để triển khai OutputTransformation tuỳ chỉnh, bạn cần ghi đè phương thức transformOutput:

class CustomOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
    }
}

Để định dạng số điện thoại, hãy thêm dấu ngoặc đơn mở ở chỉ mục 0, dấu ngoặc đơn đóng ở chỉ mục 4 và dấu gạch ngang ở chỉ mục 8 vào OutputTransformation:

class PhoneNumberOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
}

Tiếp theo, hãy thêm OutputTransformation vào TextField:

TextField(
    state = rememberTextFieldState(),
    outputTransformation = PhoneNumberOutputTransformation()
)

Cách các phép biến đổi hoạt động cùng nhau

Sơ đồ sau đây cho thấy quy trình từ nhập văn bản đến biến đổi thành đầu ra:

Hình ảnh trực quan về cách dữ liệu đầu vào văn bản trải qua các phép biến đổi trước khi trở thành dữ liệu đầu ra văn bản.
Hình 4. Biểu đồ cho thấy cách dữ liệu đầu vào văn bản trải qua các phép biến đổi trước khi trở thành dữ liệu đầu ra văn bản.
  1. Nhận dữ liệu đầu vào từ nguồn đầu vào.
  2. Dữ liệu đầu vào được lọc qua InputTransformation, được lưu trong TextFieldState.
  3. Dữ liệu đầu vào được truyền qua OutputTransformation để định dạng.
  4. Dữ liệu đầu vào được trình bày trong TextField.

Đặt tuỳ chọn bàn phím

TextField cho phép bạn đặt các tuỳ chọn cấu hình bàn phím, chẳng hạn như bố cục bàn phím hoặc bật tính năng tự động sửa lỗi nếu được bàn phím hỗ trợ. Một số tuỳ chọn có thể không được đảm bảo nếu bàn phím phần mềm không tuân thủ các tuỳ chọn được cung cấp ở đây. Dưới đây là danh sách các tuỳ chọn bàn phím được hỗ trợ:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

Tài nguyên khác