Computer >> Máy Tính >  >> Hệ thống >> Android

Cách làm cho hoạt ảnh Kotlin Android của bạn có thể truy cập được

Khi nghiên cứu các ví dụ về đóng góp Android đầu tiên, có rất ít ví dụ về hoạt ảnh được viết bằng Kotlin. Cũng có một vài ví dụ mã về các cân nhắc khả năng tiếp cận trong các hoạt ảnh gốc.

Vì vậy, chúng ta bắt đầu! Hãy xem cách viết hoạt ảnh gốc ‘mở rộng’ trong Kotlin và nói về cách hỗ trợ những người bật TalkBack hoặc văn bản phóng to. Tất cả mã có sẵn trong repo ví dụ này, tạo một hoạt động duy nhất với chế độ xem hoạt hình bên trong nó. Mã này dựa trên được đồng viết với Calum Turner.

Cách làm cho hoạt ảnh Kotlin Android của bạn có thể truy cập được
GIF của kết quả ứng dụng cuối

Trợ năng Android (a11y)

Tất cả các thiết bị Android đều có trình đọc màn hình tích hợp có tên TalkBack. Bạn có thể bật tùy chọn này từ cài đặt của thiết bị và cũng có hướng dẫn sử dụng lần đầu tiên được tích hợp sẵn. Các cử chỉ được sử dụng để điều hướng xung quanh trang, với phần mô tả về các phần tử tập trung được đọc to. Nếu không có điều này, một ứng dụng sẽ không thể sử dụng được đối với nhiều người dùng khiếm thị.

Điều quan trọng chính là các yếu tố chính xác có thể lấy tiêu điểm, có mô tả và các thay đổi đối với chế độ xem được thông báo.

Trong cùng một menu cài đặt, có thể điều chỉnh kích thước phông chữ cơ sở mặc định, thay đổi tỷ lệ từ 1,0. Chế độ xem phải phản ứng với sự thay đổi này về kích thước phông chữ, với tất cả các phần tử vẫn hiện diện và hoạt động.

Bố cục

Chúng tôi sẽ không xem xét các chi tiết cụ thể về kiểu dáng của bố cục ở đây vì chúng khá độc đáo đối với ví dụ này, nhưng các điểm tiếp cận rất đáng để làm nổi bật.

Hai thuộc tính được sử dụng:android:contentDescriptionandroid:importantForAccessibility .

contentDescription là những gì được đọc khi một phần tử đạt được tiêu điểm. Đối với bất kỳ ImageView nào có được tiêu điểm, điều này là cần thiết, nếu không, thay vào đó, trình đọc màn hình sẽ đọc 'không được gắn nhãn' vô ích cho người dùng.

Nếu đây là một nút, nó sẽ đọc nút ‘, nhấn đúp để kích hoạt’ theo mặc định, nhưng đối với biểu tượng ImageView, chúng tôi chỉ định hành động theo cách thủ công vì chúng tôi không có mặc định này.

android:contentDescription="tap to toggle extra person information"

Chúng tôi cũng sử dụng importantForAccessibility:no để TẮT tiêu điểm cho TextView ‘+’, vì văn bản bên dưới hai huy hiệu cung cấp mô tả và do đó, dấu ‘+’ sẽ khó hiểu hơn là hữu ích nếu đọc to.

Đối với cả hai điều này, kiểm tra thủ công trên thiết bị thực có bật TalkBack là dấu hiệu tốt nhất để biết ngữ cảnh có hợp lý không khi không có hình ảnh.

Mở rộng hoạt ảnh

Hoạt ảnh của chúng tôi sẽ kích hoạt khi nhấn vào biểu tượng 'thông tin', chuyển đổi việc mở rộng phần chi tiết.

Chúng tôi sẽ thực hiện tất cả điều này bên trong một hoạt động duy nhất để cho phép tập trung đơn giản vào mã hoạt ảnh. Trong một ứng dụng thế giới thực, chế độ xem này được áp dụng có nhiều khả năng nằm trong chế độ xem phân mảnh hoặc trình tái chế của chính nó, do đó, một cấu trúc mã trừu tượng hơn sẽ được sử dụng.

Đặt trình nghe

Trong hoạt động mẫu của chúng tôi onCreate trước tiên chúng ta phải thiết lập một trình lắng nghe trên biểu tượng của chúng tôi và chuyển vào chế độ xem sẽ được chuyển đổi.

infoIcon.setOnClickListener { toggleCardBody(root.personEntryBody) }

Chúng tôi cũng thiết lập một biến trong lớp để theo dõi xem chế độ xem có bị bật / tắt hay không, đặt chế độ xem ban đầu là đóng.

private var isToggled = false

Chuyển đổi mở rộng hoạt ảnh

Trong bố cục của chúng tôi, chúng tôi đã đặt chiều cao của personEntryBody thành 0dp .

Để chuyển sang chế độ mở này, chúng ta cần biết chiều cao mới để đặt, độ dài của hoạt ảnh và chiều cao của nó tại mỗi thời điểm của hoạt ảnh.

Sau đó, chúng ta cần đặt isToggled nghịch đảo của nó và đảm bảo rằng khi được nhấn lại, nó sẽ ngược lại.

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()
}

Vì chiều cao khi chế độ xem được vẽ ban đầu là 0, chúng ta phải tính kích thước mới của nó bằng cách đo lại bố cục của nó.

Như được mô tả trong tài liệu về bố cục chế độ xem Android, chúng ta có thể sử dụng measure() cùng với các thông số bố cục mà chúng tôi đã gán cho chế độ xem để đo mỗi khi nhấn vào biểu tượng thông tin.

Để tính toán chiều cao tối đa, chúng tôi phải thêm phần đệm trên và dưới theo cách thủ công, vì chúng không được bao gồm trong chiều cao đo được.

Tùy thuộc vào isToggled sau đó chúng tôi biết liệu chúng tôi đang bắt đầu từ 0 hay bắt đầu từ chiều cao tối đa được mở rộng và do đó, chiều cao mục tiêu đối lập.

Chúng tôi sử dụng Value Animator để di chuyển từ giá trị bắt đầu sang giá trị cuối mục tiêu và đặt thời lượng tính bằng mili giây. Thời lượng này hoàn toàn dựa trên thử nghiệm thủ công sau này để có trải nghiệm người dùng.

ValueAnimator
        .ofInt(startHeight, targetHeight)
        .setDuration(200)

Chúng tôi gắn thời lượng với chiều cao với trình nghe cập nhật, yêu cầu vẽ bố cục mới sau mỗi lần cập nhật và điều chỉnh chiều cao mỗi lần.

    expandAnimator.addUpdateListener {
        val value = it.animatedValue as Int
        body.layoutParams.height = value
        body.requestLayout()
    }

    expandAnimator.doOnEnd {
        isToggled = !isToggled
    }

    expandAnimator.start()

Khi chúng tôi đang sử dụng Kotlin, chúng tôi cũng thêm androidx thư viện tới build.gradle của chúng tôi để hưởng lợi từ doOnEnd của nó sự mở rộng. Điều này cho phép chúng ta dễ dàng đảo ngược isToggled biến.

Cuối cùng, chúng tôi bắt đầu hoạt ảnh của chúng tôi! Chúng ta đã có một phần thân có thể mở rộng và co lại khi chạm vào biểu tượng!

Hoạt ảnh mượt mà hơn

Mặc dù hoạt ảnh của chúng tôi về mặt kỹ thuật vẫn hoạt động như hiện nay, nhưng một bước bổ sung tuyệt vời là thêm bộ nội suy để chuyển động có cảm giác tự nhiên hơn.

expandAnimator.interpolator = FastOutSlowInInterpolator()

Tăng khả năng tiếp cận của chúng tôi

Chúng tôi sẽ bổ sung hai điều cuối cùng để hy vọng sẽ giúp ích cho người dùng a11y của chúng tôi.

Đầu tiên, chúng tôi có thể trợ giúp điều hướng bằng AccessibilityEvent .

expandAnimator.doOnEnd {
    if (!isToggled)       body.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
    isToggled = !isToggled
}

Điều này có nghĩa là khi hoạt ảnh chuyển từ đóng sang mở, tiêu điểm sẽ ngay lập tức chuyển đến tiêu điểm trên mục đầu tiên trong nội dung, trong trường hợp này là mô tả. Trong bố cục, chúng tôi đặt mô tả về hành động của biểu tượng thông tin, nhưng vì chúng tôi có thể không dựa vào chỉ báo trực quan để người dùng chuyển sang mục tiếp theo nên chúng tôi có thể xử lý việc này cho họ.

Thứ hai, chúng tôi cho phép các kích thước phông chữ khác nhau. Chiều cao đo được trả về từ measure() không tính đến tỷ lệ phông chữ được đặt trong cài đặt trợ năng của thiết bị và do đó, khi ở tỷ lệ lớn, phần dưới cùng của mô tả sẽ bị cắt vì nó quá lớn để vừa.

Chúng tôi có thể truy cập tỷ lệ phông chữ theo lập trình và chia tỷ lệ chiều cao của chúng tôi dựa trên điều này. Chúng tôi chuyển đổi nó thành một số nguyên vì tỷ lệ phông chữ có thể dẫn đến một số float sẽ không hoạt động như một chiều cao bố cục.

val a11yFontScale = body.context.resources.configuration.fontScale
val maxHeight = ((body.measuredHeight + body.paddingTop + body.paddingBottom) * a11yFontScale).toInt()

Đã xong!

Cách làm cho hoạt ảnh Kotlin Android của bạn có thể truy cập được
Ảnh GIF kết quả ứng dụng cuối

Và chúng tôi có nó, chúng tôi đã đến hình ảnh động cuối cùng của chúng tôi! Chỉ với một vài dòng bổ sung, chúng tôi đã tăng đáng kể phạm vi phủ sóng a11y của nó và có một phần mở rộng mượt mà để lộ huy hiệu Kotlin và Android?

Cảm ơn vì đã đọc?

Đây là một vài điều khác mà tôi đã viết gần đây:

  • Tùy chỉnh các bài kiểm tra CodeceptJS E2E
  • Thử nghiệm React với Jest và Enzyme II

Các tính năng bổ sung hữu ích

  • Bài đăng tuyệt vời về androidx của Joe Birch trên Khám phá KTX dành cho Android
  • Hướng dẫn về Trợ năng Android:Bắt đầu