Tăng khả năng tiếp cận cho các thành phần hiển thị tuỳ chỉnh

Nếu ứng dụng của bạn đòi hỏi một thành phần hiển thị tuỳ chỉnh, bạn phải thực hiện thêm một số thao tác để giúp thành phần hiển thị đó trở nên dễ truy cập hơn. Dưới đây là những nhiệm vụ chính cần làm để cải thiện khả năng truy cập của thành phần hiển thị tuỳ chỉnh:

  • Xử lý các lượt nhấn của thành phần điều khiển hướng
  • Triển khai các phương thức API hỗ trợ tiếp cận
  • Gửi các đối tượng AccessibilityEvent dành riêng cho thành phần hiển thị tuỳ chỉnh của bạn
  • Điền vào AccessibilityEventAccessibilityNodeInfo cho thành phần hiển thị của bạn

Xử lý các lượt nhấn của thành phần điều khiển hướng

Trên hầu hết các thiết bị, thao tác sử dụng một thành phần điều khiển hướng nhấn vào một thành phần hiển thị sẽ gửi một KeyEventKEYCODE_DPAD_CENTER đến thành phần hiển thị hiện đang có tâm điểm. Tất cả thành phần hiển thị Android tiêu chuẩn đều đã xử lý KEYCODE_DPAD_CENTER một cách thích hợp. Khi xây dựng một thành phần điều khiển View tuỳ chỉnh, hãy đảm bảo sự kiện này có tác dụng tương tự như thành phần hiển thị trên màn hình cảm ứng.

Thành phần điều khiển tuỳ chỉnh của bạn cũng sẽ xem sự kiện KEYCODE_ENTER tương tự như KEYCODE_DPAD_CENTER. Phương pháp này giúp người dùng tương tác từ một bàn phím đầy đủ dễ dàng hơn nhiều.

Triển khai các phương thức API hỗ trợ tiếp cận

Sự kiện hỗ trợ tiếp cận là những thông báo về hoạt động tương tác của người dùng với các thành phần giao diện trực quan trong ứng dụng của bạn. Những thông báo này do Dịch vụ Hỗ trợ tiếp cận (Accessibility Services) xử lý. Dịch vụ này sử dụng thông tin trong các sự kiện này để tạo ý kiến phản hồi và các lời nhắc bổ sung. Trong Android 4.0 (API cấp 14) trở lên, các phương thức để tạo sự kiện hỗ trợ tiếp cận đã được mở rộng để cung cấp thông tin chi tiết hơn so với giao diện AccessibilityEventSource được giới thiệu trong Android 1.6 (API cấp 4). Các phương thức hỗ trợ tiếp cận được mở rộng là một phần của lớp View cũng như lớp View.AccessibilityDelegate. Các phương thức này bao gồm như sau:

sendAccessibilityEvent()
(API cấp 4) Phương thức này được gọi khi người dùng thực hiện hành động trên một thành phần hiển thị. Sự kiện này được phân loại theo kiểu hành động của người dùng, chẳng hạn như TYPE_VIEW_CLICKED. Thường thì, trừ khi đang tạo thành phần hiển thị tuỳ chỉnh, bạn sẽ không cần triển khai phương thức này.
sendAccessibilityEventUnchecked()
(API cấp 4) Phương thức này được dùng khi mã gọi đến cần trực tiếp điều khiển việc kiểm tra trạng thái bật của chức năng hỗ trợ tiếp cận trên thiết bị (AccessibilityManager.isEnabled()). Nếu triển khai phương thức này, bạn phải thực hiện lệnh gọi như khi chức năng hỗ trợ tiếp cận được bật, bất kể chế độ cài đặt thực tế của hệ thống. Thông thường, bạn không cần triển khai phương thức này đối với thành phần hiển thị tuỳ chỉnh.
dispatchPopulateAccessibilityEvent()
(API cấp 4) Hệ thống sẽ gọi phương thức này khi thành phần hiển thị tuỳ chỉnh của bạn tạo ra một sự kiện hỗ trợ tiếp cận. Kể từ API cấp 14, phương thức triển khai mặc định của phương thức này sẽ gọi onPopulateAccessibilityEvent() cho thành phần hiển thị này và sau đó là phương thức dispatchPopulateAccessibilityEvent() cho mỗi thành phần con của thành phần hiển thị này. Để hỗ trợ dịch vụ hỗ trợ tiếp cận trên các bản sửa đổi của Android trước phiên bản 4.0 (API cấp 14), bạn phải ghi đè phương thức này và điền getText() bằng văn bản mô tả cho thành phần hiển thị tuỳ chỉnh của bạn, văn bản này sẽ được đọc bằng các dịch vụ hỗ trợ tiếp cận, chẳng hạn như TalkBack.
onPopulateAccessibilityEvent()
(API cấp 14) Phương thức này sẽ thiết lập lời nhắc bằng văn bản nói của AccessibilityEvent dành cho thành phần hiển thị của bạn. Phương thức này cũng được gọi nếu thành phần hiển thị là con của thành phần hiển thị tạo ra một sự kiện hỗ trợ tiếp cận.

Lưu ý: Việc sửa đổi các thuộc tính bổ sung khác (ngoài văn bản) trong phương thức này có thể ghi đè các thuộc tính do các phương thức khác thiết lập. Mặc dù bạn có thể sửa đổi các thuộc tính của sự kiện hỗ trợ tiếp cận bằng phương thức này, nhưng bạn nên hạn chế thực hiện các thay đổi này đối với nội dung văn bản, và sử dụng phương thức onInitializeAccessibilityEvent() để sửa đổi các thuộc tính khác của sự kiện.

Lưu ý: Nếu phương thức triển khai của sự kiện này ghi đè toàn bộ văn bản đầu ra mà không cho phép các phần khác trong bố cục sửa đổi nội dung của sự kiện, thì bạn không được gọi phương thức triển khai lớp cha của phương thức này trong mã của bạn.

onInitializeAccessibilityEvent()
(API cấp 14) Hệ thống gọi phương thức này để lấy thêm thông tin về trạng thái của thành phần hiển thị, ngoài nội dung văn bản. Nếu thành phần hiển thị tuỳ chỉnh của bạn cung cấp chức năng kiểm soát tương tác ngoài một TextView hoặcButton đơn giản, bạn nên ghi đè phương thức này và thiết lập thông tin bổ sung về thành phần hiển thị vào sự kiện sử dụng phương thức này, chẳng hạn như kiểu trường mật khẩu, kiểu hộp đánh dấu hoặc kiểu trạng thái cung cấp tương tác hoặc phản hồi cho người dùng. Nếu bạn ghi đè phương thức này, bạn phải gọi phương thức triển khai lớp cha của phương thức này, sau đó chỉ sửa đổi các thuộc tính chưa được lớp cha thiết lập.
onInitializeAccessibilityNodeInfo()
(API cấp 14) Phương thức này cung cấp cho các dịch vụ hỗ trợ tiếp cận thông tin về trạng thái của thành phần hiển thị. Phương thức triển khai View mặc định có một tập hợp các thuộc tính thành phần hiển thị chuẩn. Nhưng nếu thành phần hiển thị tuỳ chỉnh của bạn cung cấp chức năng kiểm soát tương tác ngoài một TextView hoặc Button đơn giản, bạn nên ghi đè phương thức này và thiết lập thông tin bổ sung về thành phần hiển thị vào đối tượng AccessibilityNodeInfo được xử lý bởi phương thức này.
onRequestSendAccessibilityEvent()
(API cấp 14) Hệ thống gọi phương thức này khi một thành phần con của thành phần hiển thị của bạn đã tạo một AccessibilityEvent. Bước này cho phép thành phần hiển thị cha sửa đổi sự kiện hỗ trợ tiếp cận bằng thông tin bổ sung. Bạn chỉ nên triển khai phương thức này nếu thành phần hiển thị tuỳ chỉnh của bạn có thể có thành phần con và nếu thành phần hiển thị cha có thể cung cấp thông tin về bối cảnh cho sự kiện hỗ trợ tiếp cận có thể hữu ích cho các dịch vụ hỗ trợ tiếp cận.

Để hỗ trợ các phương thức hỗ trợ tiếp cận này cho một thành phần hiển thị tuỳ chỉnh, bạn nên làm theo một trong các phương pháp sau:

  • Nếu ứng dụng của bạn nhắm đến Android 4.0 (API cấp 14) trở lên, hãy ghi đè và triển khai các phương thức hỗ trợ tiếp cận được liệt kê ở trên trực tiếp trong lớp thành phần hiển thị tuỳ chỉnh của bạn.
  • Nếu thành phần hiển thị tuỳ chỉnh của bạn dự định tương thích với Android 1.6 (API cấp 4) trở lên, hãy thêm Thư viện hỗ trợ Android, Bản sửa đổi 5 trở lên vào dự án của bạn. Sau đó, trong lớp thành phần hiển thị tuỳ chỉnh, hãy gọi phương thức ViewCompat.setAccessibilityDelegate() để triển khai các phương thức hỗ trợ tiếp cận ở trên. Để biết ví dụ về phương pháp này, hãy xem Thư viện hỗ trợ Android (Bản sửa đổi 5 trở lên) mẫu AccessibilityDelegateSupportActivity trong (<sdk>/extras/android/support/v4/samples/Support4Demos/)

Trong cả hai trường hợp, bạn nên triển khai các phương thức hỗ trợ tiếp cận sau đây cho lớp thành phần hiển thị tuỳ chỉnh:

Để biết thêm thông tin về cách triển khai các phương thức này, hãy xem phần Điền các sự kiện hỗ trợ tiếp cận.

Gửi các sự kiện hỗ trợ tiếp cận

Tuỳ thuộc vào các chi tiết cụ thể của thành phần hiển thị tuỳ chỉnh, bạn có thể cần gửi các đối tượng AccessibilityEvent vào các thời điểm khác nhau hoặc cho các sự kiện không được triển khai theo cách mặc định. Lớp View cung cấp phương thức triển khai mặc định cho các kiểu sự kiện này:

Lưu ý: Các sự kiện di chuột được liên kết với tính năng Explore by Touch. Tính năng này sử dụng các sự kiện di chuột để kích hoạt âm thanh cho các phần tử giao diện người dùng.

Nói chung, bạn nên gửi AccessibilityEvent bất cứ khi nào nội dung trong thành phần hiển thị tuỳ chỉnh của bạn thay đổi. Chẳng hạn, nếu bạn đang triển khai một thanh trượt tuỳ chỉnh cho phép người dùng chọn một giá trị số bằng cách nhấn vào các mũi tên trái hoặc phải, thì thành phần hiển thị tuỳ chỉnh của bạn sẽ gửi đi một sự kiện thuộc kiểu TYPE_VIEW_TEXT_CHANGED bất cứ khi nào giá trị của thanh trượt thay đổi. Mã mẫu sau đây minh họa việc sử dụng phương thức sendAccessibilityEvent() để báo cáo sự kiện này.

Kotlin

override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
    return when(keyCode) {
        KeyEvent.KEYCODE_DPAD_LEFT -> {
            currentValue--
            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED)
            true
        }
        ...
    }
}

Java

@Override
public boolean onKeyUp (int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
        currentValue--;
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
        return true;
    }
    ...
}

Điền các sự kiện hỗ trợ tiếp cận

Mỗi AccessibilityEvent có một tập hợp các thuộc tính bắt buộc để mô tả trạng thái hiện tại của thành phần hiển thị. Các thuộc tính này bao gồm các thông tin về thành phần hiển thị như: tên lớp, mô tả về nội dung và trạng thái đã đánh dấu. Các thuộc tính cụ thể bắt buộc đối với từng loại sự kiện được mô tả trong tài liệu tham khảo về AccessibilityEvent. Phương thức triển khai View cung cấp các giá trị mặc định cho các thuộc tính này. Nhiều giá trị trong số này, bao gồm tên lớp và dấu thời gian của sự kiện, được cung cấp tự động. Nếu bạn đang tạo một thành phần hiển thị tuỳ chỉnh, bạn phải cung cấp một số thông tin về nội dung và đặc điểm của thành phần hiển thị đó. Thông tin này có thể đơn giản như nhãn nút nhấn, nhưng cũng có thể bao gồm thông tin bổ sung về trạng thái mà bạn muốn thêm vào sự kiện.

Yêu cầu tối thiểu để cung cấp thông tin cho các dịch vụ hỗ trợ tiếp cận có sử dụng thành phần hiển thị tuỳ chỉnh là triển khai dispatchPopulateAccessibilityEvent(). Phương thức này được hệ thống gọi để yêu cầu thông tin cho AccessibilityEvent và giúp thành phần hiển thị tuỳ chỉnh của bạn tương thích với các dịch vụ hỗ trợ tiếp cận trên Android 1.6 (API cấp 4) trở lên. Mã sau đây minh họa về cách triển khai cơ bản của phương thức này.

Kotlin

override fun dispatchPopulateAccessibilityEvent(event: AccessibilityEvent): Boolean {
    // Call the super implementation to populate its text to the event, which
    // calls onPopulateAccessibilityEvent() on API Level 14 and up.
    return super.dispatchPopulateAccessibilityEvent(event).let { completed ->

        // In case this is running on a API revision earlier that 14, check
        // the text content of the event and add an appropriate text
        // description for this custom view:
        if (text?.isNotEmpty() == true) {
            event.text.add(text)
            true
        } else {
            completed
        }
    }
}

Java

@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
    // Call the super implementation to populate its text to the event, which
    // calls onPopulateAccessibilityEvent() on API Level 14 and up.
    boolean completed = super.dispatchPopulateAccessibilityEvent(event);

    // In case this is running on a API revision earlier that 14, check
    // the text content of the event and add an appropriate text
    // description for this custom view:
    CharSequence text = getText();
    if (!TextUtils.isEmpty(text)) {
        event.getText().add(text);
        return true;
    }
    return completed;
}

Đối với Android 4.0 (API cấp 14) trở lên, hãy sử dụng phương thức onPopulateAccessibilityEvent()onInitializeAccessibilityEvent() để điền hoặc sửa đổi thông tin trong AccessibilityEvent. Sử dụng phương thức onPopulateAccessibilityEvent() dành riêng cho việc thêm hoặc sửa đổi nội dung văn bản của sự kiện. Nội dung này sẽ được các dịch vụ hỗ trợ tiếp cận (như TalkBack) chuyển thành lời nhắc âm thanh. Sử dụng phương thức onInitializeAccessibilityEvent() để điền thêm thông tin về sự kiện, chẳng hạn như trạng thái lựa chọn của thành phần hiển thị.

Ngoài ra, hãy triển khai phương thức onInitializeAccessibilityNodeInfo(). Sau khi nhận sự kiện hỗ trợ tiếp cận, các đối tượng AccessibilityNodeInfo được điền bằng phương thức này sẽ được các dịch vụ hỗ trợ tiếp cận sử dụng để kiểm tra hệ phân cấp thành phần hiển thị đã tạo ra sự kiện đó, để nhận thông tin chi tiết hơn về bối cảnh và cung cấp ý kiến phản hồi phù hợp cho người dùng.

Mã ví dụ bên dưới cho thấy cách ghi đè ba phương thức này bằng cách sử dụng ViewCompat.setAccessibilityDelegate(). Xin lưu ý rằng mã mẫu này yêu cầu bạn thêm Thư viện hỗ trợ Android dành cho API cấp 4 (Bản sửa đổi 5 trở lên) vào dự án của bạn.

Kotlin

ViewCompat.setAccessibilityDelegate(this, object : AccessibilityDelegateCompat() {

    override fun onPopulateAccessibilityEvent(host: View, event: AccessibilityEvent) {
        super.onPopulateAccessibilityEvent(host, event)
        // We call the super implementation to populate its text for the
        // event. Then we add our text not present in a super class.
        // Very often you only need to add the text for the custom view.
        if (text?.isNotEmpty() == true) {
            event.text.add(text)
        }
    }

    override fun onInitializeAccessibilityEvent(host: View, event: AccessibilityEvent) {
        super.onInitializeAccessibilityEvent(host, event);
        // We call the super implementation to let super classes
        // set appropriate event properties. Then we add the new property
        // (checked) which is not supported by a super class.
        event.isChecked = isChecked()
    }

    override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
        super.onInitializeAccessibilityNodeInfo(host, info)
        // We call the super implementation to let super classes set
        // appropriate info properties. Then we add our properties
        // (checkable and checked) which are not supported by a super class.
        info.isCheckable = true
        info.isChecked = isChecked()
        // Quite often you only need to add the text for the custom view.
        if (text?.isNotEmpty() == true) {
            info.text = text
        }
    }
})

Java

ViewCompat.setAccessibilityDelegate(new AccessibilityDelegateCompat() {
    @Override
    public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
        super.onPopulateAccessibilityEvent(host, event);
        // We call the super implementation to populate its text for the
        // event. Then we add our text not present in a super class.
        // Very often you only need to add the text for the custom view.
        CharSequence text = getText();
        if (!TextUtils.isEmpty(text)) {
            event.getText().add(text);
        }
    }
    @Override
    public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(host, event);
        // We call the super implementation to let super classes
        // set appropriate event properties. Then we add the new property
        // (checked) which is not supported by a super class.
        event.setChecked(isChecked());
    }
    @Override
    public void onInitializeAccessibilityNodeInfo(View host,
            AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);
        // We call the super implementation to let super classes set
        // appropriate info properties. Then we add our properties
        // (checkable and checked) which are not supported by a super class.
        info.setCheckable(true);
        info.setChecked(isChecked());
        // Quite often you only need to add the text for the custom view.
        CharSequence text = getText();
        if (!TextUtils.isEmpty(text)) {
            info.setText(text);
        }
    }
}

Bạn có thể triển khai các phương thức này trực tiếp trong lớp thành phần hiển thị tuỳ chỉnh. Để tìm hiểu một ví dụ khác về phương pháp này, hãy xem Thư viện hỗ trợ Android (Bản sửa đổi 5 trở lên) mẫu AccessibilityDelegateSupportActivity trong (<sdk>/extras/android/support/v4/samples/Support4Demos/).

Cung cấp bối cảnh hỗ trợ tiếp cận tuỳ chỉnh

Trong Android 4.0 (API cấp 14), khung này đã được tăng cường để cho phép các dịch vụ hỗ trợ tiếp cận kiểm tra hệ thống phân cấp thành phần hiển thị có chứa một thành phần giao diện người dùng có tạo ra một sự kiện hỗ trợ tiếp cận. Tính năng tăng cường này cho phép các dịch vụ hỗ trợ tiếp cận cung cấp nhiều thông tin theo bối cảnh hơn để hỗ trợ người dùng.

Có một số trường hợp mà dịch vụ hỗ trợ tiếp cận không thể nhận được đầy đủ thông tin từ hệ thống phân cấp thành phần hiển thị. Ví dụ: thành phần điều khiển giao diện tuỳ chỉnh có hai hoặc nhiều khu vực có thể nhấn riêng biệt (chẳng hạn như thành phần điều khiển Lịch). Trong trường hợp này, các dịch vụ không thể nhận đủ thông tin vì các phần phụ có thể nhấn không nằm trong hệ thống phân cấp thành phần hiển thị.

Hình 1. Thành phần hiển thị tuỳ chỉnh Lịch có các phần tử Ngày có thể chọn.

Trong ví dụ minh hoạ trong Hình 1, toàn bộ lịch được triển khai dưới dạng một thành phần hiển thị duy nhất. Vì vậy, nếu bạn không làm gì khác, các dịch vụ hỗ trợ tiếp cận sẽ không nhận đủ thông tin về nội dung của thành phần hiển thị và lựa chọn của người dùng trong thành phần hiển thị. Ví dụ: nếu người dùng nhấn vào ô chứa ngày 17 thì khung hỗ trợ tiếp cận sẽ chỉ nhận được thông tin mô tả của toàn bộ thành phần điều khiển Lịch. Trong trường hợp này, dịch vụ hỗ trợ tiếp cận TalkBack sẽ chỉ đọc thông báo "Lịch", hoặc tốt hơn một chút thì sẽ đọc "Lịch tháng tư", và người dùng sẽ vẫn thắc mắc về ngày đã chọn.

Để cung cấp đầy đủ thông tin bối cảnh cho các dịch vụ hỗ trợ tiếp cận trong những tình huống như vậy, khung hỗ trợ tiếp cận sẽ cung cấp một cách thức để chỉ định một hệ thống phân cấp thành phần hiển thị ảo. Hệ thống phân cấp thành phần hiển thị ảo là một cách giúp các nhà phát triển ứng dụng cung cấp một hệ thống phân cấp thành phần hiển thị bổ sung cho các dịch vụ hỗ trợ tiếp cận để phù hợp hơn với thông tin thực tế trên màn hình. Phương pháp này cho phép các dịch vụ hỗ trợ tiếp cận cung cấp thêm thông tin hữu ích cho người dùng về bối cảnh.

Một tình huống khác mà bạn có thể cần phải sử dụng hệ phân cấp thành phần hiển thị ảo là giao diện người dùng chứa một nhóm các thành phần điều khiển (thành phần hiển thị) có chức năng liên quan chặt chẽ, trong đó thao tác trên một thành phần điều khiển sẽ ảnh hưởng đến nội dung của một hoặc nhiều phần tử, chẳng hạn như bộ chọn số với các nút lên và xuống riêng biệt. Trong trường hợp này, các dịch vụ hỗ trợ tiếp cận không thể nhận được đầy đủ thông tin vì hành động trên một thành phần điều khiển sẽ thay đổi nội dung trong thành phần điều khiển khác và mối quan hệ của các thành phần điều khiển đó có thể không rõ ràng đối với dịch vụ hỗ trợ tiếp cận. Để xử lý tình huống này, hãy nhóm các thành phần điều khiển có liên quan bằng một thành phần hiển thị để chứa tất cả, và cung cấp một hệ thống phân cấp thành phần hiển thị ảo từ vùng chứa này để thể hiện rõ thông tin và hành vi do các thành phần điều khiển cung cấp.

Để cung cấp hệ thống phân cấp thành phần hiển thị ảo cho một thành phần hiển thị, hãy ghi đè phương thức getAccessibilityNodeProvider() trong thành phần hiển thị hoặc nhóm thành phần hiển thị tuỳ chỉnh của bạn và trả về một phương thức triển khai của AccessibilityNodeProvider. Để xem ví dụ triển khai tính năng hỗ trợ tiếp cận này, hãy xem AccessibilityNodeProviderActivity trong dự án mẫu ApiDemos. Bạn có thể triển khai một hệ phân cấp thành phần hiển thị ảo tương thích với Android 1.6 trở lên bằng cách sử dụngThư viện hỗ trợ với phương thức ViewCompat.getAccessibilityNodeProvider() và cung cấp phương thức triển khai AccessibilityNodeProviderCompat.

Xử lý sự kiện nhấn tuỳ chỉnh

Các thành phần điều khiển hiển thị tuỳ chỉnh có thể yêu cầu hành vi sự kiện nhấn không chuẩn mực, như được minh họa trong các ví dụ sau.

Khai báo các hành động dựa trên lượt nhấn

Nếu tiện ích widget của bạn sử dụng OnClickListener hoặc OnLongClickListener hoặc giao diện, hệ thống sẽ xử lý hành động ACTION_CLICK và hành động ACTION_LONG_CLICK cho bạn. Tuy nhiên, nếu ứng dụng của bạn sử dụng một tiện ích widget được tuỳ chỉnh nhiều hơn dựa trên giao diện OnTouchListener, thì bạn cần khai báo trình xử lý tuỳ chỉnh cho các hành động hỗ trợ tiếp cận dựa trên lượt nhấn. Để thực hiện việc này, hãy gọi phương thức replaceAccessibilityAction() cho từng hành động, như minh họa trong đoạn mã sau đây:

Kotlin

// Assumes that the widget is designed to select text when tapped and select
// all text when long-tapped. In its strings.xml file, this app has set
// "select" to "Select" and "select_all" to "Select all", respectively.
ViewCompat.replaceAccessibilityAction(
            WIDGET,
            ACTION_CLICK,
            context.getString(R.string.select)
) { view, commandArguments ->
    selectText()
}

ViewCompat.replaceAccessibilityAction(
            WIDGET,
            ACTION_LONG_CLICK,
            context.getString(R.string.select_all)
) { view, commandArguments ->
    selectAllText()
}

Java

// Assumes that the widget is designed to select text when tapped and select
// all text when long-tapped. In its strings.xml file, this app has set
// "select" to "Select" and "select_all" to "Select all", respectively.
ViewCompat.replaceAccessibilityAction(WIDGET, ACTION_CLICK,
        context.getString(R.string.select),
        (view, commandArguments) -> {
            selectText();
        });

ViewCompat.replaceAccessibilityAction(WIDGET, ACTION_LONG_CLICK,
        context.getString(R.string.select_all),
        (view, commandArguments) -> {
            selectAllText();
        });

Tạo sự kiện lượt nhấn tuỳ chỉnh

Một thành phần điều khiển tuỳ chỉnh có thể sử dụng phương thức trình nghe onTouchEvent(MotionEvent) để phát hiện các sự kiện ACTION_DOWNACTION_UP và kích hoạt một sự kiện nhấn đặc biệt. Để duy trì khả năng tương thích với các dịch vụ hỗ trợ tiếp cận, mã xử lý sự kiện nhấn tuỳ chỉnh này phải làm như sau:

  1. Tạo một AccessibilityEvent thích hợp cho hành động nhấn được diễn giải.
  2. Bật dịch vụ hỗ trợ tiếp cận để thực hiện thao tác nhấn tuỳ chỉnh cho những người dùng không thể sử dụng màn hình cảm ứng.

Để xử lý các yêu cầu này một cách hiệu quả, mã của bạn phải ghi đè phương thức performClick(). Phương thức này phải gọi phương thức triển khai lớp cha của mình và sau đó thực thi bất kỳ hành động nào mà sự kiện nhấn yêu cầu. Khi phát hiện hành động nhấn tuỳ chỉnh, mã đó sẽ gọi phương thức performClick() của bạn. Mã ví dụ sau đây minh họa mẫu này.

Kotlin

class CustomTouchView(context: Context) : View(context) {

    var downTouch = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        super.onTouchEvent(event)

        // Listening for the down and up touch events
        return when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                downTouch = true
                true
            }

            MotionEvent.ACTION_UP -> if (downTouch) {
                downTouch = false
                performClick() // Call this method to handle the response, and
                // thereby enable accessibility services to
                // perform this action for a user who cannot
                // click the touchscreen.
                true
            } else {
                false
            }

            else -> false  // Return false for other touch events
        }
    }

    override fun performClick(): Boolean {
        // Calls the super implementation, which generates an AccessibilityEvent
        // and calls the onClick() listener on the view, if any
        super.performClick()

        // Handle the action for the custom click here

        return true
    }
}

Java

class CustomTouchView extends View {

    public CustomTouchView(Context context) {
        super(context);
    }

    boolean downTouch = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        // Listening for the down and up touch events
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downTouch = true;
                return true;

            case MotionEvent.ACTION_UP:
                if (downTouch) {
                    downTouch = false;
                    performClick(); // Call this method to handle the response, and
                                    // thereby enable accessibility services to
                                    // perform this action for a user who cannot
                                    // click the touchscreen.
                    return true;
                }
        }
        return false; // Return false for other touch events
    }

    @Override
    public boolean performClick() {
        // Calls the super implementation, which generates an AccessibilityEvent
        // and calls the onClick() listener on the view, if any
        super.performClick();

        // Handle the action for the custom click here

        return true;
    }
}

Mẫu nêu trên đảm bảo rằng sự kiện lượt nhấn tuỳ chỉnh tương thích với các dịch vụ hỗ trợ tiếp cận bằng cách sử dụng phương thức performClick() để vừa tạo một sự kiện hỗ trợ tiếp cận, vừa cung cấp một điểm truy cập để các dịch vụ hỗ trợ tiếp cận thay mặt cho người dùng thực hiện sự kiện nhấn tuỳ chỉnh này.

Lưu ý: Nếu thành phần hiển thị tuỳ chỉnh của bạn có các vùng có thể nhấn riêng biệt (chẳng hạn như thành phần hiển thị tuỳ chỉnh Lịch) thì bạn phải triển khai hệ thống phân cấp thành phần hiển thị ảo bằng cách ghi đè getAccessibilityNodeProvider() trong thành phần hiển thị tuỳ chỉnh của bạn nhằm tương thích với các dịch vụ hỗ trợ tiếp cận