Span คือออบเจ็กต์มาร์กอัปที่มีประสิทธิภาพซึ่งคุณสามารถใช้เพื่อจัดรูปแบบข้อความที่
ระดับอักขระหรือย่อหน้า การรวม span กับวัตถุข้อความทำให้คุณสามารถ
ข้อความได้หลายวิธี รวมถึงการเพิ่มสี การทำให้ข้อความคลิกได้
การปรับขนาดข้อความ และลากข้อความด้วยวิธีที่กำหนดเอง Span สามารถ
เปลี่ยนคุณสมบัติของ TextPaint
หรือวาดบน
Canvas
และเปลี่ยนเลย์เอาต์ข้อความ
Android มีระยะเวลาหลายประเภทซึ่งครอบคลุมข้อความทั่วไปมากมาย การจัดรูปแบบ คุณยังสามารถสร้างระยะเวลาของคุณเองเพื่อใช้การจัดรูปแบบที่กำหนดเองได้อีกด้วย
สร้างและใช้ระยะเวลา
ในการสร้างระยะเวลา คุณสามารถใช้ชั้นเรียนใดชั้นเรียนหนึ่งที่ระบุในตารางต่อไปนี้ คลาสจะแตกต่างกันไปขึ้นอยู่กับว่าตัวข้อความเปลี่ยนแปลงได้หรือไม่ หรือไม่ มาร์กอัปจะเปลี่ยนแปลงไม่ได้ และโครงสร้างข้อมูลที่สำคัญใดที่มีข้อมูล span
ชั้น | ข้อความที่ปิดได้ | มาร์กอัปที่ปิดได้ | โครงสร้างข้อมูล |
---|---|---|---|
SpannedString |
ไม่ | ไม่ | อาร์เรย์เชิงเส้น |
SpannableString |
ไม่ | ใช่ | อาร์เรย์เชิงเส้น |
SpannableStringBuilder |
ใช่ | ใช่ | แผนผังช่วง |
ทั้ง 3 ชั้นเรียนนี้จะขยายแพ็กเกจ Spanned
ของ Google SpannableString
และ SpannableStringBuilder
ยังขยายระยะเวลา
อินเทอร์เฟซของ Spannable
วิธีตัดสินใจเลือกใช้มีดังนี้
- หากคุณไม่ได้แก้ไขข้อความหรือมาร์กอัปหลังจากการสร้าง ให้ใช้
SpannedString
- ถ้าคุณต้องการแนบระยะเวลาจำนวนน้อยกับออบเจ็กต์ข้อความเดียว และ
ข้อความนั้นเป็นแบบอ่านอย่างเดียว โปรดใช้
SpannableString
- ถ้าคุณต้องการแก้ไขข้อความหลังจากการสร้าง และคุณต้องแนบ span กับ
ข้อความ ให้ใช้
SpannableStringBuilder
- หากคุณจำเป็นต้องแนบช่วงเวลาจำนวนมากกับออบเจ็กต์ข้อความ ไม่ว่า
ไม่ว่าข้อความนั้นเป็นแบบอ่านอย่างเดียว ให้ใช้
SpannableStringBuilder
หากต้องการใช้ระยะเวลา โปรดโทรไปที่ setSpan(Object _what_, int _start_, int _end_, int
_flags_)
บนออบเจ็กต์ Spannable
พารามิเตอร์ what หมายถึงระยะเวลาที่คุณอยู่
ที่ใช้กับข้อความ และพารามิเตอร์ start และ end จะแสดงส่วน
ของข้อความที่คุณจะใช้สแปนด้วย
ถ้าคุณแทรกข้อความภายในขอบเขตของสแปน สแปนจะขยายเป็น
รวมข้อความที่แทรกเข้ามา เมื่อแทรกข้อความที่ช่วงเวลา
ขอบเขต ซึ่งก็คือดัชนีเริ่มต้นหรือสิ้นสุด ซึ่งก็คือธง
จะกำหนดว่า span จะขยายเพื่อรวมข้อความที่แทรกหรือไม่ ใช้
เวลา
Spannable.SPAN_EXCLUSIVE_INCLUSIVE
เพื่อใส่ข้อความที่แทรกเข้ามาและใช้
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
เพื่อยกเว้นข้อความที่แทรก
ตัวอย่างต่อไปนี้แสดงวิธีแนบไฟล์
ForegroundColorSpan
เป็น
สตริง:
Kotlin
val spannable = SpannableStringBuilder("Text is spantastic!") spannable.setSpan( ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE )
Java
SpannableStringBuilder spannable = new SpannableStringBuilder("Text is spantastic!"); spannable.setSpan( new ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE );
เนื่องจากตั้งค่าระยะเวลาโดยใช้ Spannable.SPAN_EXCLUSIVE_INCLUSIVE
ระยะเวลา
ขยายเพื่อรวมข้อความที่แทรกไว้ที่ขอบเขตของช่วง ดังที่แสดงใน
ตัวอย่างต่อไปนี้
Kotlin
val spannable = SpannableStringBuilder("Text is spantastic!") spannable.setSpan( ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE ) spannable.insert(12, "(& fon)")
Java
SpannableStringBuilder spannable = new SpannableStringBuilder("Text is spantastic!"); spannable.setSpan( new ForegroundColorSpan(Color.RED), 8, // start 12, // end Spannable.SPAN_EXCLUSIVE_INCLUSIVE ); spannable.insert(12, "(& fon)");
คุณสามารถแนบระยะเวลาหลายช่วงกับข้อความเดียวกันได้ ตัวอย่างต่อไปนี้จะแสดงวิธีการ เพื่อสร้างข้อความตัวหนาและมีสีแดง
Kotlin
val spannable = SpannableString("Text is spantastic!") spannable.setSpan(ForegroundColorSpan(Color.RED), 8, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) spannable.setSpan( StyleSpan(Typeface.BOLD), 8, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE )
Java
SpannableString spannable = new SpannableString("Text is spantastic!"); spannable.setSpan( new ForegroundColorSpan(Color.RED), 8, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ); spannable.setSpan( new StyleSpan(Typeface.BOLD), 8, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
ประเภทช่วง Android
Android มีสแปนกว่า 20 ประเภทใน android.text.style Android แบ่งประเภทระยะเวลาได้ 2 วิธีหลักๆ ดังนี้
- ระยะเวลาส่งผลต่อข้อความอย่างไร: ระยะเวลาอาจส่งผลต่อลักษณะของข้อความหรือข้อความ เมตริกต่างๆ
- ขอบเขตระดับ: บางช่วงสามารถใช้กับอักขระแต่ละตัวได้ ส่วนบางช่วงอาจใช้กับอักขระแต่ละตัวได้ ต้องใช้ได้กับทั้งย่อหน้า
ส่วนต่อไปนี้จะอธิบายหมวดหมู่เหล่านี้โดยละเอียดยิ่งขึ้น
ระยะเวลาที่ส่งผลต่อลักษณะของข้อความ
ระยะเวลาบางรายการที่ใช้ในระดับอักขระจะส่งผลต่อลักษณะของข้อความ เช่น
เปลี่ยนข้อความหรือสีพื้นหลัง และเพิ่มเส้นใต้หรือขีดทับ เหล่านี้
จะขยายรหัส
CharacterStyle
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีใช้ UnderlineSpan
เพื่อขีดเส้นใต้
ข้อความ:
Kotlin
val string = SpannableString("Text with underline span") string.setSpan(UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
Java
SpannableString string = new SpannableString("Text with underline span"); string.setSpan(new UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
การขยายที่มีผลต่อลักษณะของข้อความเท่านั้นจะทริกเกอร์ข้อความซ้ำโดยไม่มี
ซึ่งจะทำให้เกิดการคำนวณเลย์เอาต์ใหม่ ระยะเวลาเหล่านี้จะใช้
UpdateAppearance
และขยายเวลา
CharacterStyle
คลาสย่อย CharacterStyle
รายการกำหนดวิธีเขียนข้อความโดยการให้สิทธิ์เข้าถึง
อัปเดต TextPaint
ระยะเวลาที่ส่งผลต่อเมตริกข้อความ
ระยะเวลาอื่นๆ ที่มีผลในระดับอักขระจะส่งผลต่อเมตริกข้อความ เช่น บรรทัด
ความสูงและขนาดข้อความ ซึ่งจะขยายระยะเวลา
MetricAffectingSpan
ตัวอย่างโค้ดต่อไปนี้สร้าง
RelativeSizeSpan
ที่
เพิ่มขนาดข้อความอีก 50%
Kotlin
val string = SpannableString("Text with relative size span") string.setSpan(RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
Java
SpannableString string = new SpannableString("Text with relative size span"); string.setSpan(new RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
การใช้ช่วงที่ส่งผลกับเมตริกข้อความจะทำให้ออบเจ็กต์สังเกตการณ์ วัดข้อความอีกครั้งเพื่อให้ได้เลย์เอาต์และการแสดงภาพที่ถูกต้อง ตัวอย่างเช่น การเปลี่ยน ขนาดตัวอักษรอาจทำให้คำปรากฏในบรรทัดที่ต่างกัน ใช้ก่อนหน้า span จะทริกเกอร์การวัดค่าใหม่ การคํานวณเลย์เอาต์ข้อความอีกครั้ง และการวาดรูปแบบ ข้อความ
ระยะที่มีผลต่อเมตริกข้อความจะขยายคลาส MetricAffectingSpan
ซึ่งเป็น
คลาสนามธรรมที่ทำให้คลาสย่อยกำหนดได้ว่าสแปนจะส่งผลต่อการวัดข้อความอย่างไร
ด้วยการให้สิทธิ์เข้าถึง TextPaint
เนื่องจาก MetricAffectingSpan
ขยายเวลา
CharacterSpan
คลาสย่อยจะส่งผลต่อลักษณะของข้อความที่อักขระ
ระยะเวลาที่ส่งผลต่อย่อหน้า
นอกจากนี้ระยะเวลายังสามารถส่งผลต่อข้อความในระดับย่อหน้า เช่น การเปลี่ยน
การจัดแนวหรือระยะขอบของข้อความ ระยะเวลาที่ส่งผลต่อทั้งย่อหน้า
ใช้งาน ParagraphStyle
ถึง
คุณใช้สแปนเหล่านี้ ให้คุณแนบสับกับทั้งย่อหน้า โดยไม่ใส่คำลงท้าย
อักขระขึ้นบรรทัดใหม่ ถ้าคุณพยายามใช้ช่วงย่อหน้ากับสิ่งอื่นที่ไม่ใช่
เขียนทั้งย่อหน้า Android ไม่ใช้ Span เลย
รูปที่ 8 แสดงวิธีที่ Android แยกย่อหน้าในข้อความ
ตัวอย่างโค้ดต่อไปนี้ใช้
QuoteSpan
ใน 1 ย่อหน้า โปรดทราบว่า
หากคุณแนบช่วงกับตำแหน่งอื่นๆ ที่ไม่ใช่จุดเริ่มต้นหรือจุดสิ้นสุดของ
ย่อหน้า Android ไม่ใช้รูปแบบเลย
Kotlin
spannable.setSpan(QuoteSpan(color), 8, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
Java
spannable.setSpan(new QuoteSpan(color), 8, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
สร้างระยะเวลาที่กำหนดเอง
หากคุณต้องการฟังก์ชันมากกว่าที่มีใน Android รุ่นที่มีอยู่ คุณสามารถใช้ระยะเวลาที่กำหนดเองได้ เมื่อนำระยะเวลาของคุณเองไปใช้ ให้ตัดสินใจว่า ว่าช่วงของคุณมีผลต่อข้อความที่ระดับอักขระหรือระดับย่อหน้า และ จะส่งผลต่อเลย์เอาต์หรือลักษณะของข้อความหรือไม่ ซึ่งช่วย พิจารณาว่าคุณสามารถขยายคลาสพื้นฐานใดได้บ้างและอินเทอร์เฟซใดที่คุณอาจต้องใช้ เพื่อนำไปปฏิบัติ ใช้ตารางต่อไปนี้ในการอ้างอิง
สถานการณ์ | คลาสหรืออินเทอร์เฟซ |
---|---|
ระยะเวลาจะมีผลต่อข้อความในระดับอักขระ | CharacterStyle |
ระยะเวลาจะมีผลต่อลักษณะของข้อความ | UpdateAppearance |
ระยะเวลามีผลต่อเมตริกข้อความ | UpdateLayout |
ระยะเวลาจะมีผลกับข้อความในระดับย่อหน้า | ParagraphStyle |
ตัวอย่างเช่น ถ้าคุณต้องการใช้ระยะเวลาที่กำหนดเองซึ่งจะปรับขนาดข้อความและ
สี ขยาย RelativeSizeSpan
ผ่านการรับค่า RelativeSizeSpan
ขยาย CharacterStyle
และใช้อินเทอร์เฟซ Update
ทั้ง 2 รายการ เนื่องจาก
มี Callback สำหรับ updateDrawState
และ updateMeasureState
อยู่แล้ว
คุณสามารถลบล้าง Callback เหล่านี้เพื่อใช้ลักษณะการทำงานที่กำหนดเองของคุณได้
โค้ดต่อไปนี้สร้างช่วงที่กำหนดเองที่ขยาย RelativeSizeSpan
และ
ลบล้าง Callback updateDrawState
เพื่อกำหนดสีของ TextPaint
Kotlin
class RelativeSizeColorSpan( size: Float, @ColorInt private val color: Int ) : RelativeSizeSpan(size) { override fun updateDrawState(textPaint: TextPaint) { super.updateDrawState(textPaint) textPaint.color = color } }
Java
public class RelativeSizeColorSpan extends RelativeSizeSpan { private int color; public RelativeSizeColorSpan(float spanSize, int spanColor) { super(spanSize); color = spanColor; } @Override public void updateDrawState(TextPaint textPaint) { super.updateDrawState(textPaint); textPaint.setColor(color); } }
ตัวอย่างนี้แสดงวิธีสร้างระยะเวลาที่กำหนดเอง คุณสามารถบรรลุ
โดยใช้ RelativeSizeSpan
และ ForegroundColorSpan
กับข้อความ
ทดสอบการใช้งาน Span
อินเทอร์เฟซ Spanned
ให้คุณตั้งค่าระยะเวลา และยังเรียกระยะเวลาจาก
ข้อความ เมื่อทำการทดสอบ ให้ใช้ Android JUnit ต่างๆ
ทดสอบ เพื่อยืนยันว่าเพิ่ม span ที่ถูกต้องแล้ว
ในตำแหน่งที่ถูกต้อง ตัวอย่างการจัดรูปแบบข้อความ
แอป
มี Span ที่ใช้มาร์กอัปกับสัญลักษณ์หัวข้อย่อยโดยการแนบ
BulletPointSpan
กับข้อความ ตัวอย่างโค้ดต่อไปนี้แสดงวิธีการทดสอบ
หัวข้อย่อยปรากฏตามที่คาดไว้หรือไม่:
Kotlin
@Test fun textWithBulletPoints() { val result = builder.markdownToSpans("Points\n* one\n+ two") // Check whether the markup tags are removed. assertEquals("Points\none\ntwo", result.toString()) // Get all the spans attached to the SpannedString. val spans = result.getSpans<Any>(0, result.length, Any::class.java) // Check whether the correct number of spans are created. assertEquals(2, spans.size.toLong()) // Check whether the spans are instances of BulletPointSpan. val bulletSpan1 = spans[0] as BulletPointSpan val bulletSpan2 = spans[1] as BulletPointSpan // Check whether the start and end indices are the expected ones. assertEquals(7, result.getSpanStart(bulletSpan1).toLong()) assertEquals(11, result.getSpanEnd(bulletSpan1).toLong()) assertEquals(11, result.getSpanStart(bulletSpan2).toLong()) assertEquals(14, result.getSpanEnd(bulletSpan2).toLong()) }
Java
@Test public void textWithBulletPoints() { SpannedString result = builder.markdownToSpans("Points\n* one\n+ two"); // Check whether the markup tags are removed. assertEquals("Points\none\ntwo", result.toString()); // Get all the spans attached to the SpannedString. Object[] spans = result.getSpans(0, result.length(), Object.class); // Check whether the correct number of spans are created. assertEquals(2, spans.length); // Check whether the spans are instances of BulletPointSpan. BulletPointSpan bulletSpan1 = (BulletPointSpan) spans[0]; BulletPointSpan bulletSpan2 = (BulletPointSpan) spans[1]; // Check whether the start and end indices are the expected ones. assertEquals(7, result.getSpanStart(bulletSpan1)); assertEquals(11, result.getSpanEnd(bulletSpan1)); assertEquals(11, result.getSpanStart(bulletSpan2)); assertEquals(14, result.getSpanEnd(bulletSpan2)); }
ดูตัวอย่างการทดสอบเพิ่มเติมได้ที่ MarkdownBuilderTest ใน GitHub
ทดสอบระยะเวลาที่กำหนดเอง
เมื่อทดสอบระยะเวลา ให้ยืนยันว่า TextPaint
มีช่วงระยะเวลาที่คาดไว้
แก้ไขและทำให้องค์ประกอบที่ถูกต้องปรากฏบน Canvas
สำหรับ
ตัวอย่างเช่น ลองพิจารณาการใช้งานระยะเวลาที่กำหนดเองซึ่งแทรกสัญลักษณ์หัวข้อย่อยไว้หน้า
ข้อความบางอย่าง หัวข้อย่อยมีขนาดและสีที่ระบุ รวมถึงมีช่องว่าง
ระหว่างขอบด้านซ้ายของพื้นที่ที่ถอนออกได้และหัวข้อย่อย
คุณทดสอบลักษณะการทำงานของชั้นเรียนนี้ได้โดยใช้การทดสอบ AndroidJUnit กำลังตรวจสอบข้อมูลต่อไปนี้
- หากคุณใช้ระยะเวลาอย่างถูกต้อง สัญลักษณ์หัวข้อย่อยของขนาดที่ระบุ และ สีจะปรากฏบนผืนผ้าใบ และมีพื้นที่ว่างที่เหมาะสมระหว่างด้านซ้าย และหัวข้อย่อย
- หากคุณไม่ได้ใช้ระยะเวลานี้ ลักษณะการทำงานที่กำหนดเองจะไม่ปรากฏขึ้น
คุณสามารถดูการใช้งานการทดสอบเหล่านี้ได้ใน TextStyling ตัวอย่างใน GitHub
คุณสามารถทดสอบการโต้ตอบของ Canvas ได้ด้วยการลอกเลียนผ้าใบและส่งภาพเลียนแบบ
ของ
drawLeadingMargin()
และตรวจสอบว่าเมธอดที่ถูกต้องถูกเรียกด้วย
พารามิเตอร์
ดูตัวอย่างการทดสอบช่วงเพิ่มเติมได้ใน BulletPointSpanTest
แนวทางปฏิบัติแนะนำในการใช้สแปน
มีวิธีการใช้หน่วยความจำอย่างมีประสิทธิภาพในการตั้งค่าข้อความใน TextView
หลายวิธี ทั้งนี้ขึ้นอยู่กับ
ตามความต้องการของคุณ
แนบหรือปลดช่วงออกโดยไม่เปลี่ยนแปลงข้อความเบื้องหลัง
TextView.setText()
มีโอเวอร์โหลดหลายรายการที่จัดการระยะเวลาต่างกัน ตัวอย่างเช่น คุณสามารถ
ตั้งค่าออบเจ็กต์ข้อความ Spannable
ด้วยโค้ดต่อไปนี้
Kotlin
textView.setText(spannableObject)
Java
textView.setText(spannableObject);
เมื่อเรียกใช้ setText()
ที่มากเกินไปนี้ TextView
จะสร้างสำเนา
Spannable
เป็น SpannedString
และเก็บไว้ในความทรงจำเป็น CharSequence
ซึ่งหมายความว่า ข้อความและช่วงเวลาของคุณจะเปลี่ยนแปลงไม่ได้ ดังนั้น เมื่อคุณต้องการ
อัปเดตข้อความหรือระยะเวลา สร้างออบเจ็กต์ Spannable
ใหม่และการเรียกใช้
setText()
อีกครั้ง ซึ่งจะทริกเกอร์การวัดค่าและวาดคอลัมน์
เลย์เอาต์
หากต้องการระบุว่าระยะเวลาต้องเปลี่ยนแปลงได้ คุณสามารถใช้
setText(CharSequence text, TextView.BufferType
type)
ดังที่ปรากฏในตัวอย่างต่อไปนี้
Kotlin
textView.setText(spannable, BufferType.SPANNABLE) val spannableText = textView.text as Spannable spannableText.setSpan( ForegroundColorSpan(color), 8, spannableText.length, SPAN_INCLUSIVE_INCLUSIVE )
Java
textView.setText(spannable, BufferType.SPANNABLE); Spannable spannableText = (Spannable) textView.getText(); spannableText.setSpan( new ForegroundColorSpan(color), 8, spannableText.getLength(), SPAN_INCLUSIVE_INCLUSIVE);
ในตัวอย่างนี้
BufferType.SPANNABLE
ทำให้ TextView
สร้าง SpannableString
และ
ตอนนี้ออบเจ็กต์ CharSequence
ที่ TextView
เก็บไว้มีมาร์กอัปที่แก้ไขได้
ข้อความที่เปลี่ยนแปลงไม่ได้ หากต้องการอัปเดตระยะเวลา ให้ดึงข้อความเป็น Spannable
จากนั้น
อัปเดตระยะเวลาตามที่จำเป็น
เมื่อคุณแนบ ถอด หรือเปลี่ยนตำแหน่งสแปน TextView
โดยอัตโนมัติ
อัปเดตเพื่อแสดงการเปลี่ยนแปลงของข้อความ หากคุณเปลี่ยนแอตทริบิวต์ภายใน
ของระยะเวลาที่มีอยู่ ให้โทรติดต่อ invalidate()
เพื่อทำการเปลี่ยนแปลงที่เกี่ยวข้องกับลักษณะที่ปรากฏ หรือ
requestLayout()
เพื่อทำการเปลี่ยนแปลงที่เกี่ยวข้องกับเมตริก
ตั้งค่าข้อความใน TextView หลายครั้ง
ในบางกรณี เช่น เมื่อใช้
RecyclerView.ViewHolder
คุณอาจต้องการใช้ TextView
ซ้ำและตั้งค่าข้อความหลายครั้ง โดย
ไม่ว่าคุณจะตั้งค่า BufferType
หรือไม่ก็ตาม TextView
จะสร้าง
สำเนาของออบเจ็กต์ CharSequence
และจัดเก็บไว้ในหน่วยความจำ ทั้งหมดนี้ทำให้
คุณตั้งใจอัปเดต TextView
รายการ คุณจะอัปเดตต้นฉบับไม่ได้
CharSequence
เพื่ออัปเดตข้อความ หมายความว่าทุกครั้งที่คุณกำหนด
TextView
จะสร้างวัตถุใหม่
หากต้องการควบคุมกระบวนการนี้ได้มากขึ้นและหลีกเลี่ยงออบเจ็กต์พิเศษ
ที่คุณสามารถนำไปประยุกต์ใช้
Spannable.Factory
และลบล้าง
newSpannable()
แทนที่จะสร้างวัตถุข้อความใหม่ คุณสามารถแคสต์และส่งคืน
CharSequence
เป็น Spannable
ดังที่แสดงในตัวอย่างต่อไปนี้
Kotlin
val spannableFactory = object : Spannable.Factory() { override fun newSpannable(source: CharSequence?): Spannable { return source as Spannable } }
Java
Spannable.Factory spannableFactory = new Spannable.Factory(){ @Override public Spannable newSpannable(CharSequence source) { return (Spannable) source; } };
คุณต้องใช้ textView.setText(spannableObject, BufferType.SPANNABLE)
เมื่อ
กำลังตั้งค่าข้อความ มิเช่นนั้น ระบบจะสร้างแหล่งที่มา CharSequence
เป็น Spanned
และไม่สามารถแคสต์ไปยัง Spannable
ซึ่งทำให้ newSpannable()
แสดงผล
ClassCastException
หลังจากลบล้าง newSpannable()
แล้ว ให้ TextView
ใช้ Factory
ใหม่:
Kotlin
textView.setSpannableFactory(spannableFactory)
Java
textView.setSpannableFactory(spannableFactory);
ตั้งค่าออบเจ็กต์ Spannable.Factory
ครั้งเดียวทันทีหลังจากที่ได้รับการอ้างอิงไปยัง
TextView
หากคุณใช้ RecyclerView
ให้ตั้งค่าออบเจ็กต์ Factory
เมื่อคุณ
ก่อนอื่นให้เพิ่มยอดดู เพื่อหลีกเลี่ยงการสร้างออบเจ็กต์เพิ่มเติมเมื่อ
RecyclerView
เชื่อมโยงรายการใหม่กับ ViewHolder
ของคุณ
เปลี่ยนแอตทริบิวต์ช่วงภายใน
หากคุณต้องการเปลี่ยนเฉพาะแอตทริบิวต์ภายในของช่วงเวลาที่เปลี่ยนแปลงได้ เช่น
สีของสัญลักษณ์หัวข้อย่อยในหัวข้อย่อยแบบกำหนดเอง คุณจะเลี่ยงการเรียกค่าโสหุ้ยได้
setText()
หลายครั้งโดยการเก็บการอ้างอิงสแปนไว้ขณะสร้าง
เมื่อคุณจำเป็นต้องแก้ไขระยะเวลา คุณสามารถแก้ไขการอ้างอิงแล้วเรียกใช้
invalidate()
หรือ requestLayout()
ใน TextView
ทั้งนี้ขึ้นอยู่กับประเภทของ
ที่คุณเปลี่ยนแปลง
ในตัวอย่างโค้ดต่อไปนี้ การใช้งานสัญลักษณ์หัวข้อย่อยที่กำหนดเองมีแอตทริบิวต์ สีเริ่มต้นของสีแดงที่เปลี่ยนเป็นสีเทาเมื่อแตะปุ่ม
Kotlin
class MainActivity : AppCompatActivity() { // Keeping the span as a field. val bulletSpan = BulletPointSpan(color = Color.RED) override fun onCreate(savedInstanceState: Bundle?) { ... val spannable = SpannableString("Text is spantastic") // Setting the span to the bulletSpan field. spannable.setSpan( bulletSpan, 0, 4, Spanned.SPAN_INCLUSIVE_INCLUSIVE ) styledText.setText(spannable) button.setOnClickListener { // Change the color of the mutable span. bulletSpan.color = Color.GRAY // Color doesn't change until invalidate is called. styledText.invalidate() } } }
Java
public class MainActivity extends AppCompatActivity { private BulletPointSpan bulletSpan = new BulletPointSpan(Color.RED); @Override protected void onCreate(Bundle savedInstanceState) { ... SpannableString spannable = new SpannableString("Text is spantastic"); // Setting the span to the bulletSpan field. spannable.setSpan(bulletSpan, 0, 4, Spanned.SPAN_INCLUSIVE_INCLUSIVE); styledText.setText(spannable); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Change the color of the mutable span. bulletSpan.setColor(Color.GRAY); // Color doesn't change until invalidate is called. styledText.invalidate(); } }); } }
ใช้ฟังก์ชันส่วนขยาย KTX สำหรับ Android
Android KTX ยังมีฟังก์ชันส่วนขยายที่ช่วยให้ทำงานกับระยะเวลา ได้ง่ายยิ่งขึ้น โปรดดูข้อมูลเพิ่มเติมในเอกสารประกอบเกี่ยวกับ androidx.core.text ใหม่