TextField cho phép người dùng nhập dữ liệu và sửa đổi văn bản. Có hai loại trường văn bản mà bạn có thể sử dụng: trường văn bản dựa trên trạng thái và trường văn bản dựa trên giá trị. Chọn loại nội dung 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 một phương pháp hoàn chỉnh và đáng tin cậy hơn để quản lý trạng thái của TextField. Bảng sau đây trình bày sự khác biệt giữa các loại trường văn bản này và bao gồm 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 theo tiểu bang |
|---|---|---|---|
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 |
Sử dụng rõ ràng đối tượng |
|
Biến đổi hình ảnh |
Sử dụng |
Sử dụng |
|
Giới hạn dòng |
Chấp nhận |
Sử dụng |
|
Trường văn bản bảo mật |
Không áp dụng |
|
|
Trang này mô tả cách bạn có thể triển khai TextField, tạo kiểu cho dữ liệu đầu vào 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à chuyển đổi dữ liệu đầu vào của người dùng một cách trực quan.
Chọn phương thức triển khai TextField
Có hai cấp độ triển khai TextField:
TextFieldlà 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:BasicTextFieldcho phép người dùng chỉnh sửa văn bản bằng bàn phím phần cứng hoặc bàn phím phần mềm, nhưng không cung cấp các thành phần trang trí như gợi ý hoặc phần giữ chỗ.
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
OutlinedTextField( state = rememberTextFieldState(), label = { Text("Label") } )
Kiểu TextField
TextField và BasicTextField cùng có chung nhiều thông số phổ biến để tuỳ chỉnh.
Danh sách đầy đủ cho TextField có sẵn trong
mã nguồn TextField. Đây là danh sách chưa đầy đủ một vài tham số hữu ích:
textStylelineLimits
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) )
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, 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 cấu hình hạn mức cho dòng
Các thành phần kết hợp TextField hỗ trợ thao tác cuộn dọc theo một trục duy nhất. Hành vi cuộn được xác định bằng tham số lineLimits. TextField được định cấu hình cho một dòng sẽ cuộn theo chiều ngang, trong khi TextField nhiều dòng sẽ cuộn theo chiều dọc.
Sử dụng TextFieldLineLimits để chọn cấu hình dòng phù hợp cho TextField:
TextField( state = rememberTextFieldState(), lineLimits = TextFieldLineLimits.SingleLine )
Cấu hình SingleLine có các đặc điểm sau:
- Văn bản không bao giờ xuống dòng và không cho phép dòng mới.
TextFieldluôn có chiều cao cố định.- Nếu văn bản bị tràn, văn bản sẽ cuộn theo chiều ngang.
TextField( state = rememberTextFieldState("Hello\nWorld\nHello\nWorld"), lineLimits = TextFieldLineLimits.MultiLine(1, 4) )
Cấu hình MultiLine có các đặc điểm sau:
- Chấp nhận hai tham số:
minHeightInLinesvàmaxHeightInLines. - Trường văn bản có chiều cao tối thiểu là
minHeightInLines. - Nếu văn bản bị tràn, văn bản sẽ xuống dòng.
- Nếu văn bản cần nhiều dòng hơn, thì trường này sẽ tăng lên cho đến khi đạt chiều cao
maxHeightInLinesvà cuộn theo chiều dọc.
Tạo kiểu cho dữ liệu đầu vào 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 Brush để thêm dải 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 cho văn bản, hãy xem bài viết Bật tính năng tạo kiểu nâng cao bằng Brush API.
Triển khai độ dốc màu bằng TextStyle
Để triển khai độ dốc màu khi bạn nhập trong TextField, hãy đặt bút vẽ mà bạn chọn làm TextStyle cho TextField. Trong ví dụ này, chúng ta sử dụng một bút vẽ tích hợp sẵn có 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) )
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 của lớp đó. TextFieldState được thiết kế để nâng lên bất cứ nơi nào phù hợp trong cấu trúc của bạn. Có 2 thuộc tính chính do TextFieldState cung cấp:
initialText: Nội dung củaTextField.initialSelection: Cho biết vị trí của con trỏ hoặc vùng chọn.
Điểm khác biệt giữa TextFieldState và 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 hoàn toàn toàn bộ luồng đầu vào. Việc này bao gồm việc sử dụng cấu trúc dữ liệu sao lưu chính xác, bộ lọc cùng trình định dạng cùng dòng, cũng như đồ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 việc này, bạn nên sử dụng hàm rememberTextFieldState().
rememberTextFieldState() tạo thực thể TextFieldState trong composable, đảm bảo đối tượng state được ghi nhớ, đồng thời cung cấp chức năng lưu và khôi phục tích hợp sẵn:
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, )
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. Trạng thái này lưu giữ cả nội dung văn bản và thông tin về lựa chọn.
Bạn thường gặp TextFieldBuffer dưới dạng phạm vi 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 đó, những thay đổi này sẽ được cam kết với TextFieldState hoặc được chuyển đến 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 tiêu 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 hiệu dụng 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à không bao gồm.
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("1234567890") TextField( state = phoneNumberState, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Phone ), inputTransformation = InputTransformation.maxLength(10).then { 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àmTextFieldBufferđể bạn có thể sử dụng các phương thức nhưinsert,replace,append, v.v.// Initial textFieldState text passed in is "I love Android" // textFieldState.text : I love Android // textFieldState.selection: TextRange(14, 14) textFieldState.edit { insert(14, "!") } // textFieldState.text : I love Android! // textFieldState.selection: TextRange(15, 15) textFieldState.edit { replace(7, 14, "Compose") } // textFieldState.text : I love Compose! // textFieldState.selection: TextRange(15, 15) textFieldState.edit { append("!!!") } // textFieldState.text : I love Compose!!!! // textFieldState.selection: TextRange(18, 18) textFieldState.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.textFieldState.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.textFieldState.clearText() // textFieldState.text : // textFieldState.selection : TextRange(0, 0)
Để biết 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 dữ liệu đầ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, còn biến đổi dữ liệu đầ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 các phép biến đổi dữ liệu đầu vào
Phép biến đổi dữ liệu đầ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 của bạn nhận số điện thoại của Hoa Kỳ, thì 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 sẵn cho các trường hợp sử dụng InputTransformation phổ biến. Để giới hạn
độ dài, hãy gọi InputTransformation.maxLength():
TextField( state = rememberTextFieldState(), lineLimits = TextFieldLineLimits.SingleLine, inputTransformation = InputTransformation.maxLength(10) )
Quy tắc chuyể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 dữ liệu đầ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 (!asCharSequence().isDigitsOnly()) { revertAllChanges() } } }
Phép biến đổi đầu vào chuỗi
Để thêm nhiều bộ lọc vào dữ liệu đầu vào dạng văn bản, hãy liên kết InputTransformation bằng hàm mở rộng then. Các bộ lọc được thực thi tuần tự. Theo phương pháp hay nhất, hãy áp dụng các bộ lọc có tính chọn lọc cao nhất trước để tránh các phép biến đổi không cần thiết trên dữ liệu mà 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 dữ liệu đầu vào, dữ liệu đầ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 đó 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 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 những vị trí thích hợp:
Đây là cách mới để 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 cần phải tính toán các mối liên kết bù trừ của chúng.
OutputTransformation là một giao diện phương thức trừu tượng duy nhất. Để 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 quy tắc chuyển đổi phối hợp hoạt động
Sơ đồ sau đây cho thấy quy trình từ dữ liệu đầu vào dạng văn bản đến quá trình biến đổi thành dữ liệu đầu ra:
- Dữ liệu đầu vào được nhận từ nguồn đầu vào.
- Dữ liệu đầu vào được lọc thông qua một
InputTransformation, được lưu trong TextFieldState. - Dữ liệu đầu vào được truyền qua
OutputTransformationđể định dạng. - Thông tin đầu vào được trình bày trong
TextField.
Đặt tuỳ chọn bàn phím
TextField cho phép bạn cài đặ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ợ:
capitalizationautoCorrectkeyboardTypeimeAction
Lớp KeyboardOptions hiện có chứa một tham số boolean mới là showKeyboardOnFocus. Bạn dùng tham số này riêng cho các thành phần TextField được tích hợp với TextFieldState. Tuỳ chọn này chi phối hành vi của bàn phím phần mềm khi TextField nhận được tiêu điểm thông qua các phương tiện khác ngoài hoạt động tương tác trực tiếp của người dùng (ví dụ: theo phương thức lập trình).
Khi KeyboardOptions.showKeyboardOnFocus được đặt thành true, bàn phím phần mềm sẽ không tự động xuất hiện nếu TextField nhận được tiêu điểm một cách gián tiếp. Trong những trường hợp như vậy, người dùng phải nhấn rõ ràng vào chính TextField để hiện bàn phím.
Xác định logic tương tác với bàn phím
Nút hành động trên bàn phím phần mềm của Android cho phép phản hồi tương tác trong ứng dụng của bạn. Để biết thêm thông tin về cách định cấu hình nút hành động, hãy xem phần Đặt tuỳ chọn bàn phím.
Để xác định điều gì xảy ra khi người dùng nhấn vào nút hành động này, hãy sử dụng tham số onKeyboardAction. Tham số này chấp nhận một giao diện chức năng không bắt buộc có tên là KeyboardActionHandler. Giao diện KeyboardActionHandler chứa một phương thức duy nhất là onKeyboardAction(performDefaultAction: () -> Unit).
Bằng cách cung cấp phương thức triển khai cho phương thức onKeyboardAction này, bạn có thể
giới thiệu logic tuỳ chỉnh thực thi khi người dùng nhấn nút hành động của bàn phím.
Một số loại thao tác chuẩn trên bàn phím có các hành vi mặc định được tích hợp sẵn.
Ví dụ: việc chọn ImeAction.Next hoặc ImeAction.Previous làm loại hành động sẽ chuyển tiêu điểm sang trường nhập dữ liệu tiếp theo hoặc trước đó theo mặc định. Tương tự, nút hành động được đặt thành ImeAction.Done thường sẽ đóng bàn phím phần mềm. Các chức năng mặc định này được thực thi tự động và không yêu cầu bạn cung cấp KeyboardActionHandler.
Bạn cũng có thể triển khai hành vi tuỳ chỉnh ngoài các hành động mặc định này.
Khi bạn cung cấp KeyboardActionHandler, phương thức onKeyboardAction của nó sẽ nhận được hàm performDefaultAction. Bạn có thể gọi hàm performDefaultAction() này tại bất kỳ thời điểm nào trong logic tuỳ chỉnh để kích hoạt hành vi mặc định chuẩn liên kết với thao tác IME hiện tại.
TextField( state = textFieldViewModel.usernameState, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), onKeyboardAction = { performDefaultAction -> textFieldViewModel.validateUsername() performDefaultAction() } )
Đoạn mã này minh hoạ một trường hợp sử dụng phổ biến trên màn hình đăng ký có trường tên người dùng. Đối với trường này, ImeAction.Next được chọn cho nút hành động trên bàn phím. Lựa chọn này giúp bạn di chuyển nhanh chóng và liền mạch đến trường mật khẩu tiếp theo.
Ngoài thao tác điều hướng tiêu chuẩn này, bạn cần bắt đầu một quy trình xác thực trong nền cho tên người dùng khi người dùng tiếp tục nhập mật khẩu. Để đảm bảo rằng hành vi chuyển đổi tiêu điểm mặc định vốn có của ImeAction.Next được giữ lại cùng với logic xác thực tuỳ chỉnh này, hàm performDefaultAction() sẽ được gọi. Việc gọi performDefaultAction() sẽ kích hoạt ngầm hệ thống quản lý tiêu điểm cơ bản để di chuyển tiêu điểm đến phần tử trên giao diện người dùng thích hợp tiếp theo, duy trì luồng điều hướng dự kiến.
Tạo trường mật khẩu bảo mật
SecureTextField là một composable được xây dựng dựa trên các trường văn bản dựa trên state để viết trường mật khẩu. Bạn nên sử dụng SecureTextField để tạo trường văn bản mật khẩu, vì trường này ẩn dữ liệu đầu vào của ký tự theo mặc định và tắt thao tác cắt và sao chép.
SecureTextField có textObfuscationMode, giúp kiểm soát cách người dùng nhìn thấy
ký tự nhập vào. textObfuscationMode có các tuỳ chọn sau:
Hidden: Ẩn tất cả dữ liệu đầu vào. Hành vi mặc định trên nền tảng máy tính.
Visible: Cho thấy tất cả dữ liệu đầu vào.
RevealLastTyped: Ẩn tất cả dữ liệu đầu vào ngoại trừ ký tự cuối cùng. Hành vi mặc định trên thiết bị di động.
Tài nguyên khác
- Tự động định dạng số điện thoại trong trường văn bản
- Hiện hoặc ẩn mật khẩu dựa trên nút bật/tắt của người dùng
- Xác thực dữ liệu đầu vào khi người dùng nhập