กำหนดค่าช่องข้อความ

TextField ช่วยให้ผู้ใช้ป้อนและแก้ไขข้อความได้ ช่องข้อความที่คุณใช้ได้มี 2 ประเภท ได้แก่ ช่องข้อความตามสถานะและช่องข้อความตามค่า เลือกประเภทที่ต้องการแสดงเนื้อหา ดังนี้

เราขอแนะนำให้ใช้ช่องข้อความตามสถานะ เนื่องจากเป็นวิธีที่สมบูรณ์และเชื่อถือได้มากกว่าในการจัดการสถานะของ TextField ตารางต่อไปนี้สรุปความแตกต่างระหว่างช่องข้อความประเภทต่างๆ และข้อดีที่สำคัญของช่องข้อความตามสถานะ

ฟีเจอร์

ช่องข้อความตามค่า

ช่องข้อความตามสถานะ

สิทธิประโยชน์ตามรัฐ

การจัดการสถานะ

อัปเดตสถานะช่องข้อความด้วย Callback onValueChange คุณมีหน้าที่รับผิดชอบในการอัปเดต value ในรัฐของคุณเองตามการเปลี่ยนแปลงที่รายงานโดย onValueChange

ใช้ออบเจ็กต์ TextFieldState อย่างชัดแจ้งเพื่อจัดการสถานะการป้อนข้อความ (ค่า การเลือก และองค์ประกอบ) ระบบจะจดจำและแชร์สถานะนี้ได้

  • ระบบได้นำ Callback onValueChange ออกแล้ว ซึ่งจะป้องกันไม่ให้คุณใช้ลักษณะการทำงานแบบไม่พร้อมกัน
  • สถานะจะยังคงอยู่แม้จะมีการจัดองค์ประกอบใหม่ การกำหนดค่า และการสิ้นสุดการประมวลผล

การเปลี่ยนรูปแบบภาพ

ใช้ VisualTransformation เพื่อแก้ไขลักษณะที่ข้อความที่แสดงปรากฏ โดยปกติแล้ว วิธีนี้จะจัดการทั้งการจัดรูปแบบอินพุตและเอาต์พุตในขั้นตอนเดียว

ใช้ InputTransformation เพื่อแก้ไขอินพุตของผู้ใช้ก่อนที่จะคอมมิตไปยังสถานะ และใช้ OutputTransformation เพื่อจัดรูปแบบเนื้อหาช่องข้อความโดยไม่เปลี่ยนข้อมูลสถานะที่เกี่ยวข้อง

  • คุณไม่จำเป็นต้องระบุการแมปออฟเซ็ตระหว่างข้อความดิบต้นฉบับกับข้อความที่เปลี่ยนรูปแบบด้วย OutputTransformation อีกต่อไป

ขีดจำกัดของบรรทัด

ยอมรับ singleLine: Boolean, maxLines: Int และ minLines: Int เพื่อควบคุมจำนวนบรรทัด

ใช้ lineLimits: TextFieldLineLimits เพื่อกำหนดค่าจำนวนบรรทัดขั้นต่ำและสูงสุดที่ช่องข้อความสามารถใช้ได้

  • ขจัดความกำกวมเมื่อกำหนดค่าขีดจำกัดบรรทัดโดยระบุพารามิเตอร์ lineLimits ของประเภท TextFieldLineLimits

ช่องข้อความที่ปลอดภัย

ไม่มี

SecureTextField เป็น Composable ที่สร้างขึ้นบนช่องข้อความตามสถานะสำหรับการเขียนช่องรหัสผ่าน

  • ช่วยให้คุณเพิ่มประสิทธิภาพเพื่อความปลอดภัยเบื้องหลัง และมาพร้อมกับ UI ที่กำหนดไว้ล่วงหน้าด้วย textObfuscationMode

หน้านี้อธิบายวิธีใช้ TextField, จัดรูปแบบอินพุต TextField และกำหนดค่าตัวเลือก TextField อื่นๆ เช่น ตัวเลือกแป้นพิมพ์และการเปลี่ยนรูปแบบอินพุตของผู้ใช้แบบเป็นภาพ

เลือกการติดตั้งใช้งาน TextField

การติดตั้งใช้งาน TextField มี 2 ระดับ ได้แก่

  1. TextField คือการติดตั้งใช้งาน Material Design เราขอแนะนำให้เลือกการติดตั้งใช้งานนี้เนื่องจากเป็นไปตามหลักเกณฑ์ของ Material Design
  2. BasicTextField ช่วยให้ผู้ใช้แก้ไขข้อความโดยใช้แป้นพิมพ์ฮาร์ดแวร์หรือแป้นพิมพ์เสมือนได้ แต่ไม่มีการตกแต่ง เช่น คำแนะนำหรือตัวยึดตำแหน่ง

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

ช่องข้อความที่แก้ไขได้ซึ่งมีคำว่า

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

ช่องข้อความที่แก้ไขได้ซึ่งมีเส้นขอบและป้ายกำกับสีม่วง

รูปแบบ TextField

TextField และ BasicTextField มีพารามิเตอร์ทั่วไปหลายรายการที่ใช้ร่วมกันสำหรับการปรับแต่ง โปรดดูรายการทั้งหมดสำหรับ TextField ในซอร์สโค้ด TextField ต่อไปนี้เป็นรายการพารามิเตอร์ที่มีประโยชน์บางส่วนโดยสังเขป

  • 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)
)

TextField แบบหลายบรรทัด โดยมี 2 บรรทัดที่แก้ไขได้พร้อมป้ายกำกับ

เราขอแนะนำให้ใช้ TextField แทน BasicTextField เมื่อการออกแบบของคุณต้องใช้ TextField หรือ OutlinedTextField ของ Material อย่างไรก็ตาม ควรใช้ BasicTextField เมื่อสร้างการออกแบบที่ไม่ต้องการการตกแต่งจากข้อกำหนดของ Material

จัดรูปแบบอินพุตด้วย Brush API

คุณสามารถใช้ Brush API เพื่อจัดรูปแบบขั้นสูงยิ่งขึ้นใน TextField ส่วนต่อไปนี้จะอธิบายวิธีใช้ Brush เพื่อเพิ่มการไล่ระดับสีให้กับอินพุต TextField

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Brush API เพื่อจัดรูปแบบข้อความได้ที่เปิดใช้การจัดรูปแบบขั้นสูงด้วย Brush API

ใช้การไล่ระดับสีโดยใช้ TextStyle

หากต้องการใช้การไล่ระดับสีขณะพิมพ์ภายใน TextField ให้ตั้งค่าแปรงที่เลือกเป็น TextStyle สำหรับ TextField ในตัวอย่างนี้ เราใช้แปรงในตัวที่มีlinearGradientเพื่อดูเอฟเฟกต์การไล่ระดับสีรุ้งเมื่อพิมพ์ข้อความลงใน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)
)

ข้อความที่พิมพ์ในช่องข้อความแสดงเอฟเฟกต์การไล่ระดับสีรุ้ง
รูปที่ 1 เอฟเฟกต์การไล่ระดับสีรุ้งสำหรับเนื้อหา TextField

จัดการสถานะช่องข้อความ

TextField ใช้คลาสตัวเก็บสถานะเฉพาะที่ชื่อ TextFieldState สำหรับเนื้อหาและการเลือก TextFieldState ออกแบบมาให้ยกขึ้นได้ทุกที่ที่เหมาะกับสถาปัตยกรรมของคุณ TextFieldState มีพร็อพเพอร์ตี้หลัก 2 รายการดังนี้

  • initialText: เนื้อหาของ TextField
  • initialSelection: ระบุตำแหน่งของเคอร์เซอร์หรือการเลือก

สิ่งที่ทำให้ TextFieldState แตกต่างจากแนวทางอื่นๆ เช่น Callback ของ onValueChange คือ TextFieldState จะรวมขั้นตอนการป้อนข้อมูลทั้งหมดไว้ด้วยกัน ซึ่งรวมถึงการใช้โครงสร้างข้อมูลสำรองที่ถูกต้อง การแทรกตัวกรองและตัวจัดรูปแบบในบรรทัด รวมถึงการซิงค์การแก้ไขทั้งหมดที่มาจากแหล่งที่มาต่างๆ

ViewModel

คุณสามารถใช้ TextFieldState() เพื่อยกสถานะใน TextField ได้ เราขอแนะนำให้ใช้ฟังก์ชัน rememberTextFieldState() สำหรับกรณีนี้ rememberTextFieldState() จะสร้างอินสแตนซ์ TextFieldState ใน Composable, ตรวจสอบว่าระบบจดจำออบเจ็กต์สถานะ และมีฟังก์ชันการบันทึกและกู้คืนในตัว ดังนี้

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

rememberTextFieldState สามารถมีพารามิเตอร์ว่างหรือมีค่าเริ่มต้นที่ส่งเข้ามาเพื่อแสดงค่าของข้อความในการเริ่มต้น หากมีการส่งค่าอื่นในการจัดองค์ประกอบใหม่ในภายหลัง ค่าของสถานะจะไม่อัปเดต หากต้องการอัปเดตสถานะหลังจากเริ่มต้นแล้ว ให้เรียกใช้เมธอดแก้ไขใน TextFieldState

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

TextField ที่มีข้อความ "ชื่อผู้ใช้" ปรากฏอยู่ภายในช่องข้อความ
รูปที่ 2 TextField โดยมี "ชื่อผู้ใช้" เป็นข้อความเริ่มต้น

แก้ไขข้อความด้วย TextFieldBuffer

TextFieldBuffer ทำหน้าที่เป็นคอนเทนเนอร์ข้อความที่แก้ไขได้ ซึ่งมีฟังก์ชันคล้ายกับ StringBuilder ซึ่งมีทั้งเนื้อหาข้อความและข้อมูลเกี่ยวกับการเลือก

คุณมักจะพบ TextFieldBuffer เป็นขอบเขตตัวรับในฟังก์ชันต่างๆ เช่น TextFieldState.edit, InputTransformation.transformInput หรือ OutputTransformation.transformOutput ในฟังก์ชันเหล่านี้ คุณสามารถอ่านหรืออัปเดต TextFieldBuffer ได้ตามต้องการ หลังจากนั้น ระบบจะคอมมิตการเปลี่ยนแปลงเหล่านี้กับ TextFieldState หรือส่งต่อไปยังไปป์ไลน์การแสดงผลในกรณีของ OutputTransformation

คุณสามารถใช้ฟังก์ชันการแก้ไขมาตรฐาน เช่น append, insert, replace หรือ delete เพื่อแก้ไขเนื้อหาของบัฟเฟอร์ได้ หากต้องการเปลี่ยนสถานะการเลือก ให้ตั้งค่าตัวแปร selection: TextRange โดยตรง หรือใช้ฟังก์ชันยูทิลิตี เช่น placeCursorAtEnd หรือ selectAll การเลือกจะแสดงด้วย TextRange โดยที่ดัชนีเริ่มต้นจะรวมอยู่ด้วยและดัชนีสิ้นสุดจะไม่รวมอยู่ด้วย TextRange ที่มีค่าเริ่มต้นและค่าสิ้นสุดเหมือนกัน เช่น (3, 3) หมายถึงตำแหน่งเคอร์เซอร์ที่ไม่มีการเลือกอักขระ

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, "-")
    }
)

แก้ไขข้อความใน TextFieldState

มีหลายวิธีที่ช่วยให้คุณแก้ไขสถานะได้โดยตรงผ่านตัวแปรสถานะ ดังนี้

  • edit: ช่วยให้คุณแก้ไขเนื้อหาของสถานะและให้ฟังก์ชัน TextFieldBuffer เพื่อให้คุณใช้วิธีการต่างๆ เช่น insert, replace, append และอื่นๆ ได้

    // 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: ล้างข้อความปัจจุบัน แทนที่ด้วยข้อความที่ระบุ และตั้งค่าเคอร์เซอร์ไว้ที่ส่วนท้าย

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

  • clearText: ล้างข้อความทั้งหมด

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

ดูฟังก์ชัน TextFieldState อื่นๆ ได้ที่ข้อมูลอ้างอิง TextFieldState

แก้ไขข้อมูลที่ผู้ใช้ป้อน

ส่วนต่อไปนี้จะอธิบายวิธีแก้ไขข้อมูลที่ผู้ใช้ป้อน การเปลี่ยนรูปแบบอินพุตช่วยให้คุณกรองอินพุต TextField ขณะที่ผู้ใช้กำลังพิมพ์ ส่วนการเปลี่ยนรูปแบบเอาต์พุตจะจัดรูปแบบอินพุตของผู้ใช้ก่อนที่จะแสดงบนหน้าจอ

กรองข้อมูลที่ผู้ใช้ป้อนด้วยการเปลี่ยนรูปแบบอินพุต

การเปลี่ยนรูปแบบอินพุตช่วยให้คุณกรองอินพุตจากผู้ใช้ได้ ตัวอย่างเช่น หาก TextField ของคุณรับหมายเลขโทรศัพท์ของสหรัฐอเมริกา คุณจะยอมรับเฉพาะหมายเลขที่มี 10 หลักเท่านั้น ระบบจะบันทึกผลลัพธ์ของ InputTransformation ไว้ใน TextFieldState

มีตัวกรองในตัวสำหรับกรณีการใช้งาน InputTransformation ทั่วไป หากต้องการจำกัดความยาว ให้โทรหา InputTransformation.maxLength():

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

การเปลี่ยนรูปแบบอินพุตที่กำหนดเอง

InputTransformation เป็นอินเทอร์เฟซฟังก์ชันเดียว เมื่อติดตั้งใช้งาน InputTransformation ที่กำหนดเอง คุณต้องลบล้าง TextFieldBuffer.transformInput:

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

สำหรับหมายเลขโทรศัพท์ ให้เพิ่มการเปลี่ยนรูปแบบอินพุตที่กำหนดเองซึ่งอนุญาตให้พิมพ์เฉพาะตัวเลขลงใน TextField ดังนี้

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

การเปลี่ยนรูปแบบอินพุตเชน

หากต้องการเพิ่มตัวกรองหลายรายการในการป้อนข้อความ ให้เชื่อมโยง InputTransformation โดยใช้ฟังก์ชันส่วนขยาย then ระบบจะเรียกใช้ตัวกรองตามลำดับ แนวทางปฏิบัติแนะนำคือให้ใช้ตัวกรองที่เลือกมากที่สุดก่อนเพื่อหลีกเลี่ยงการเปลี่ยนรูปแบบข้อมูลที่ไม่จำเป็นซึ่งจะถูกกรองออกในท้ายที่สุด

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

หลังจากเพิ่มการเปลี่ยนรูปแบบอินพุตแล้ว อินพุต TextField จะยอมรับตัวเลขสูงสุด 10 หลัก

จัดรูปแบบอินพุตก่อนแสดง

OutputTransformationช่วยให้คุณจัดรูปแบบอินพุตของผู้ใช้ก่อนที่จะแสดงผลบนหน้าจอ การจัดรูปแบบที่ทำผ่าน OutputTransformation จะไม่บันทึกใน TextFieldState ซึ่งต่างจาก InputTransformation จากตัวอย่างหมายเลขโทรศัพท์ก่อนหน้านี้ คุณต้องเพิ่มวงเล็บและขีดกลางในตำแหน่งที่เหมาะสม ดังนี้

หมายเลขโทรศัพท์ของสหรัฐอเมริกาที่จัดรูปแบบอย่างถูกต้องด้วยวงเล็บ ขีดกลาง และดัชนีที่เกี่ยวข้อง
รูปที่ 3 หมายเลขโทรศัพท์ของสหรัฐอเมริกาที่มีการจัดรูปแบบและดัชนีที่สอดคล้องกันอย่างเหมาะสม

นี่เป็นวิธีใหม่ในการจัดการ VisualTransformation ในTextFieldที่อิงตามมูลค่า โดยความแตกต่างที่สำคัญคือคุณไม่จำเป็นต้องคำนวณการแมปออฟเซ็ต

OutputTransformation เป็นอินเทอร์เฟซเมธอดแอบสแตรกรายการเดียว หากต้องการใช้ OutputTransformation ที่กำหนดเอง คุณต้องลบล้างเมธอด transformOutput ดังนี้

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

หากต้องการจัดรูปแบบหมายเลขโทรศัพท์ ให้เพิ่มวงเล็บเปิดที่ดัชนี 0 วงเล็บปิดที่ดัชนี 4 และขีดกลางที่ดัชนี 8 ใน OutputTransformation:

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

จากนั้นเพิ่ม OutputTransformation ลงใน TextField โดยทำดังนี้

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

วิธีการทำงานร่วมกันของการเปลี่ยนรูปแบบ

แผนภาพต่อไปนี้แสดงขั้นตอนตั้งแต่การป้อนข้อความไปจนถึงการเปลี่ยนรูปแบบเป็นเอาต์พุต

ภาพแสดงวิธีที่อินพุตข้อความผ่านการเปลี่ยนรูปแบบก่อนที่จะกลายเป็นเอาต์พุตข้อความ
รูปที่ 4 แผนภาพแสดงวิธีที่อินพุตข้อความผ่านการเปลี่ยนรูปแบบก่อนที่จะกลายเป็นเอาต์พุตข้อความ
  1. ระบบจะรับอินพุตจากแหล่งที่มาของอินพุต
  2. ระบบจะกรองอินพุตผ่าน InputTransformation ซึ่งจะบันทึกไว้ใน TextFieldState
  3. ระบบจะส่งอินพุตผ่าน OutputTransformation เพื่อจัดรูปแบบ
  4. อินพุตจะแสดงใน TextField

ตั้งค่าตัวเลือกแป้นพิมพ์

TextField ช่วยให้คุณตั้งค่าตัวเลือกการกำหนดค่าแป้นพิมพ์ เช่น รูปแบบแป้นพิมพ์ หรือเปิดใช้การแก้ไขอัตโนมัติหากแป้นพิมพ์รองรับ ระบบอาจไม่รับประกันตัวเลือกบางอย่างหากแป้นพิมพ์เสมือนไม่เป็นไปตามตัวเลือกที่ระบุไว้ที่นี่ รายการตัวเลือกแป้นพิมพ์ที่รองรับมีดังนี้

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

แหล่งข้อมูลเพิ่มเติม