Skip to content

Commit

Permalink
xplat/js/react-native-github/packages/react-native/ReactAndroid/src/m…
Browse files Browse the repository at this point in the history
…ain/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java

Summary: Changelog: [Internal]

Differential Revision: D67912326
  • Loading branch information
Abbondanzo authored and facebook-github-bot committed Jan 8, 2025
1 parent ec72af4 commit c7e6c00
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 161 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.views.scroll

import android.view.View
import android.view.ViewGroup
import android.view.accessibility.AccessibilityEvent
import androidx.core.view.AccessibilityDelegateCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import com.facebook.react.R
import com.facebook.react.bridge.AssertionException
import com.facebook.react.bridge.ReactSoftExceptionLogger
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.uimanager.ReactAccessibilityDelegate
import com.facebook.react.uimanager.ReactAccessibilityDelegate.AccessibilityRole

internal class ReactScrollViewAccessibilityDelegate : AccessibilityDelegateCompat() {

private val TAG: String = ReactScrollViewAccessibilityDelegate::class.java.simpleName

override fun onInitializeAccessibilityEvent(host: View, event: AccessibilityEvent) {
super.onInitializeAccessibilityEvent(host, event)
if (host is ReactScrollView || host is ReactHorizontalScrollView) {
onInitializeAccessibilityEventInternal(host, event)
} else {
ReactSoftExceptionLogger.logSoftException(
TAG,
AssertionException(
("ReactScrollViewAccessibilityDelegate should only be used with ReactScrollView or ReactHorizontalScrollView, not with class: ${host.javaClass.simpleName}")))
}
}

override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
super.onInitializeAccessibilityNodeInfo(host, info)
if (host is ReactScrollView || host is ReactHorizontalScrollView) {
onInitializeAccessibilityNodeInfoInternal(host, info)
} else {
ReactSoftExceptionLogger.logSoftException(
TAG,
AssertionException(
("ReactScrollViewAccessibilityDelegate should only be used with ReactScrollView or ReactHorizontalScrollView, not with class: ${host.javaClass.simpleName}")))
}
}

private fun onInitializeAccessibilityEventInternal(view: View, event: AccessibilityEvent) {
val accessibilityCollection =
view.getTag(R.id.accessibility_collection) as? ReadableMap ?: return

event.itemCount = accessibilityCollection.getInt("itemCount")

val contentView = (view as? ViewGroup)?.getChildAt(0) as? ViewGroup ?: return

var firstVisibleIndex: Int? = null
var lastVisibleIndex: Int? = null

for (index in 0..<contentView.childCount) {
val nextChild = contentView.getChildAt(index)
val isVisible: Boolean
if (view is ReactScrollView) {
isVisible = view.isPartiallyScrolledInView(nextChild)
} else if (view is ReactHorizontalScrollView) {
isVisible = view.isPartiallyScrolledInView(nextChild)
} else {
return
}
var accessibilityCollectionItem: ReadableMap? =
nextChild.getTag(R.id.accessibility_collection_item) as ReadableMap

if (nextChild !is ViewGroup) {
return
}

// If this child's accessibilityCollectionItem is null, we'll check one more
// nested child.
// Happens when getItemLayout is not passed in FlatList which adds an additional
// View in the hierarchy.
if (nextChild.childCount > 0 && accessibilityCollectionItem == null) {
val nestedNextChild = nextChild.getChildAt(0)
if (nestedNextChild != null) {
val nestedChildAccessibility =
nestedNextChild.getTag(R.id.accessibility_collection_item) as? ReadableMap
if (nestedChildAccessibility != null) {
accessibilityCollectionItem = nestedChildAccessibility
}
}
}

if (isVisible && accessibilityCollectionItem != null) {
if (firstVisibleIndex == null) {
firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex")
}
lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex")
}

if (firstVisibleIndex != null && lastVisibleIndex != null) {
event.fromIndex = firstVisibleIndex
event.toIndex = lastVisibleIndex
}
}
}

private fun onInitializeAccessibilityNodeInfoInternal(
view: View,
info: AccessibilityNodeInfoCompat
) {
val accessibilityRole = AccessibilityRole.fromViewTag(view)

if (accessibilityRole != null) {
ReactAccessibilityDelegate.setRole(info, accessibilityRole, view.context)
}

val accessibilityCollection = view.getTag(R.id.accessibility_collection) as? ReadableMap

if (accessibilityCollection != null) {
val rowCount = accessibilityCollection.getInt("rowCount")
val columnCount = accessibilityCollection.getInt("columnCount")
val hierarchical = accessibilityCollection.getBoolean("hierarchical")

val collectionInfoCompat =
AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain(
rowCount, columnCount, hierarchical)
info.setCollectionInfo(collectionInfoCompat)
}

if (view is ReactScrollView) {
info.isScrollable = view.scrollEnabled
} else if (view is ReactHorizontalScrollView) {
info.isScrollable = view.scrollEnabled
}
}
}

0 comments on commit c7e6c00

Please sign in to comment.