5

I have been trying to implement ViewPager2 with accessibility with talk-back but focus is not moving beyond the second partial visible item. I want to traverse and scroll the viewpager2 with talkback and accessibility but was not able to achieve that.

--------------
| <item> | <item> | <item> | <item> | <item> |
--------------

Please Help me in this. I have searched a lot tried various things but nothing has worked for me.

 ViewPager2.accessibilityDelegate = object : AccessibilityDelegate() {
        override fun onRequestSendAccessibilityEvent(
            host: ViewGroup?,
            child: View?,
            event: AccessibilityEvent?
        ): Boolean {
            if (event?.eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
                ViewPager2.currentItem = ViewPager2.indexOfChild(child)
            }
            return super.onRequestSendAccessibilityEvent(host, child, event)
        }
    }
Pravesh
  • 822
  • 1
  • 8
  • 20

3 Answers3

2

I just open a bug at the android issuetracker for this problem https://issuetracker.google.com/issues/186785895

Catluc
  • 1,775
  • 17
  • 25
0

I manage to work using the below code. It is not optimised but workaround until Google fixes this issue.

val recyclerView = viewPager.getChildAt(0) as RecyclerView
        recyclerView.accessibilityDelegate = object : View.AccessibilityDelegate() {
            override fun onRequestSendAccessibilityEvent(
                host: ViewGroup?,
                child: View?,
                event: AccessibilityEvent?
            ): Boolean {
                if (event?.eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
                    val position = recyclerView.indexOfChild(child)
                    viewPager.setCurrentItem(position, true)
                    val recyclerView = viewPager.getChildAt(0) as RecyclerView
                    recyclerView.apply {
                            viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener {
                                override fun onGlobalLayout() {
                                    viewTreeObserver.removeOnGlobalLayoutListener(this)
                                    recyclerView.smoothScrollToPosition(position)
                                }
                        })
                    }
                    child?.requestFocus()
                    viewPager.requestLayout()
                }
                return super.onRequestSendAccessibilityEvent(host, child, event)
            }
        }
Chetak Bhimani
  • 459
  • 4
  • 19
0

If anyone's running into a bug with the above solution where you cannot swipe through all children: use recyclerView.getChildAdapterPosition(child) for position.

A RecyclerView may have less children than adapter items (e.g. 10 items displayed in a list of 100). In such situations, using a position with indexOfChild(child) won't allow you to swiper beyond the 10th element.

smoothScrollToPosition supports scrolling to an adapter position, and this has worked pretty smoothly for me

LeGiraffe
  • 41
  • 6