Computer >> คอมพิวเตอร์ >  >> ระบบ >> Android

วิธีทำให้แอนิเมชั่น Kotlin Android ของคุณสามารถเข้าถึงได้

เมื่อค้นคว้าตัวอย่างสำหรับการสนับสนุน Android ครั้งแรก มีตัวอย่างบางส่วนสำหรับแอนิเมชั่นที่เขียนด้วย Kotlin นอกจากนี้ยังมีตัวอย่างโค้ดสองสามข้อของข้อควรพิจารณาเกี่ยวกับการเข้าถึงพิเศษภายในแอนิเมชันดั้งเดิม

งั้นเราไปกันเลย! มาดูการเขียนแอนิเมชั่น 'ขยาย' ดั้งเดิมใน Kotlin และพูดคุยเกี่ยวกับวิธีช่วยเหลือผู้ที่เปิดใช้งาน TalkBack หรือข้อความที่ขยายใหญ่ขึ้น โค้ดทั้งหมดมีอยู่ใน repo ตัวอย่างนี้ โดยสร้างกิจกรรมเดียวที่มีมุมมองแบบเคลื่อนไหวอยู่ภายใน โค้ดนี้มีพื้นฐานมาจากการเขียนร่วมกับ Calum Turner

วิธีทำให้แอนิเมชั่น Kotlin Android ของคุณสามารถเข้าถึงได้
GIF ของผลลัพธ์แอปสุดท้าย

การเข้าถึง Android (a11y)

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

สิ่งสำคัญที่สำคัญคือองค์ประกอบที่ถูกต้องสามารถโฟกัสได้ มีคำอธิบาย และประกาศการเปลี่ยนแปลงมุมมอง

ภายในเมนูการตั้งค่าเดียวกัน ขนาดฟอนต์พื้นฐานเริ่มต้นสามารถปรับขนาดได้ตั้งแต่ 1.0 มุมมองควรตอบสนองต่อการเปลี่ยนแปลงขนาดแบบอักษรนี้ โดยองค์ประกอบทั้งหมดยังคงอยู่และทำงานอยู่

เลย์เอาต์

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

ใช้คุณสมบัติสองอย่าง:android:contentDescription และ android:importantForAccessibility .

contentDescription คือสิ่งที่อ่านเมื่อองค์ประกอบได้รับการโฟกัส สำหรับ ImageView ที่ได้รับความสนใจ นี่เป็นสิ่งสำคัญ ไม่เช่นนั้นโปรแกรมอ่านหน้าจอจะอ่าน "ไม่มีป้ายกำกับ" ที่ไม่มีประโยชน์ให้ผู้ใช้ฟังแทน

หากเป็นปุ่ม จะมีข้อความว่า ' button แตะสองครั้งเพื่อเปิดใช้งาน' โดยค่าเริ่มต้น แต่สำหรับไอคอน 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()

เสร็จแล้ว!

วิธีทำให้แอนิเมชั่น Kotlin Android ของคุณสามารถเข้าถึงได้
GIF ของผลลัพธ์แอปสุดท้าย

และแล้วเราก็มาถึงอนิเมชั่นสุดท้ายของเราแล้ว! ด้วยบรรทัดพิเศษเพียงไม่กี่บรรทัด เราได้เพิ่มความครอบคลุม a11y อย่างมาก และมีส่วนที่ขยายอย่างราบรื่นซึ่งเผยให้เห็นป้าย Kotlin และ Android หรือไม่

ขอบคุณที่อ่าน ?

ต่อไปนี้คืออีกสองสามสิ่งที่ฉันเขียนเมื่อเร็วๆ นี้:

  • กำหนดการทดสอบ CodeceptJS E2E เอง
  • การทดสอบปฏิกิริยากับ Jest และ Enzyme II

ส่วนเสริมที่เป็นประโยชน์

  • โพสต์ androidx ที่ยอดเยี่ยมของ Joe Birch ในการสำรวจ KTX สำหรับ Android
  • บทช่วยสอนการเข้าถึง Android:เริ่มต้นใช้งาน