เมื่อค้นคว้าตัวอย่างสำหรับการสนับสนุน Android ครั้งแรก มีตัวอย่างบางส่วนสำหรับแอนิเมชั่นที่เขียนด้วย Kotlin นอกจากนี้ยังมีตัวอย่างโค้ดสองสามข้อของข้อควรพิจารณาเกี่ยวกับการเข้าถึงพิเศษภายในแอนิเมชันดั้งเดิม
งั้นเราไปกันเลย! มาดูการเขียนแอนิเมชั่น 'ขยาย' ดั้งเดิมใน Kotlin และพูดคุยเกี่ยวกับวิธีช่วยเหลือผู้ที่เปิดใช้งาน TalkBack หรือข้อความที่ขยายใหญ่ขึ้น โค้ดทั้งหมดมีอยู่ใน repo ตัวอย่างนี้ โดยสร้างกิจกรรมเดียวที่มีมุมมองแบบเคลื่อนไหวอยู่ภายใน โค้ดนี้มีพื้นฐานมาจากการเขียนร่วมกับ Calum Turner
การเข้าถึง Android (a11y)
อุปกรณ์ Android ทั้งหมดมาพร้อมกับโปรแกรมอ่านหน้าจอในตัวที่ชื่อว่า TalkBack โดยสามารถเปิดได้จากการตั้งค่าของอุปกรณ์ และยังมีคู่มือการใช้ครั้งแรกในตัว ระบบใช้ท่าทางสัมผัสเพื่อไปยังส่วนต่างๆ ของหน้า โดยมีคำอธิบายขององค์ประกอบที่เน้นให้อ่านออกเสียง หากไม่มีสิ่งนี้ แอปจะไม่สามารถใช้งานได้สำหรับผู้ใช้ที่มีความบกพร่องทางสายตาจำนวนมาก
สิ่งสำคัญที่สำคัญคือองค์ประกอบที่ถูกต้องสามารถโฟกัสได้ มีคำอธิบาย และประกาศการเปลี่ยนแปลงมุมมอง
ภายในเมนูการตั้งค่าเดียวกัน ขนาดฟอนต์พื้นฐานเริ่มต้นสามารถปรับขนาดได้ตั้งแต่ 1.0 มุมมองควรตอบสนองต่อการเปลี่ยนแปลงขนาดแบบอักษรนี้ โดยองค์ประกอบทั้งหมดยังคงอยู่และทำงานอยู่
เลย์เอาต์
เราจะไม่ดูที่การจัดสไตล์เฉพาะของเลย์เอาต์ในที่นี้ เนื่องจากมีความเฉพาะเจาะจงสำหรับตัวอย่างนี้ แต่ส่วนช่วยสำหรับการเข้าถึงก็ควรค่าแก่การเน้น
ใช้คุณสมบัติสองอย่าง:android:contentDescription
และ android:importantForAccessibility
.
contentDescription
คือสิ่งที่อ่านเมื่อองค์ประกอบได้รับการโฟกัส สำหรับ ImageView ที่ได้รับความสนใจ นี่เป็นสิ่งสำคัญ ไม่เช่นนั้นโปรแกรมอ่านหน้าจอจะอ่าน "ไม่มีป้ายกำกับ" ที่ไม่มีประโยชน์ให้ผู้ใช้ฟังแทน
หากเป็นปุ่ม จะมีข้อความว่า '
android:contentDescription="tap to toggle extra person information"
เรายังใช้ importantForAccessibility:no
เพื่อปิดโฟกัสสำหรับ '+' TextView เนื่องจากข้อความใต้ป้ายทั้งสองมีคำอธิบาย ดังนั้น '+' จึงสับสนมากกว่ามีประโยชน์หากอ่านออกเสียง
สำหรับทั้งสองกรณีนี้ การทดสอบด้วยตนเองในอุปกรณ์จริงโดยเปิดใช้ TalkBack เป็นเครื่องบ่งชี้ที่ดีที่สุดว่าบริบทเหมาะสมหรือไม่หากไม่มีภาพ
ขยายแอนิเมชั่น
ภาพเคลื่อนไหวของเราจะเปิดใช้งานเมื่อแตะไอคอน "ข้อมูล" เพื่อสลับการขยายส่วนรายละเอียด
เราจะทำสิ่งนี้ทั้งหมดภายในกิจกรรมเดียวเพื่อให้โฟกัสไปที่โค้ดแอนิเมชั่นได้ง่ายๆ ในแอปในโลกแห่งความเป็นจริง มุมมองนี้มีแนวโน้มที่จะอยู่ภายในแฟรกเมนต์หรือมุมมองของผู้รีไซเคิล ดังนั้นจะใช้โครงสร้างโค้ดที่เป็นนามธรรมมากขึ้น
การตั้งค่าผู้ฟัง
ภายใน onCreate
. ของกิจกรรมตัวอย่างของเรา ก่อนอื่นเราต้องตั้งค่าผู้ฟังบนไอคอนของเราและส่งผ่านในมุมมองที่จะสลับ
infoIcon.setOnClickListener { toggleCardBody(root.personEntryBody) }
นอกจากนี้เรายังตั้งค่าตัวแปรภายในคลาสเพื่อติดตามว่ามีการสลับมุมมองหรือไม่ โดยตั้งค่าเป็นปิดในตอนแรก
private var isToggled = false
สลับภาพเคลื่อนไหวขยาย
ภายในเลย์เอาต์ของเรา เราได้ตั้งค่าความสูงของ personEntryBody
ถึง 0dp
.
ในการสลับเปิดนี้ เราจำเป็นต้องทราบความสูงใหม่ที่จะตั้งค่า ความยาวของแอนิเมชั่นควรเป็น และความสูงที่ควรจะเป็นในแต่ละช่วงเวลาของแอนิเมชั่น
จากนั้นเราต้องตั้งค่า isToggled
กลับด้าน และให้แน่ใจว่าเมื่อเคาะอีกครั้ง มันจะย้อนกลับ
private fun toggleCardBody(body: View) {
body.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
val maxHeight = body.measuredHeight + body.paddingTop + body.paddingBottom
val startHeight = if (isToggled) maxHeight else 0
val targetHeight = if (isToggled) 0 else maxHeight
val expandAnimator = ValueAnimator
.ofInt(startHeight, targetHeight)
.setDuration(200)
expandAnimator.addUpdateListener {
val value = it.animatedValue as Int
body.layoutParams.height = value
body.requestLayout()
}
expandAnimator.doOnEnd {
isToggled = !isToggled
}
expandAnimator.start()
}
เนื่องจากความสูงเมื่อวาดมุมมองในตอนแรกเป็น 0 เราจึงต้องคำนวณขนาดใหม่ด้วยการวัดเลย์เอาต์
ตามที่อธิบายไว้ในเอกสารเค้าโครงมุมมองของ Android เราสามารถใช้ measure()
พร้อมกับพารามิเตอร์เลย์เอาต์ที่เรากำหนดให้กับมุมมองเพื่อวัดซ้ำทุกครั้งที่แตะไอคอนข้อมูล
ในการคำนวณความสูงสูงสุด เราต้องเพิ่มการเติมด้านบนและด้านล่างด้วยตนเอง เนื่องจากสิ่งเหล่านี้ไม่รวมอยู่ในความสูงที่วัดได้
ขึ้นอยู่กับ isToggled
จากนั้นเราจะรู้ว่าเรากำลังเริ่มต้นจาก 0 หรือเริ่มจากความสูงสูงสุดที่ขยายแล้ว และความสูงของเป้าหมายตรงข้ามกัน
เราใช้ Value Animator เพื่อย้ายจากค่าเริ่มต้นไปยังค่าสิ้นสุดเป้าหมาย และกำหนดระยะเวลาเป็นมิลลิวินาที ระยะเวลานี้อิงจากการทดสอบด้วยตนเองในภายหลังสำหรับความรู้สึก UX
ValueAnimator
.ofInt(startHeight, targetHeight)
.setDuration(200)
เราผูกระยะเวลากับความสูงด้วยตัวฟังการอัปเดต โดยขอให้วาดเลย์เอาต์ใหม่หลังการอัปเดตแต่ละครั้ง และปรับความสูงในแต่ละครั้ง
expandAnimator.addUpdateListener {
val value = it.animatedValue as Int
body.layoutParams.height = value
body.requestLayout()
}
expandAnimator.doOnEnd {
isToggled = !isToggled
}
expandAnimator.start()
ขณะที่เราใช้ Kotlin เรายังเพิ่ม androidx
ห้องสมุดของเรา build.gradle
เพื่อรับประโยชน์จาก doOnEnd
การขยาย. สิ่งนี้ทำให้เราสามารถผกผัน isToggled
. ได้ง่ายมาก ตัวแปร
ในที่สุดเราก็เริ่มแอนิเมชั่นของเรา! เรามีร่างกายที่ขยายและหดตัวเมื่อสัมผัสไอคอน!
ภาพเคลื่อนไหวที่ราบรื่นยิ่งขึ้น
แม้ว่าแอนิเมชั่นของเราจะใช้งานได้ตามปกติ แต่ขั้นตอนเพิ่มเติมที่ดีคือการเพิ่มตัวแก้ไขเพื่อให้การเคลื่อนไหวรู้สึกเป็นธรรมชาติมากขึ้น
expandAnimator.interpolator = FastOutSlowInInterpolator()
การเพิ่มการเข้าถึงของเรา
เราจะเพิ่มสองสิ่งสุดท้ายเพื่อหวังว่าจะช่วยผู้ใช้อายุ 11 ปีของเราได้
อันดับแรก เราสามารถช่วยในการนำทางโดยใช้ AccessibilityEvent
.
expandAnimator.doOnEnd {
if (!isToggled) body.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
isToggled = !isToggled
}
ซึ่งหมายความว่าเมื่อภาพเคลื่อนไหวย้ายจากปิดเป็นเปิด โฟกัสจะข้ามไปยังโฟกัสที่รายการแรกในเนื้อหาทันที ในกรณีนี้คือคำอธิบาย ในเลย์เอาต์ เราตั้งค่าคำอธิบายของแอคชันไอคอนข้อมูล แต่เนื่องจากเราอาจไม่สามารถพึ่งพาตัวบ่งชี้ที่มองเห็นได้สำหรับผู้ใช้เพื่อย้ายไปยังรายการถัดไป เราจึงสามารถจัดการสิ่งนี้ให้กับพวกเขาได้
ประการที่สอง เราอนุญาตให้ใช้ขนาดตัวอักษรที่แตกต่างกัน ความสูงที่วัดได้กลับมาจาก measure()
ไม่ได้คำนึงถึงการกำหนดขนาดแบบอักษรในการตั้งค่าการช่วยสำหรับการเข้าถึงของอุปกรณ์ ดังนั้นเมื่อมีขนาดใหญ่ ด้านล่างของคำอธิบายจะถูกครอบตัดเนื่องจากมีขนาดใหญ่เกินไปที่จะพอดี
เราสามารถเข้าถึงมาตราส่วนแบบอักษรโดยทางโปรแกรม และปรับขนาดความสูงของเราตามสิ่งนี้ เราแปลงเป็นจำนวนเต็มเนื่องจากมาตราส่วนแบบอักษรอาจส่งผลให้ลอยซึ่งจะไม่ทำงานเป็นความสูงของเค้าโครง
val a11yFontScale = body.context.resources.configuration.fontScale
val maxHeight = ((body.measuredHeight + body.paddingTop + body.paddingBottom) * a11yFontScale).toInt()
เสร็จแล้ว!
และแล้วเราก็มาถึงอนิเมชั่นสุดท้ายของเราแล้ว! ด้วยบรรทัดพิเศษเพียงไม่กี่บรรทัด เราได้เพิ่มความครอบคลุม a11y อย่างมาก และมีส่วนที่ขยายอย่างราบรื่นซึ่งเผยให้เห็นป้าย Kotlin และ Android หรือไม่
ขอบคุณที่อ่าน ?
ต่อไปนี้คืออีกสองสามสิ่งที่ฉันเขียนเมื่อเร็วๆ นี้:
- กำหนดการทดสอบ CodeceptJS E2E เอง
- การทดสอบปฏิกิริยากับ Jest และ Enzyme II
ส่วนเสริมที่เป็นประโยชน์
- โพสต์ androidx ที่ยอดเยี่ยมของ Joe Birch ในการสำรวจ KTX สำหรับ Android
- บทช่วยสอนการเข้าถึง Android:เริ่มต้นใช้งาน