จัดรูปแบบย่อหน้า

หน้านี้จะอธิบายวิธีจัดรูปแบบข้อความสำหรับย่อหน้า หากต้องการกำหนดการจัดรูปแบบระดับย่อหน้า คุณสามารถกําหนดค่าพารามิเตอร์ เช่น textAlign และ lineHeight หรือกําหนด ParagraphStyle ของคุณเอง

ตั้งค่าการจัดข้อความ

พารามิเตอร์ textAlign ช่วยให้คุณตั้งค่าการจัดแนวแนวนอนของข้อความภายในพื้นที่ผิวแบบคอมโพสิเบิล Text

โดยค่าเริ่มต้น Text จะเลือกการจัดแนวข้อความตามปกติโดยขึ้นอยู่กับค่าเนื้อหา ดังนี้

  • ขอบด้านซ้ายของคอนเทนเนอร์ Text สำหรับตัวอักษรจากซ้ายไปขวา เช่น ละติน ซีริลลิก หรือฮันกึล
  • ขอบด้านขวาของคอนเทนเนอร์ Text สำหรับตัวอักษรจากขวาไปซ้าย เช่น อาหรับหรือฮีบรู

@Composable
fun CenterText() {
    Text(
        "Hello World", textAlign = TextAlign.Center, modifier = Modifier.width(150.dp)
    )
}

คํา

หากต้องการกำหนดการจัดแนวข้อความของคอมโพสิชัน Text ด้วยตนเอง ให้ใช้ TextAlign.Start และ TextAlign.End แทน TextAlign.Left และ TextAlign.Right ตามลำดับ เนื่องจากจะแสดงที่ขอบด้านขวาของคอมโพสิชัน Text โดยขึ้นอยู่กับการวางแนวข้อความภาษาที่ต้องการ เช่น TextAlign.End จะจัดชิดทางด้านขวาสำหรับข้อความภาษาฝรั่งเศสและทางด้านซ้ายสำหรับข้อความภาษาอาหรับ แต่ TextAlign.Right จะจัดชิดทางด้านขวาไม่ว่าจะใช้ตัวอักษรใดก็ตาม

เพิ่มรูปแบบหลายรูปแบบในย่อหน้า

หากต้องการเพิ่มหลายสไตล์ในย่อหน้า ให้ใช้ ParagraphStyle ใน AnnotatedString ซึ่งจะใส่คำอธิบายประกอบด้วยสไตล์ของคำอธิบายประกอบแบบกำหนดเองได้ เมื่อทำเครื่องหมายข้อความบางส่วนด้วย ParagraphStyle แล้ว ระบบจะแยกข้อความส่วนนั้นออกจากข้อความที่เหลือราวกับว่ามีการตัดบรรทัดขึ้นต้นและลงท้าย

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มรูปแบบหลายรูปแบบในข้อความได้ที่หัวข้อเพิ่มรูปแบบหลายรูปแบบในข้อความ

AnnotatedString มีตัวสร้างที่ปลอดภัยต่อประเภทเพื่อช่วยให้คุณสร้าง buildAnnotatedString ได้ง่ายขึ้น ข้อมูลโค้ดต่อไปนี้ใช้ buildAnnotatedString เพื่อตั้งค่า ParagraphStyle

@Composable
fun ParagraphStyle() {
    Text(
        buildAnnotatedString {
            withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
                withStyle(style = SpanStyle(color = Color.Blue)) {
                    append("Hello\n")
                }
                withStyle(
                    style = SpanStyle(
                        fontWeight = FontWeight.Bold, color = Color.Red
                    )
                ) {
                    append("World\n")
                }
                append("Compose")
            }
        }
    )
}

ย่อหน้า 3 ย่อหน้าใน 3 รูปแบบที่แตกต่างกัน ได้แก่ สีน้ำเงิน สีแดง ตัวหนา และสีดําธรรมดา

ปรับความสูงของบรรทัดและการเว้นวรรค

includeFontPadding เป็นพร็อพเพอร์ตี้เดิมที่เพิ่มการเยื้องเพิ่มเติมตามเมตริกแบบอักษรที่ด้านบนของบรรทัดแรกและด้านล่างของบรรทัดสุดท้ายของข้อความ ตั้งแต่ BOM ของ Compose เวอร์ชัน 2024.01.01 เป็นต้นไป ระบบจะตั้งค่า includeFontPadding เป็น false โดยค่าเริ่มต้น ซึ่งจะทำให้เลย์เอาต์ข้อความเริ่มต้นสอดคล้องกับเครื่องมือออกแบบทั่วไปมากขึ้น

ความสามารถในการกําหนดค่า lineHeight ไม่ใช่สิ่งใหม่ ฟีเจอร์นี้พร้อมใช้งานมาตั้งแต่ Android Q คุณสามารถกําหนดค่า lineHeight สําหรับ Text ได้โดยใช้พารามิเตอร์ lineHeight ซึ่งจะกระจายความสูงของบรรทัดในแต่ละบรรทัดของข้อความ จากนั้นใช้ LineHeightStyle API ใหม่เพื่อกำหนดค่าเพิ่มเติมเกี่ยวกับวิธีจัดแนวข้อความนี้ภายในพื้นที่ว่าง และนำเว้นวรรคออก

คุณอาจต้องปรับ lineHeight โดยใช้หน่วยข้อความ "em" (ขนาดแบบอักษรสัมพัทธ์) แทน "sp" (พิกเซลที่ปรับขนาด) เพื่อให้แม่นยำยิ่งขึ้น ดูข้อมูลเพิ่มเติมเกี่ยวกับการเลือกหน่วยข้อความที่เหมาะสมได้ที่ TextUnit

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

Text(
    text = text,
    style = LocalTextStyle.current.merge(
        TextStyle(
            lineHeight = 2.5.em,
            platformStyle = PlatformTextStyle(
                includeFontPadding = false
            ),
            lineHeightStyle = LineHeightStyle(
                alignment = LineHeightStyle.Alignment.Center,
                trim = LineHeightStyle.Trim.None
            )
        )
    )
)

นอกจากการปรับ lineHeight แล้ว ตอนนี้คุณยังจัดกึ่งกลางและจัดรูปแบบข้อความเพิ่มเติมได้โดยใช้การกำหนดค่ากับ LineHeightStyle API เวอร์ชันทดลอง: LineHeightStyle.Alignment และ LineHeightStyle.Trim (ต้องตั้งค่า includeFontPadding เป็น false เพื่อให้การตัดข้อความทำงาน) การจัดแนวและการตัดจะใช้พื้นที่ที่วัดระหว่างบรรทัดข้อความเพื่อกระจายข้อความไปยังบรรทัดทั้งหมดอย่างเหมาะสมยิ่งขึ้น ซึ่งรวมถึงบรรทัดข้อความเดียวและบรรทัดแรกของบล็อกข้อความ

LineHeightStyle.Alignment กำหนดวิธีจัดแนวบรรทัดในพื้นที่ว่างที่ความสูงของบรรทัดระบุ ในบรรทัดแต่ละบรรทัด คุณสามารถจัดแนวข้อความให้อยู่ด้านบน ด้านล่าง ตรงกลาง หรือตามสัดส่วน LineHeightStyle.Trim จากนั้นจะช่วยให้คุณเลือกที่จะเว้นวรรคหรือนำเว้นวรรคส่วนเกินที่ด้านบนของบรรทัดแรกและด้านล่างของบรรทัดสุดท้ายของข้อความออกได้ ซึ่งสร้างขึ้นจากการปรับเปลี่ยน lineHeight และการจัดแนว ตัวอย่างต่อไปนี้แสดงลักษณะของข้อความหลายบรรทัดที่มีการกำหนดค่า LineHeightStyle.Trim แบบต่างๆ เมื่อจัดแนวเป็นกึ่งกลาง (LineHeightStyle.Alignment.Center)

รูปภาพแสดง LineHeightStyle.Trim.None รูปภาพแสดง LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
รูปภาพแสดง LineHeightStyle.Trim.FirstLineTop รูปภาพแสดง LineHeightStyle.Trim.LastLineBottom
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom
เท่านั้น

ดูข้อมูลเพิ่มเติมเกี่ยวกับบริบทของการเปลี่ยนแปลงนี้ วิธีการทํางานของ includeFontPadding ในระบบมุมมอง และการเปลี่ยนแปลงที่เกิดขึ้นกับเครื่องมือเขียนและ LineHeightStyle API ใหม่ได้ในบล็อกโพสต์การแก้ไขระยะห่างจากขอบของแบบอักษรในเครื่องมือเขียนข้อความ

แทรกตัวแบ่งบรรทัด

LineBreak API กําหนดเกณฑ์ในการแยกข้อความเป็นหลายบรรทัด คุณสามารถระบุประเภทการแบ่งบรรทัดที่ต้องการในTextStyleบล็อกของคอมโพสิชัน Text ประเภทการแบ่งบรรทัดที่กำหนดล่วงหน้ามีดังนี้

  • Simple — การขึ้นบรรทัดใหม่แบบพื้นฐานที่รวดเร็ว แนะนำสำหรับช่องป้อนข้อความ
  • Heading — การแบ่งบรรทัดด้วยกฎการแบ่งที่ผ่อนปรนมากขึ้น เหมาะสำหรับข้อความสั้นๆ เช่น ชื่อ
  • Paragraph — การขึ้นบรรทัดใหม่ช้าลงแต่มีคุณภาพสูงขึ้นเพื่อให้อ่านง่ายขึ้น แนะนำสำหรับข้อความจำนวนมาก เช่น ย่อหน้า

ข้อมูลโค้ดต่อไปนี้ใช้ทั้ง Simple และ Paragraph เพื่อระบุลักษณะการแบ่งบรรทัดในบล็อกข้อความยาว

TextSample(
    samples = mapOf(
        "Simple" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Simple
                )
            )
        },
        "Paragraph" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph
                )
            )
        }
    )
)

บล็อกข้อความที่แสดงกลยุทธ์การแบ่งบรรทัดแบบง่ายเทียบกับบล็อกข้อความที่มีกลยุทธ์การแบ่งที่เพิ่มประสิทธิภาพตามย่อหน้า บล็อกข้อความที่มีกลยุทธ์การแบ่งบรรทัดแบบง่ายจะมีความยาวบรรทัดแตกต่างกันไปมากกว่า
รูปที่ 1 บล็อกข้อความที่มีกลยุทธ์การแบ่งบรรทัดแบบง่าย (ด้านบน) เทียบกับบล็อกข้อความที่มีการแบ่งบรรทัดแบบเพิ่มประสิทธิภาพย่อหน้า (ด้านล่าง)

ในเอาต์พุตด้านบน โปรดสังเกตว่าลักษณะการแบ่งบรรทัด Paragraph ให้ผลลัพธ์ที่สมดุลกว่าการแบ่งบรรทัด Simple

ปรับแต่งการขึ้นบรรทัดใหม่

นอกจากนี้ คุณยังสร้างการกำหนดค่า LineBreak ของคุณเองได้ด้วยพารามิเตอร์ Strategy Strategy อาจเป็นค่าใดก็ได้ต่อไปนี้

  • Balanced — พยายามปรับความยาวบรรทัดของข้อความให้สมดุล รวมถึงใช้การแบ่งคำอัตโนมัติหากเปิดใช้ แนะนำสำหรับหน้าจอขนาดเล็ก เช่น นาฬิกา เพื่อแสดงข้อความได้มากที่สุด
  • HighQuality — เพิ่มประสิทธิภาพย่อหน้าเพื่อให้อ่านข้อความได้ง่ายขึ้น รวมถึงการแบ่งคำหากเปิดใช้ (ควรเป็นค่าเริ่มต้นสำหรับทุกอย่างที่ไม่ใช่ Balanced หรือ Simple)
  • Simple — กลยุทธ์พื้นฐานที่รวดเร็ว หากเปิดใช้ ระบบจะแบ่งคำเฉพาะสำหรับคำที่เกินบรรทัด มีประโยชน์สำหรับการแก้ไขข้อความเพื่อหลีกเลี่ยงการเปลี่ยนตำแหน่งขณะพิมพ์

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

TextSample(
    samples = mapOf(
        "Balanced" to {
            val smallScreenAdaptedParagraph =
                LineBreak.Paragraph.copy(strategy = LineBreak.Strategy.Balanced)
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(200.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = smallScreenAdaptedParagraph
                )
            )
        },
        "Default" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(200.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default
            )
        }
    )
)

ย่อหน้าที่มีกลยุทธ์การแบ่งบรรทัดที่สมดุลและย่อหน้าที่มีการจัดรูปแบบโดยไม่มีกลยุทธ์ ย่อหน้าที่มีกลยุทธ์การแบ่งบรรทัดอย่างสมดุลจะมีความยาวบรรทัดที่สอดคล้องกันมากกว่าค่าเริ่มต้น
รูปที่ 2 ย่อหน้าที่มีการจัดรูปแบบด้วยBalancedกลยุทธ์การแบ่งบรรทัด (ด้านบน) เทียบกับย่อหน้าที่มีการจัดรูปแบบโดยไม่มีกลยุทธ์การแบ่งบรรทัด

ข้อควรพิจารณาเกี่ยวกับ CJK

นอกจากนี้ คุณยังปรับแต่ง LineBreak ด้วย API ของ Strictness และ WordBreak ได้ด้วย ซึ่งออกแบบมาเพื่อภาษา CJK โดยเฉพาะ คุณอาจไม่เห็นผลของ API เหล่านี้ในภาษาที่ไม่ใช่ CJK เสมอไป โดยรวมแล้ว ระบบจะกำหนดกฎการแบ่งบรรทัดตามภาษา

Strictness อธิบายความเข้มงวดของการแบ่งบรรทัดด้วยพร็อพเพอร์ตี้ต่อไปนี้

  • Default — กฎการแบ่งบรรทัดเริ่มต้นสำหรับภาษา อาจสอดคล้องกับ Normal หรือ Strict
  • Loose — กฎที่มีข้อจำกัดน้อยที่สุด เหมาะสำหรับบรรทัดสั้นๆ
  • Normal — กฎที่พบบ่อยที่สุดสำหรับการแบ่งบรรทัด
  • Strict — กฎที่เข้มงวดที่สุดสำหรับการแบ่งบรรทัด

WordBreak กำหนดวิธีแทรกการขึ้นบรรทัดใหม่ภายในคำด้วยพร็อพเพอร์ตี้ต่อไปนี้

  • Default — กฎการแบ่งบรรทัดเริ่มต้นสำหรับภาษา
  • Phrase — ตัวแบ่งบรรทัดจะแบ่งตามวลี

ข้อมูลโค้ดต่อไปนี้ใช้การตั้งค่าStrictความเข้มงวดและการแบ่งคำ Phrase สำหรับข้อความภาษาญี่ปุ่น

val customTitleLineBreak = LineBreak(
    strategy = LineBreak.Strategy.HighQuality,
    strictness = LineBreak.Strictness.Strict,
    wordBreak = LineBreak.WordBreak.Phrase
)
Text(
    text = "あなたに寄り添う最先端のテクノロジー。",
    modifier = Modifier.width(250.dp),
    fontSize = 14.sp,
    style = TextStyle.Default.copy(
        lineBreak = customTitleLineBreak
    )
)

ข้อความภาษาญี่ปุ่นที่มีการตั้งค่าความเข้มงวดและการแบ่งคำเทียบกับข้อความเริ่มต้น
รูปที่ 3 ข้อความที่จัดรูปแบบด้วยการตั้งค่า Strictness และ WordBreak (ด้านบน) เทียบกับข้อความที่จัดรูปแบบด้วย LineBreak.Heading เท่านั้น (ด้านล่าง)

ใส่ขีดกลางในข้อความที่แบ่งออกเป็นหลายบรรทัด

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

ระบบจะไม่เปิดใช้การแบ่งบรรทัดโดยค่าเริ่มต้น หากต้องการเปิดใช้การแบ่งบรรทัด ให้เพิ่ม Hyphens.Auto ลงในบล็อก TextStyle ดังนี้

TextSample(
    samples = mapOf(
        "Hyphens - None" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph,
                    hyphens = Hyphens.None
                )
            )
        },
        "Hyphens - Auto" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph,
                    hyphens = Hyphens.Auto
                )
            )
        }
    )
)

ย่อหน้าที่ไม่ได้เปิดใช้การแบ่งวรรคและย่อหน้าที่มีการเปิดใช้การแบ่งวรรค
  เมื่อเปิดใช้การแบ่งคำ ระบบจะแบ่งคำออกเป็น 2 บรรทัด
รูปที่ 4 ย่อหน้าที่ไม่ได้เปิดใช้การแบ่งคำ (ด้านบน) เทียบกับย่อหน้าที่มีการเปิดใช้การแบ่งคำ (ด้านล่าง)

เมื่อเปิดใช้ การตัดคำจะเกิดขึ้นภายใต้เงื่อนไขต่อไปนี้เท่านั้น

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