From 26d37b7595bd4288978c42eaf82f98be4292346c Mon Sep 17 00:00:00 2001 From: Nishan Bende Date: Sun, 6 Jun 2021 14:28:26 +0530 Subject: [PATCH 01/66] announce showing x of y items in flatlist --- Libraries/Lists/VirtualizedList.js | 30 ++++++++- .../react/uimanager/BaseViewManager.java | 14 +++++ .../uimanager/BaseViewManagerAdapter.java | 6 ++ .../uimanager/ReactAccessibilityDelegate.java | 61 +++++++++++++++++++ .../interfaces/BaseViewManagerDelegate.java | 6 ++ .../interfaces/BaseViewManagerInterface.java | 4 ++ .../react/uimanager/interfaces/ViewProps.java | 2 + .../main/res/views/uimanager/values/ids.xml | 8 ++- 8 files changed, 127 insertions(+), 4 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 976b22705e5df3..6b47fd23b90238 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1236,6 +1236,15 @@ class VirtualizedList extends React.PureComponent { _defaultRenderScrollComponent = props => { const onRefresh = props.onRefresh; + const accessibilityCollectionProps = { + accessibilityRole: 'list', + accessibilityCollectionInfo: { + rowCount: this.props.getItemCount(this.props.data), + columnCount: 1, + hierarchical: false, + }, + }; + if (this._isNestedWithSameOrientation()) { // $FlowFixMe[prop-missing] - Typing ReactNativeComponent revealed errors return ; @@ -1246,9 +1255,11 @@ class VirtualizedList extends React.PureComponent { JSON.stringify(props.refreshing ?? 'undefined') + '`', ); + return ( // $FlowFixMe[prop-missing] Invalid prop usage { ); } else { // $FlowFixMe[prop-missing] Invalid prop usage - return ; + return ; } }; @@ -2064,11 +2075,23 @@ class CellRenderer extends React.Component< : horizontal ? [styles.row, inversionStyle] : inversionStyle; + + const accessibilityCollectionItemInfo = { + rowIndex: index, + rowSpan: 1, + columnIndex: 1, + columnSpan: 1, + heading: false, + }; + const result = !CellRendererComponent ? ( /* $FlowFixMe[incompatible-type-arg] (>=0.89.0 site=react_native_fb) * This comment suppresses an error found when Flow v0.89 was deployed. * To see the error, delete this comment and run Flow. */ - + {element} {itemSeparator} @@ -2076,7 +2099,8 @@ class CellRenderer extends React.Component< + onLayout={onLayout} + accessibilityCollectionItemInfo={accessibilityCollectionItemInfo}> {element} {itemSeparator} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index 25579c4c292f6b..bcb6edb023d411 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -151,6 +151,7 @@ public void setAccessibilityHint(@NonNull T view, @Nullable String accessibility updateViewContentDescription(view); } + @Override @ReactProp(name = ViewProps.ACCESSIBILITY_ROLE) public void setAccessibilityRole(@NonNull T view, @Nullable String accessibilityRole) { @@ -160,6 +161,19 @@ public void setAccessibilityRole(@NonNull T view, @Nullable String accessibility view.setTag(R.id.accessibility_role, AccessibilityRole.fromValue(accessibilityRole)); } + + @Override + @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION_INFO) + public void setAccessibilityCollectionInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionInfo) { + view.setTag(R.id.accessibility_collection_info, accessibilityCollectionInfo); + } + + @Override + @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION_ITEM_INFO) + public void setAccessibilityCollectionItemInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionItemInfo) { + view.setTag(R.id.accessibility_collection_item_info, accessibilityCollectionItemInfo); + } + @Override @ReactProp(name = ViewProps.ACCESSIBILITY_STATE) public void setViewState(@NonNull T view, @Nullable ReadableMap accessibilityState) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java index c0e21dece66f2a..e202a91fe5d7bc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java @@ -30,6 +30,12 @@ public void setAccessibilityLiveRegion(@NonNull T view, @Nullable String liveReg @Override public void setAccessibilityRole(@NonNull T view, @Nullable String accessibilityRole) {} + @Override + public void setAccessibilityCollectionInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionInfo) {} + + @Override + public void setAccessibilityCollectionItemInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionItemInfo) {} + @Override public void setViewState(@NonNull T view, @Nullable ReadableMap accessibilityState) {} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index 78c83a38611ab3..2e260f9324db84 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -8,12 +8,14 @@ package com.facebook.react.uimanager; import android.content.Context; +import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.SpannableString; import android.text.style.URLSpan; import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import androidx.annotation.Nullable; import androidx.core.view.AccessibilityDelegateCompat; @@ -107,6 +109,7 @@ public enum AccessibilityRole { TAB, TABLIST, TIMER, + LIST, TOOLBAR; public static String getValue(AccessibilityRole role) { @@ -135,6 +138,8 @@ public static String getValue(AccessibilityRole role) { return "android.widget.SpinButton"; case SWITCH: return "android.widget.Switch"; + case LIST: + return "android.widget.AbsListView"; case NONE: case LINK: case SUMMARY: @@ -204,6 +209,20 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo } final ReadableArray accessibilityActions = (ReadableArray) host.getTag(R.id.accessibility_actions); + final ReadableMap accessibilityCollectionInfo = + (ReadableMap) host.getTag(R.id.accessibility_collection_info); + + + if (accessibilityCollectionInfo != null) { + int rowCount = accessibilityCollectionInfo.getInt("rowCount"); + int columnCount = accessibilityCollectionInfo.getInt("columnCount"); + boolean hierarchical = accessibilityCollectionInfo.getBoolean("hierarchical"); + + AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain(rowCount, columnCount, hierarchical); + info.setCollectionInfo(collectionInfoCompat); + } + + if (accessibilityActions != null) { for (int i = 0; i < accessibilityActions.size(); i++) { final ReadableMap action = accessibilityActions.getMap(i); @@ -259,12 +278,54 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo } } + private boolean isViewVisible(View scrollView, View view) { + Rect scrollBounds = new Rect(); + scrollView.getDrawingRect(scrollBounds); + float viewHeight = view.getHeight(); + // Verify View is half visible + float top = view.getY() + viewHeight / 2; + float bottom = top + view.getHeight() - viewHeight / 2; + + if (scrollBounds.top < top && scrollBounds.bottom > bottom) { + return true; + } else { + return false; + } + } + @Override public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); // Set item count and current item index on accessibility events for adjustable // in order to make Talkback announce the value of the adjustable final ReadableMap accessibilityValue = (ReadableMap) host.getTag(R.id.accessibility_value); + final ReadableMap accessibilityCollectionInfo = (ReadableMap) host.getTag(R.id.accessibility_collection_info); + if (accessibilityCollectionInfo != null) { + event.setItemCount(accessibilityCollectionInfo.getInt("rowCount")); + + View contentView = ((ViewGroup) host).getChildAt(0); + + ReadableMap firstVisible = null; + ReadableMap lastVisible = null; + + for(int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { + View nextChild = ((ViewGroup) contentView).getChildAt(index); + boolean isVisible = isViewVisible(host, nextChild); + if (isVisible == true) { + if(firstVisible == null) { + firstVisible = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); + } + lastVisible = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); + } + + + if (firstVisible != null && lastVisible != null) { + event.setFromIndex(firstVisible.getInt("rowIndex")); + event.setToIndex(lastVisible.getInt("rowIndex")); + } + } + } + if (accessibilityValue != null && accessibilityValue.hasKey("min") && accessibilityValue.hasKey("now") diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java index 1598b578877b2f..452bde73552e61 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java @@ -47,6 +47,12 @@ public void setProperty(T view, String propName, @Nullable Object value) { case ViewProps.ACCESSIBILITY_STATE: mViewManager.setViewState(view, (ReadableMap) value); break; + case ViewProps.ACCESSIBILITY_COLLECTION_INFO: + mViewManager.setAccessibilityCollectionInfo(view, (ReadableMap) value); + break; + case ViewProps.ACCESSIBILITY_COLLECTION_ITEM_INFO: + mViewManager.setAccessibilityCollectionItemInfo(view, (ReadableMap) value); + break; case ViewProps.BACKGROUND_COLOR: mViewManager.setBackgroundColor( view, value == null ? 0 : ColorPropConverter.getColor(value, view.getContext())); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java index 5423eeedd91a71..e20654208398d7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java @@ -26,6 +26,10 @@ public interface BaseViewManagerInterface { void setAccessibilityLiveRegion(T view, @Nullable String liveRegion); void setAccessibilityRole(T view, @Nullable String accessibilityRole); + + void setAccessibilityCollectionInfo(T view, @Nullable ReadableMap accessibilityCollectionInfo); + + void setAccessibilityCollectionItemInfo(T view, @Nullable ReadableMap accessibilityCollectionItemInfo); void setViewState(T view, @Nullable ReadableMap accessibilityState); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java index 2327b364980dae..9cec3cafdd6e25 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java @@ -145,6 +145,8 @@ public class ViewProps { public static final String Z_INDEX = "zIndex"; public static final String RENDER_TO_HARDWARE_TEXTURE = "renderToHardwareTextureAndroid"; public static final String ACCESSIBILITY_LABEL = "accessibilityLabel"; + public static final String ACCESSIBILITY_COLLECTION_INFO = "accessibilityCollectionInfo"; + public static final String ACCESSIBILITY_COLLECTION_ITEM_INFO = "accessibilityCollectionItemInfo"; public static final String ACCESSIBILITY_HINT = "accessibilityHint"; public static final String ACCESSIBILITY_LIVE_REGION = "accessibilityLiveRegion"; public static final String ACCESSIBILITY_ROLE = "accessibilityRole"; diff --git a/ReactAndroid/src/main/res/views/uimanager/values/ids.xml b/ReactAndroid/src/main/res/views/uimanager/values/ids.xml index 6886defd469257..37ab9d1796ec1d 100644 --- a/ReactAndroid/src/main/res/views/uimanager/values/ids.xml +++ b/ReactAndroid/src/main/res/views/uimanager/values/ids.xml @@ -15,7 +15,13 @@ - + + + + + + + From ec09520b4086952f04876b2a1e1e07ad888e5a32 Mon Sep 17 00:00:00 2001 From: Nishan Bende Date: Sun, 20 Jun 2021 12:18:15 +0530 Subject: [PATCH 02/66] feat: grid accessibility announcement in flatlist --- ...roidHorizontalScrollViewNativeComponent.js | 1 + Libraries/Lists/FlatList.js | 64 +++++++++- Libraries/Lists/VirtualizedList.js | 34 +----- .../uimanager/ReactAccessibilityDelegate.java | 68 +++-------- .../scroll/ReactHorizontalScrollView.java | 70 +++++++++++ .../ReactHorizontalScrollViewManager.java | 7 ++ .../react/views/scroll/ReactScrollView.java | 113 ++++++++++++++++++ 7 files changed, 270 insertions(+), 87 deletions(-) diff --git a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js index 05f629e01a1d1e..aaaeda859feaf9 100644 --- a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js @@ -36,6 +36,7 @@ const AndroidHorizontalScrollViewNativeComponent: HostComponent = NativeC snapToStart: true, snapToOffsets: true, contentOffset: true, + accessibilityCollectionInfo: true, }, }), ); diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index b9008a028a78ca..9bac80e1c2acce 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -606,11 +606,29 @@ class FlatList extends React.PureComponent, void> { return ( {item.map((it, kk) => { - const element = renderer({ - item: it, - index: index * numColumns + kk, - separators: info.separators, - }); + const accessibilityCollectionItemInfo = { + rowIndex: index, + rowSpan: 1, + columnIndex: (index * numColumns + kk) % numColumns, + columnSpan: 1, + heading: false, + itemIndex: index * numColumns + kk, + }; + + const element = ( + + {renderer({ + item: it, + index: index * numColumns + kk, + separators: info.separators, + })} + + ); return element != null ? ( {element} ) : null; @@ -618,12 +636,41 @@ class FlatList extends React.PureComponent, void> { ); } else { - return renderer(info); + const {index} = info; + + const accessibilityCollectionItemInfo = { + rowIndex: index, + rowSpan: 1, + columnIndex: 0, + columnSpan: 1, + heading: false, + itemIndex: index, + }; + + return ( + + {renderer(info)} + + ); } }, }; }; + _getAccessibilityCollectionInfo = () => { + const accessibilityCollectionProps = { + itemCount: this.props.data ? this.props.data.length : 0, + rowCount: this._getItemCount(this.props.data), + columnCount: this.props.numColumns, + hierarchical: false, + }; + + return accessibilityCollectionProps; + }; + render(): React.Node { const {numColumns, columnWrapperStyle, ...restProps} = this.props; @@ -633,6 +680,10 @@ class FlatList extends React.PureComponent, void> { getItem={this._getItem} getItemCount={this._getItemCount} keyExtractor={this._keyExtractor} + accessibilityCollectionInfo={this._getAccessibilityCollectionInfo()} + accessibilityRole={Platform.select({ + android: this.props.numColumns > 1 ? 'grid' : 'list', + })} ref={this._captureRef} viewabilityConfigCallbackPairs={this._virtualizedListPairs} {...this._renderer()} @@ -643,6 +694,7 @@ class FlatList extends React.PureComponent, void> { const styles = StyleSheet.create({ row: {flexDirection: 'row'}, + cellStyle: {flex: 1}, }); module.exports = FlatList; diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 6b47fd23b90238..605ff026c2c03d 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1236,15 +1236,6 @@ class VirtualizedList extends React.PureComponent { _defaultRenderScrollComponent = props => { const onRefresh = props.onRefresh; - const accessibilityCollectionProps = { - accessibilityRole: 'list', - accessibilityCollectionInfo: { - rowCount: this.props.getItemCount(this.props.data), - columnCount: 1, - hierarchical: false, - }, - }; - if (this._isNestedWithSameOrientation()) { // $FlowFixMe[prop-missing] - Typing ReactNativeComponent revealed errors return ; @@ -1255,11 +1246,9 @@ class VirtualizedList extends React.PureComponent { JSON.stringify(props.refreshing ?? 'undefined') + '`', ); - return ( // $FlowFixMe[prop-missing] Invalid prop usage { ); } else { // $FlowFixMe[prop-missing] Invalid prop usage - return ; + return ; } }; @@ -2075,23 +2064,11 @@ class CellRenderer extends React.Component< : horizontal ? [styles.row, inversionStyle] : inversionStyle; - - const accessibilityCollectionItemInfo = { - rowIndex: index, - rowSpan: 1, - columnIndex: 1, - columnSpan: 1, - heading: false, - }; - const result = !CellRendererComponent ? ( /* $FlowFixMe[incompatible-type-arg] (>=0.89.0 site=react_native_fb) * - This comment suppresses an error found when Flow v0.89 was deployed. * - To see the error, delete this comment and run Flow. */ - + This comment suppresses an error found when Flow v0.89 was deployed. * + To see the error, delete this comment and run Flow. */ + {element} {itemSeparator} @@ -2099,8 +2076,7 @@ class CellRenderer extends React.Component< + onLayout={onLayout}> {element} {itemSeparator} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index 2e260f9324db84..bca92f774b85ac 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -110,6 +110,7 @@ public enum AccessibilityRole { TABLIST, TIMER, LIST, + GRID, TOOLBAR; public static String getValue(AccessibilityRole role) { @@ -140,6 +141,8 @@ public static String getValue(AccessibilityRole role) { return "android.widget.Switch"; case LIST: return "android.widget.AbsListView"; + case GRID: + return "android.widget.GridView"; case NONE: case LINK: case SUMMARY: @@ -209,20 +212,20 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo } final ReadableArray accessibilityActions = (ReadableArray) host.getTag(R.id.accessibility_actions); - final ReadableMap accessibilityCollectionInfo = - (ReadableMap) host.getTag(R.id.accessibility_collection_info); - - if (accessibilityCollectionInfo != null) { - int rowCount = accessibilityCollectionInfo.getInt("rowCount"); - int columnCount = accessibilityCollectionInfo.getInt("columnCount"); - boolean hierarchical = accessibilityCollectionInfo.getBoolean("hierarchical"); - - AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain(rowCount, columnCount, hierarchical); - info.setCollectionInfo(collectionInfoCompat); + final ReadableMap accessibilityCollectionItemInfo = + (ReadableMap) host.getTag(R.id.accessibility_collection_item_info); + if (accessibilityCollectionItemInfo != null) { + int rowIndex = accessibilityCollectionItemInfo.getInt("rowIndex"); + int columnIndex = accessibilityCollectionItemInfo.getInt("columnIndex"); + int rowSpan = accessibilityCollectionItemInfo.getInt("rowSpan"); + int columnSpan = accessibilityCollectionItemInfo.getInt("columnSpan"); + boolean heading = accessibilityCollectionItemInfo.getBoolean("heading"); + + AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfoCompat = AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading); + info.setCollectionItemInfo(collectionItemInfoCompat); } - if (accessibilityActions != null) { for (int i = 0; i < accessibilityActions.size(); i++) { final ReadableMap action = accessibilityActions.getMap(i); @@ -278,53 +281,13 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo } } - private boolean isViewVisible(View scrollView, View view) { - Rect scrollBounds = new Rect(); - scrollView.getDrawingRect(scrollBounds); - float viewHeight = view.getHeight(); - // Verify View is half visible - float top = view.getY() + viewHeight / 2; - float bottom = top + view.getHeight() - viewHeight / 2; - if (scrollBounds.top < top && scrollBounds.bottom > bottom) { - return true; - } else { - return false; - } - } - @Override public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); // Set item count and current item index on accessibility events for adjustable // in order to make Talkback announce the value of the adjustable final ReadableMap accessibilityValue = (ReadableMap) host.getTag(R.id.accessibility_value); - final ReadableMap accessibilityCollectionInfo = (ReadableMap) host.getTag(R.id.accessibility_collection_info); - if (accessibilityCollectionInfo != null) { - event.setItemCount(accessibilityCollectionInfo.getInt("rowCount")); - - View contentView = ((ViewGroup) host).getChildAt(0); - - ReadableMap firstVisible = null; - ReadableMap lastVisible = null; - - for(int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { - View nextChild = ((ViewGroup) contentView).getChildAt(index); - boolean isVisible = isViewVisible(host, nextChild); - if (isVisible == true) { - if(firstVisible == null) { - firstVisible = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); - } - lastVisible = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); - } - - - if (firstVisible != null && lastVisible != null) { - event.setFromIndex(firstVisible.getInt("rowIndex")); - event.setToIndex(lastVisible.getInt("rowIndex")); - } - } - } if (accessibilityValue != null && accessibilityValue.hasKey("min") @@ -499,7 +462,8 @@ public static void setDelegate(final View view) { && (view.getTag(R.id.accessibility_role) != null || view.getTag(R.id.accessibility_state) != null || view.getTag(R.id.accessibility_actions) != null - || view.getTag(R.id.react_test_id) != null)) { + || view.getTag(R.id.react_test_id) != null + || view.getTag(R.id.accessibility_collection_item_info) != null)) { ViewCompat.setAccessibilityDelegate(view, new ReactAccessibilityDelegate()); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 0304f0e06783e3..d0d1939cd4c578 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -21,6 +21,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.widget.HorizontalScrollView; import android.widget.OverScroller; @@ -30,6 +31,8 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.R; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.ReactConstants; @@ -38,6 +41,7 @@ import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactAccessibilityDelegate; import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ViewProps; @@ -122,6 +126,55 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); event.setScrollable(mScrollEnabled); + final ReadableMap accessibilityCollectionInfo = (ReadableMap) host.getTag(R.id.accessibility_collection_info); + + if (accessibilityCollectionInfo != null) { + event.setItemCount(accessibilityCollectionInfo.getInt("itemCount")); + View contentView = getContentView(); + Integer firstVisibleIndex = null; + Integer lastVisibleIndex = null; + + if (!(contentView instanceof ViewGroup)) { + return; + } + + for(int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { + View nextChild = ((ViewGroup) contentView).getChildAt(index); + boolean isVisible = isPartiallyScrolledInView(nextChild); + + ReadableMap accessibilityCollectionItemInfo = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); + + if (!(nextChild instanceof ViewGroup)) { + return; + } + + int childCount = ((ViewGroup) nextChild).getChildCount(); + + // If this child's accessibilityCollectionItemInfo 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 (childCount > 0 && accessibilityCollectionItemInfo == null) { + View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); + if (nestedNextChild != null) { + ReadableMap nestedChildAccessibilityInfo = (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item_info); + if (nestedChildAccessibilityInfo != null) { + accessibilityCollectionItemInfo = nestedChildAccessibilityInfo; + } + } + } + + if (isVisible == true && accessibilityCollectionItemInfo != null) { + if(firstVisibleIndex == null) { + firstVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex"); + } + lastVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex");; + } + + if (firstVisibleIndex != null && lastVisibleIndex != null) { + event.setFromIndex(firstVisibleIndex); + event.setToIndex(lastVisibleIndex); + } + } + } } @Override @@ -129,6 +182,23 @@ public void onInitializeAccessibilityNodeInfo( View host, AccessibilityNodeInfoCompat info) { super.onInitializeAccessibilityNodeInfo(host, info); info.setScrollable(mScrollEnabled); + final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = + (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); + + if (accessibilityRole != null) { + ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); + } + + final ReadableMap accessibilityCollectionInfo = (ReadableMap) host.getTag(R.id.accessibility_collection_info); + + if (accessibilityCollectionInfo != null) { + int rowCount = accessibilityCollectionInfo.getInt("rowCount"); + int columnCount = accessibilityCollectionInfo.getInt("columnCount"); + boolean hierarchical = accessibilityCollectionInfo.getBoolean("hierarchical"); + + AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain(rowCount, columnCount, hierarchical); + info.setCollectionInfo(collectionInfoCompat); + } } }); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java index 05112f45e449ad..16481172c3aa73 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java @@ -9,8 +9,10 @@ import android.graphics.Color; import android.util.DisplayMetrics; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; +import com.facebook.react.R; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.module.annotations.ReactModule; @@ -164,6 +166,11 @@ public void setPagingEnabled(ReactHorizontalScrollView view, boolean pagingEnabl view.setPagingEnabled(pagingEnabled); } + @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION_INFO) + public void setAccessibilityCollectionInfo(ReactHorizontalScrollView view, @Nullable ReadableMap accessibilityCollectionInfo) { + view.setTag(R.id.accessibility_collection_info, accessibilityCollectionInfo); + } + /** Controls overScroll behaviour */ @ReactProp(name = "overScrollMode") public void setOverScrollMode(ReactHorizontalScrollView view, String value) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 6a2273b989960b..d2f9bfac20b1b3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -20,13 +20,18 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.widget.OverScroller; import android.widget.ScrollView; import androidx.annotation.Nullable; +import androidx.core.view.AccessibilityDelegateCompat; import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.R; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.ReactConstants; @@ -34,6 +39,7 @@ import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.PixelUtil; +import com.facebook.react.uimanager.ReactAccessibilityDelegate; import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ViewProps; @@ -69,6 +75,7 @@ public class ReactScrollView extends ScrollView private final @Nullable OverScroller mScroller; private final VelocityHelper mVelocityHelper = new VelocityHelper(); private final Rect mRect = new Rect(); // for reuse to avoid allocation + private final Rect mTempRect = new Rect(); private boolean mActivelyScrolling; private @Nullable Rect mClippingRect; @@ -109,6 +116,12 @@ public ReactScrollView(ReactContext context) { this(context, null); } + + private View getContentView() { + View contentView = getChildAt(0); + return contentView; + } + public ReactScrollView(ReactContext context, @Nullable FpsListener fpsListener) { super(context); mFpsListener = fpsListener; @@ -117,6 +130,93 @@ public ReactScrollView(ReactContext context, @Nullable FpsListener fpsListener) mScroller = getOverScrollerFromParent(); setOnHierarchyChangeListener(this); setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY); + + ViewCompat.setAccessibilityDelegate( + this, + new AccessibilityDelegateCompat() { + + @Override + public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(host, event); + event.setScrollable(mScrollEnabled); + final ReadableMap accessibilityCollectionInfo = (ReadableMap) host.getTag(R.id.accessibility_collection_info); + + if (accessibilityCollectionInfo != null) { + event.setItemCount(accessibilityCollectionInfo.getInt("itemCount")); + View contentView = getContentView(); + Integer firstVisibleIndex = null; + Integer lastVisibleIndex = null; + + if (!(contentView instanceof ViewGroup)) { + return; + } + + for(int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { + View nextChild = ((ViewGroup) contentView).getChildAt(index); + boolean isVisible = isPartiallyScrolledInView(nextChild); + + ReadableMap accessibilityCollectionItemInfo = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); + + if (!(nextChild instanceof ViewGroup)) { + return; + } + + int childCount = ((ViewGroup) nextChild).getChildCount(); + + // If this child's accessibilityCollectionItemInfo 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 (childCount > 0 && accessibilityCollectionItemInfo == null) { + View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); + if (nestedNextChild != null) { + ReadableMap nestedChildAccessibilityInfo = (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item_info); + if (nestedChildAccessibilityInfo != null) { + accessibilityCollectionItemInfo = nestedChildAccessibilityInfo; + } + } + } + + if (isVisible == true && accessibilityCollectionItemInfo != null) { + if(firstVisibleIndex == null) { + firstVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex"); + } + lastVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex");; + } + + if (firstVisibleIndex != null && lastVisibleIndex != null) { + event.setFromIndex(firstVisibleIndex); + event.setToIndex(lastVisibleIndex); + } + } + } + } + + @Override + public void onInitializeAccessibilityNodeInfo( + View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + + final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = + (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); + + if (accessibilityRole != null) { + ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); + } + + final ReadableMap accessibilityCollectionInfo = (ReadableMap) host.getTag(R.id.accessibility_collection_info); + + if (accessibilityCollectionInfo != null) { + int rowCount = accessibilityCollectionInfo.getInt("rowCount"); + int columnCount = accessibilityCollectionInfo.getInt("columnCount"); + boolean hierarchical = accessibilityCollectionInfo.getBoolean("hierarchical"); + + AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain(rowCount, columnCount, hierarchical); + info.setCollectionInfo(collectionInfoCompat); + } + + info.setScrollable(mScrollEnabled); + } + }); + } @Nullable @@ -263,6 +363,19 @@ public void requestChildFocus(View child, View focused) { super.requestChildFocus(child, focused); } + private int getScrollDelta(View descendent) { + descendent.getDrawingRect(mTempRect); + offsetDescendantRectToMyCoords(descendent, mTempRect); + return computeScrollDeltaToGetChildRectOnScreen(mTempRect); + } + + /** Returns whether the given descendent is partially scrolled in view */ + private boolean isPartiallyScrolledInView(View descendent) { + int scrollDelta = getScrollDelta(descendent); + descendent.getDrawingRect(mTempRect); + return scrollDelta != 0 && Math.abs(scrollDelta) < mTempRect.width(); + } + private void scrollToChild(View child) { Rect tempRect = new Rect(); child.getDrawingRect(tempRect); From 55877da014228ef32efbf15575c93f049bcd9b4c Mon Sep 17 00:00:00 2001 From: Nishan Bende Date: Sun, 20 Jun 2021 12:28:28 +0530 Subject: [PATCH 03/66] feat: nested flatlist example --- .../js/examples/FlatList/FlatList-nested.js | 109 ++++++++++++++++++ .../js/utils/RNTesterList.android.js | 5 + 2 files changed, 114 insertions(+) create mode 100644 packages/rn-tester/js/examples/FlatList/FlatList-nested.js diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-nested.js b/packages/rn-tester/js/examples/FlatList/FlatList-nested.js new file mode 100644 index 00000000000000..a27a859de28151 --- /dev/null +++ b/packages/rn-tester/js/examples/FlatList/FlatList-nested.js @@ -0,0 +1,109 @@ +import React from "react"; +import { + SafeAreaView, + View, + FlatList, + StyleSheet, + Text, + StatusBar, +} from "react-native"; + +const DATA = [ + { + id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba", + title: "First Item", + }, + { + id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63", + title: "Second Item", + }, + { + id: "58694a0f-3da1-471f-bd96-145571e29d72", + title: "Third Item", + }, + { + id: "bd7acbea-c1b1-46c2-aed5-3ad53abb8bbb", + title: "Fourth Item", + }, + { + id: "3ac68afc-c605-48d3-a4f8-fbd91aa97676", + title: "Fifth Item", + }, + { + id: "58694a0f-3da1-471f-bd96-145571e27234", + title: "Sixth Item", + }, + { + id: "58694a0f-3da1-471f-bd96-145571e29234", + title: "Seven Item", + }, + { + id: "58694a0f-3da1-471f-bd96-145571429234", + title: "Eight Item", + }, + { + id: "58694a0f-3da1-471f-bd96-115571429234", + title: "Nine Item", + }, + { + id: "58694a0f-3da1-471f-bd96-1155h1429234", + title: "Ten Item", + }, +]; + +const Item = ({ title }) => ( + + {title} + +); + +const renderItem = ({ item }) => ; + +const renderFlatList = ({ item }) => ( + + Flatlist {item} + + +); + +const FlatListNested = () => { + return ( + + item.toString()} + /> + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: StatusBar.currentHeight || 0, + }, + item: { + backgroundColor: "#f9c2ff", + padding: 20, + marginVertical: 8, + marginHorizontal: 16, + }, + title: { + fontSize: 16, + }, +}); + +exports.title = "FlatList Nested"; +exports.testTitle = "Test accessibility announcement in nested flatlist"; +exports.category = "ListView"; +exports.documentationURL = "https://reactnative.dev/docs/flatlist"; +exports.description = "Nested flatlist example"; +exports.examples = [ + { + title: "FlatList Nested example", + render: function (): React.Element { + return ; + }, + }, +]; diff --git a/packages/rn-tester/js/utils/RNTesterList.android.js b/packages/rn-tester/js/utils/RNTesterList.android.js index dcaa6330a30be9..bb921469fd1fe9 100644 --- a/packages/rn-tester/js/utils/RNTesterList.android.js +++ b/packages/rn-tester/js/utils/RNTesterList.android.js @@ -43,6 +43,11 @@ const ComponentExamples: Array = [ module: require('../examples/FlatList/FlatList-onEndReached'), category: 'ListView', }, + { + key: 'FlatList-nested', + module: require('../examples/FlatList/FlatList-nested'), + category: 'ListView', + }, { key: 'ImageExample', category: 'Basic', From 49aec36bba82d93e6eed753cd75e358ce23f7c4c Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 24 Feb 2022 09:37:49 +0800 Subject: [PATCH 04/66] Remove .gitattributes causing error add_cacheinfo More info at https://github.com/fabriziobertoglio1987/react-native-notes/issues/8 https://github.com/facebook/react-native/pull/31128#issuecomment-825986802 >If you want to see how these files are actually stored: >Remove .gitattributes (so that no conversion happens) I solved the problem with the following steps: 1) checkout branch I want to rebase 2) the branch was already rebased and included commit https://github.com/facebook/react-native/commit/73844712b6283dcc41805129cc8da305d5490c0b which brought `.gitattributes` file in the branch The file below triggers the error `error: add_cacheinfo failed to refresh for path 'packages/react-native-gradle-plugin/gradlew.bat'; merge aborting.` when running `git merge master`. ``` -# Windows files should use crlf line endings -# https://help.github.com/articles/dealing-with-line-endings/ -*.bat text eol=crlf ``` 3) I remove the `.gitattributes` files from the branch. 4) `git` stops converting the line ending 5) I merge main branch. `.gitattributes` files was already removed from main branch with https://github.com/facebook/react-native/pull/31398/files. Git runs the merge without problems. Also no diff because the file already deleted from main. --- .gitattributes | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 45a3dcb2a20316..00000000000000 --- a/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -# Windows files should use crlf line endings -# https://help.github.com/articles/dealing-with-line-endings/ -*.bat text eol=crlf From 60f77940009ee3cb8250eecf0e420669ffbde976 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 24 Feb 2022 13:26:28 +0800 Subject: [PATCH 05/66] remove duplicate method getContentView --- .../react/views/scroll/ReactHorizontalScrollView.java | 1 + .../com/facebook/react/views/scroll/ReactScrollView.java | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index ae2a919ddeca1c..56e4cf343303cc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -42,6 +42,7 @@ import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.PointerEvents; +import com.facebook.react.uimanager.ReactAccessibilityDelegate; import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ReactOverflowViewWithInset; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 37f314b52cbb4d..7fe0078eada396 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -114,11 +114,6 @@ public ReactScrollView(Context context) { this(context, null); } - private View getContentView() { - View contentView = getChildAt(0); - return contentView; - } - public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { super(context); mFpsListener = fpsListener; From 062cdcd107e150fce8be8978eee85ab13e0b2a14 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 24 Feb 2022 13:26:42 +0800 Subject: [PATCH 06/66] fix Runtime Error NoSuchKey exception columnCount numColums default was removed with commit https://github.com/fabriziobertoglio1987/react-native-notes/commit/7d5895df4e3c57ebfa1c146cadc989497b006623 More info at https://github.com/fabriziobertoglio1987/react-native-notes/issues/6#issuecomment-1032340879 --- Libraries/Lists/FlatList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 535a52ff03ac3e..e5bad0253c41ee 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -672,7 +672,7 @@ class FlatList extends React.PureComponent, void> { const accessibilityCollectionProps = { itemCount: this.props.data ? this.props.data.length : 0, rowCount: this._getItemCount(this.props.data), - columnCount: this.props.numColumns, + columnCount: numColumnsOrDefault(this.props.numColumns), hierarchical: false, }; From 78b5fe36018d44702525d591cb5bd591ae047fab Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 24 Feb 2022 14:25:23 +0800 Subject: [PATCH 07/66] rename accessibilityCollectionInfo to accessibilityCollection https://github.com/facebook/react-native/pull/31666#issuecomment-859100710 --- ...roidHorizontalScrollViewNativeComponent.js | 2 +- Libraries/Lists/FlatList.js | 14 +++--- .../react/uimanager/BaseViewManager.java | 16 +++---- .../uimanager/BaseViewManagerAdapter.java | 6 ++- .../uimanager/ReactAccessibilityDelegate.java | 18 ++++---- .../interfaces/BaseViewManagerDelegate.java | 8 ++-- .../interfaces/BaseViewManagerInterface.java | 8 ++-- .../react/uimanager/interfaces/ViewProps.java | 4 +- .../scroll/ReactHorizontalScrollView.java | 39 ++++++++--------- .../ReactHorizontalScrollViewManager.java | 8 ++-- .../react/views/scroll/ReactScrollView.java | 43 +++++++++---------- .../main/res/views/uimanager/values/ids.xml | 8 ++-- 12 files changed, 86 insertions(+), 88 deletions(-) diff --git a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js index c641e8f29840e7..142dc1c6b0ceec 100644 --- a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js @@ -36,7 +36,7 @@ const AndroidHorizontalScrollViewNativeComponent: HostComponent = snapToStart: true, snapToOffsets: true, contentOffset: true, - accessibilityCollectionInfo: true, + accessibilityCollection: true, borderBottomLeftRadius: true, borderBottomRightRadius: true, borderRadius: true, diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index e5bad0253c41ee..204b6ab8a57705 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -614,7 +614,7 @@ class FlatList extends React.PureComponent, void> { return ( {item.map((it, kk) => { - const accessibilityCollectionItemInfo = { + const accessibilityCollectionItem = { rowIndex: index, rowSpan: 1, columnIndex: (index * numColumns + kk) % numColumns, @@ -627,9 +627,7 @@ class FlatList extends React.PureComponent, void> { + accessibilityCollectionItem={accessibilityCollectionItem}> {renderer({ item: it, index: index * numColumns + kk, @@ -646,7 +644,7 @@ class FlatList extends React.PureComponent, void> { } else { const {index} = info; - const accessibilityCollectionItemInfo = { + const accessibilityCollectionItem = { rowIndex: index, rowSpan: 1, columnIndex: 0, @@ -659,7 +657,7 @@ class FlatList extends React.PureComponent, void> { + accessibilityCollectionItem={accessibilityCollectionItem}> {renderer(info)} ); @@ -668,7 +666,7 @@ class FlatList extends React.PureComponent, void> { }; }; - _getAccessibilityCollectionInfo = () => { + _getAccessibilityCollection = () => { const accessibilityCollectionProps = { itemCount: this.props.data ? this.props.data.length : 0, rowCount: this._getItemCount(this.props.data), @@ -693,7 +691,7 @@ class FlatList extends React.PureComponent, void> { getItem={this._getItem} getItemCount={this._getItemCount} keyExtractor={this._keyExtractor} - accessibilityCollectionInfo={this._getAccessibilityCollectionInfo()} + accessibilityCollection={this._getAccessibilityCollection()} accessibilityRole={Platform.select({ android: this.props.numColumns > 1 ? 'grid' : 'list', })} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java index af29c30bba88d4..37e49e7bf745c3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java @@ -166,7 +166,6 @@ public void setAccessibilityHint(@NonNull T view, @Nullable String accessibility updateViewContentDescription(view); } - @Override @ReactProp(name = ViewProps.ACCESSIBILITY_ROLE) public void setAccessibilityRole(@NonNull T view, @Nullable String accessibilityRole) { @@ -176,17 +175,18 @@ public void setAccessibilityRole(@NonNull T view, @Nullable String accessibility view.setTag(R.id.accessibility_role, AccessibilityRole.fromValue(accessibilityRole)); } - @Override - @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION_INFO) - public void setAccessibilityCollectionInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionInfo) { - view.setTag(R.id.accessibility_collection_info, accessibilityCollectionInfo); + @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION) + public void setAccessibilityCollection( + @NonNull T view, @Nullable ReadableMap accessibilityCollection) { + view.setTag(R.id.accessibility_collection, accessibilityCollection); } @Override - @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION_ITEM_INFO) - public void setAccessibilityCollectionItemInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionItemInfo) { - view.setTag(R.id.accessibility_collection_item_info, accessibilityCollectionItemInfo); + @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION_ITEM) + public void setAccessibilityCollectionItem( + @NonNull T view, @Nullable ReadableMap accessibilityCollectionItem) { + view.setTag(R.id.accessibility_collection_item, accessibilityCollectionItem); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java index 9f54ed8f8f5c88..afd33e22eb1ba5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java @@ -32,10 +32,12 @@ public void setAccessibilityLiveRegion(@NonNull T view, @Nullable String liveReg public void setAccessibilityRole(@NonNull T view, @Nullable String accessibilityRole) {} @Override - public void setAccessibilityCollectionInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionInfo) {} + public void setAccessibilityCollection( + @NonNull T view, @Nullable ReadableMap accessibilityCollection) {} @Override - public void setAccessibilityCollectionItemInfo(@NonNull T view, @Nullable ReadableMap accessibilityCollectionItemInfo) {} + public void setAccessibilityCollectionItem( + @NonNull T view, @Nullable ReadableMap accessibilityCollectionItem) {} @Override public void setViewState(@NonNull T view, @Nullable ReadableMap accessibilityState) {} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index faf6bc7c8f4616..aaec0050c5f267 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -223,14 +223,14 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo final ReadableArray accessibilityActions = (ReadableArray) host.getTag(R.id.accessibility_actions); - final ReadableMap accessibilityCollectionItemInfo = - (ReadableMap) host.getTag(R.id.accessibility_collection_item_info); - if (accessibilityCollectionItemInfo != null) { - int rowIndex = accessibilityCollectionItemInfo.getInt("rowIndex"); - int columnIndex = accessibilityCollectionItemInfo.getInt("columnIndex"); - int rowSpan = accessibilityCollectionItemInfo.getInt("rowSpan"); - int columnSpan = accessibilityCollectionItemInfo.getInt("columnSpan"); - boolean heading = accessibilityCollectionItemInfo.getBoolean("heading"); + final ReadableMap accessibilityCollectionItem = + (ReadableMap) host.getTag(R.id.accessibility_collection_item); + if (accessibilityCollectionItem != null) { + int rowIndex = accessibilityCollectionItem.getInt("rowIndex"); + int columnIndex = accessibilityCollectionItem.getInt("columnIndex"); + int rowSpan = accessibilityCollectionItem.getInt("rowSpan"); + int columnSpan = accessibilityCollectionItem.getInt("columnSpan"); + boolean heading = accessibilityCollectionItem.getBoolean("heading"); AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfoCompat = AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain( @@ -474,7 +474,7 @@ public static void setDelegate(final View view) { || view.getTag(R.id.accessibility_state) != null || view.getTag(R.id.accessibility_actions) != null || view.getTag(R.id.react_test_id) != null - || view.getTag(R.id.accessibility_collection_item_info) != null)) { + || view.getTag(R.id.accessibility_collection_item) != null)) { ViewCompat.setAccessibilityDelegate(view, new ReactAccessibilityDelegate()); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java index 3fe9a3c80ea743..5c2ca1b828f07a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerDelegate.java @@ -48,11 +48,11 @@ public void setProperty(T view, String propName, @Nullable Object value) { case ViewProps.ACCESSIBILITY_STATE: mViewManager.setViewState(view, (ReadableMap) value); break; - case ViewProps.ACCESSIBILITY_COLLECTION_INFO: - mViewManager.setAccessibilityCollectionInfo(view, (ReadableMap) value); + case ViewProps.ACCESSIBILITY_COLLECTION: + mViewManager.setAccessibilityCollection(view, (ReadableMap) value); break; - case ViewProps.ACCESSIBILITY_COLLECTION_ITEM_INFO: - mViewManager.setAccessibilityCollectionItemInfo(view, (ReadableMap) value); + case ViewProps.ACCESSIBILITY_COLLECTION_ITEM: + mViewManager.setAccessibilityCollectionItem(view, (ReadableMap) value); break; case ViewProps.BACKGROUND_COLOR: mViewManager.setBackgroundColor( diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java index 6837f8140b5990..0a6a9a561d5c61 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/BaseViewManagerInterface.java @@ -27,10 +27,10 @@ public interface BaseViewManagerInterface { void setAccessibilityLiveRegion(T view, @Nullable String liveRegion); void setAccessibilityRole(T view, @Nullable String accessibilityRole); - - void setAccessibilityCollectionInfo(T view, @Nullable ReadableMap accessibilityCollectionInfo); - - void setAccessibilityCollectionItemInfo(T view, @Nullable ReadableMap accessibilityCollectionItemInfo); + + void setAccessibilityCollection(T view, @Nullable ReadableMap accessibilityCollection); + + void setAccessibilityCollectionItem(T view, @Nullable ReadableMap accessibilityCollectionItem); void setViewState(T view, @Nullable ReadableMap accessibilityState); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java index 4786fdeb8e91ca..d78d1f7e5a8e8b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/interfaces/ViewProps.java @@ -146,8 +146,8 @@ public class ViewProps { public static final String Z_INDEX = "zIndex"; public static final String RENDER_TO_HARDWARE_TEXTURE = "renderToHardwareTextureAndroid"; public static final String ACCESSIBILITY_LABEL = "accessibilityLabel"; - public static final String ACCESSIBILITY_COLLECTION_INFO = "accessibilityCollectionInfo"; - public static final String ACCESSIBILITY_COLLECTION_ITEM_INFO = "accessibilityCollectionItemInfo"; + public static final String ACCESSIBILITY_COLLECTION = "accessibilityCollection"; + public static final String ACCESSIBILITY_COLLECTION_ITEM = "accessibilityCollectionItem"; public static final String ACCESSIBILITY_HINT = "accessibilityHint"; public static final String ACCESSIBILITY_LIVE_REGION = "accessibilityLiveRegion"; public static final String ACCESSIBILITY_ROLE = "accessibilityRole"; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 56e4cf343303cc..27272f4852c134 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -128,11 +128,11 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); event.setScrollable(mScrollEnabled); - final ReadableMap accessibilityCollectionInfo = - (ReadableMap) host.getTag(R.id.accessibility_collection_info); + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); - if (accessibilityCollectionInfo != null) { - event.setItemCount(accessibilityCollectionInfo.getInt("itemCount")); + if (accessibilityCollection != null) { + event.setItemCount(accessibilityCollection.getInt("itemCount")); View contentView = getContentView(); Integer firstVisibleIndex = null; Integer lastVisibleIndex = null; @@ -145,8 +145,8 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) View nextChild = ((ViewGroup) contentView).getChildAt(index); boolean isVisible = isPartiallyScrolledInView(nextChild); - ReadableMap accessibilityCollectionItemInfo = - (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); + ReadableMap accessibilityCollectionItem = + (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); if (!(nextChild instanceof ViewGroup)) { return; @@ -154,27 +154,26 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) int childCount = ((ViewGroup) nextChild).getChildCount(); - // If this child's accessibilityCollectionItemInfo is null, we'll check one more + // 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 (childCount > 0 && accessibilityCollectionItemInfo == null) { + if (childCount > 0 && accessibilityCollectionItem == null) { View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); if (nestedNextChild != null) { ReadableMap nestedChildAccessibilityInfo = - (ReadableMap) - nestedNextChild.getTag(R.id.accessibility_collection_item_info); + (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item); if (nestedChildAccessibilityInfo != null) { - accessibilityCollectionItemInfo = nestedChildAccessibilityInfo; + accessibilityCollectionItem = nestedChildAccessibilityInfo; } } } - if (isVisible == true && accessibilityCollectionItemInfo != null) { + if (isVisible == true && accessibilityCollectionItem != null) { if (firstVisibleIndex == null) { - firstVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex"); + firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); } - lastVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex"); + lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); ; } @@ -198,13 +197,13 @@ public void onInitializeAccessibilityNodeInfo( ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); } - final ReadableMap accessibilityCollectionInfo = - (ReadableMap) host.getTag(R.id.accessibility_collection_info); + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); - if (accessibilityCollectionInfo != null) { - int rowCount = accessibilityCollectionInfo.getInt("rowCount"); - int columnCount = accessibilityCollectionInfo.getInt("columnCount"); - boolean hierarchical = accessibilityCollectionInfo.getBoolean("hierarchical"); + if (accessibilityCollection != null) { + int rowCount = accessibilityCollection.getInt("rowCount"); + int columnCount = accessibilityCollection.getInt("columnCount"); + boolean hierarchical = accessibilityCollection.getBoolean("hierarchical"); AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain( diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java index 9ebb8c83289616..204f0b1956f74e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java @@ -169,10 +169,10 @@ public void setPagingEnabled(ReactHorizontalScrollView view, boolean pagingEnabl view.setPagingEnabled(pagingEnabled); } - @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION_INFO) - public void setAccessibilityCollectionInfo( - ReactHorizontalScrollView view, @Nullable ReadableMap accessibilityCollectionInfo) { - view.setTag(R.id.accessibility_collection_info, accessibilityCollectionInfo); + @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION) + public void setAccessibilityCollection( + ReactHorizontalScrollView view, @Nullable ReadableMap accessibilityCollection) { + view.setTag(R.id.accessibility_collection, accessibilityCollection); } /** Controls overScroll behaviour */ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 7fe0078eada396..dacfa05737ba55 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -131,11 +131,11 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); event.setScrollable(mScrollEnabled); - final ReadableMap accessibilityCollectionInfo = - (ReadableMap) host.getTag(R.id.accessibility_collection_info); + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); - if (accessibilityCollectionInfo != null) { - event.setItemCount(accessibilityCollectionInfo.getInt("itemCount")); + if (accessibilityCollection != null) { + event.setItemCount(accessibilityCollection.getInt("itemCount")); View contentView = getContentView(); Integer firstVisibleIndex = null; Integer lastVisibleIndex = null; @@ -148,8 +148,8 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) View nextChild = ((ViewGroup) contentView).getChildAt(index); boolean isVisible = isPartiallyScrolledInView(nextChild); - ReadableMap accessibilityCollectionItemInfo = - (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item_info); + ReadableMap accessibilityCollectionItem = + (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); if (!(nextChild instanceof ViewGroup)) { return; @@ -157,27 +157,26 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) int childCount = ((ViewGroup) nextChild).getChildCount(); - // If this child's accessibilityCollectionItemInfo is null, we'll check one more + // 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 (childCount > 0 && accessibilityCollectionItemInfo == null) { + if (childCount > 0 && accessibilityCollectionItem == null) { View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); if (nestedNextChild != null) { - ReadableMap nestedChildAccessibilityInfo = - (ReadableMap) - nestedNextChild.getTag(R.id.accessibility_collection_item_info); - if (nestedChildAccessibilityInfo != null) { - accessibilityCollectionItemInfo = nestedChildAccessibilityInfo; + ReadableMap nestedChildAccessibility = + (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item); + if (nestedChildAccessibility != null) { + accessibilityCollectionItem = nestedChildAccessibility; } } } - if (isVisible == true && accessibilityCollectionItemInfo != null) { + if (isVisible == true && accessibilityCollectionItem != null) { if (firstVisibleIndex == null) { - firstVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex"); + firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); } - lastVisibleIndex = accessibilityCollectionItemInfo.getInt("itemIndex"); + lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); ; } @@ -201,13 +200,13 @@ public void onInitializeAccessibilityNodeInfo( ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); } - final ReadableMap accessibilityCollectionInfo = - (ReadableMap) host.getTag(R.id.accessibility_collection_info); + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); - if (accessibilityCollectionInfo != null) { - int rowCount = accessibilityCollectionInfo.getInt("rowCount"); - int columnCount = accessibilityCollectionInfo.getInt("columnCount"); - boolean hierarchical = accessibilityCollectionInfo.getBoolean("hierarchical"); + if (accessibilityCollection != null) { + int rowCount = accessibilityCollection.getInt("rowCount"); + int columnCount = accessibilityCollection.getInt("columnCount"); + boolean hierarchical = accessibilityCollection.getBoolean("hierarchical"); AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain( diff --git a/ReactAndroid/src/main/res/views/uimanager/values/ids.xml b/ReactAndroid/src/main/res/views/uimanager/values/ids.xml index 806dafef9b0448..be2ec12d1c8c21 100644 --- a/ReactAndroid/src/main/res/views/uimanager/values/ids.xml +++ b/ReactAndroid/src/main/res/views/uimanager/values/ids.xml @@ -15,11 +15,11 @@ - - + + - - + + From 80acf523a4410adac8005d5c9472fb87f78e12ee Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 24 Feb 2022 15:19:31 +0800 Subject: [PATCH 08/66] rename collectionItemInfoCompat to collectionItemCompat --- .../facebook/react/uimanager/ReactAccessibilityDelegate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index aaec0050c5f267..58b5fc94aa29cf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -232,10 +232,10 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo int columnSpan = accessibilityCollectionItem.getInt("columnSpan"); boolean heading = accessibilityCollectionItem.getBoolean("heading"); - AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfoCompat = + AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemCompat = AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain( rowIndex, rowSpan, columnIndex, columnSpan, heading); - info.setCollectionItemInfo(collectionItemInfoCompat); + info.setCollectionItemInfo(collectionItemCompat); } if (accessibilityActions != null) { From 3b9a034ce9a7ac0b6f52ed80b282c3e8fc67ca35 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 24 Feb 2022 15:46:30 +0800 Subject: [PATCH 09/66] minor change --- .../java/com/facebook/react/views/scroll/ReactScrollView.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index dacfa05737ba55..ad7c6720baff33 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -177,7 +177,6 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); } lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - ; } if (firstVisibleIndex != null && lastVisibleIndex != null) { From 1563620144a2ea0c6c76c041dbffc93a81e5b1fc Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 25 Feb 2022 09:30:56 +0800 Subject: [PATCH 10/66] minor change --- .../facebook/react/views/scroll/ReactHorizontalScrollView.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 27272f4852c134..ce96c3e60e8a51 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -174,7 +174,6 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); } lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - ; } if (firstVisibleIndex != null && lastVisibleIndex != null) { From 18f7772f58d5a9fe412680dc48deca9fc9c84b61 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 09:52:22 +0800 Subject: [PATCH 11/66] yarn run lint --fix https://app.circleci.com/pipelines/github/facebook/react-native/12268/workflows/08bfaf7f-f09e-468b-810c-fd28231d72f6/jobs/237502 --- .../js/examples/FlatList/FlatList-nested.js | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-nested.js b/packages/rn-tester/js/examples/FlatList/FlatList-nested.js index a27a859de28151..120bcfa0b20b39 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-nested.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-nested.js @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; import { SafeAreaView, View, @@ -6,48 +6,48 @@ import { StyleSheet, Text, StatusBar, -} from "react-native"; +} from 'react-native'; const DATA = [ { - id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba", - title: "First Item", + id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba', + title: 'First Item', }, { - id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63", - title: "Second Item", + id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63', + title: 'Second Item', }, { - id: "58694a0f-3da1-471f-bd96-145571e29d72", - title: "Third Item", + id: '58694a0f-3da1-471f-bd96-145571e29d72', + title: 'Third Item', }, { - id: "bd7acbea-c1b1-46c2-aed5-3ad53abb8bbb", - title: "Fourth Item", + id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb8bbb', + title: 'Fourth Item', }, { - id: "3ac68afc-c605-48d3-a4f8-fbd91aa97676", - title: "Fifth Item", + id: '3ac68afc-c605-48d3-a4f8-fbd91aa97676', + title: 'Fifth Item', }, { - id: "58694a0f-3da1-471f-bd96-145571e27234", - title: "Sixth Item", + id: '58694a0f-3da1-471f-bd96-145571e27234', + title: 'Sixth Item', }, { - id: "58694a0f-3da1-471f-bd96-145571e29234", - title: "Seven Item", + id: '58694a0f-3da1-471f-bd96-145571e29234', + title: 'Seven Item', }, { - id: "58694a0f-3da1-471f-bd96-145571429234", - title: "Eight Item", + id: '58694a0f-3da1-471f-bd96-145571429234', + title: 'Eight Item', }, { - id: "58694a0f-3da1-471f-bd96-115571429234", - title: "Nine Item", + id: '58694a0f-3da1-471f-bd96-115571429234', + title: 'Nine Item', }, { - id: "58694a0f-3da1-471f-bd96-1155h1429234", - title: "Ten Item", + id: '58694a0f-3da1-471f-bd96-1155h1429234', + title: 'Ten Item', }, ]; @@ -84,7 +84,7 @@ const styles = StyleSheet.create({ marginTop: StatusBar.currentHeight || 0, }, item: { - backgroundColor: "#f9c2ff", + backgroundColor: '#f9c2ff', padding: 20, marginVertical: 8, marginHorizontal: 16, @@ -94,14 +94,14 @@ const styles = StyleSheet.create({ }, }); -exports.title = "FlatList Nested"; -exports.testTitle = "Test accessibility announcement in nested flatlist"; -exports.category = "ListView"; -exports.documentationURL = "https://reactnative.dev/docs/flatlist"; -exports.description = "Nested flatlist example"; +exports.title = 'FlatList Nested'; +exports.testTitle = 'Test accessibility announcement in nested flatlist'; +exports.category = 'ListView'; +exports.documentationURL = 'https://reactnative.dev/docs/flatlist'; +exports.description = 'Nested flatlist example'; exports.examples = [ { - title: "FlatList Nested example", + title: 'FlatList Nested example', render: function (): React.Element { return ; }, From 2a76611299aba344503e84f2121ef790bcb0d3f9 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 10:26:17 +0800 Subject: [PATCH 12/66] HorizontalSVManager has already property "accessibilityCollection". Module com.facebook.react.views.scroll.ReactHorizontalScrollViewManager has already registered a property named "accessibilityCollection". If you want to override a property, don't addthe @ReactProp annotation to the property in the subclass Errors: 1. Warnings: 2. When running . When building rule //ReactAndroid/src/main/java/com/facebook/react/views/scroll:scroll. Exited with code exit status 1 https://app.circleci.com/pipelines/github/facebook/react-native/12268/workflows/0372e966-3e3e-4289-9455-c2bb125b9e58/jobs/237511 --- .../views/scroll/ReactHorizontalScrollViewManager.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java index 204f0b1956f74e..6d4bd242dd2609 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java @@ -10,7 +10,6 @@ import android.graphics.Color; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; -import com.facebook.react.R; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.module.annotations.ReactModule; @@ -169,12 +168,6 @@ public void setPagingEnabled(ReactHorizontalScrollView view, boolean pagingEnabl view.setPagingEnabled(pagingEnabled); } - @ReactProp(name = ViewProps.ACCESSIBILITY_COLLECTION) - public void setAccessibilityCollection( - ReactHorizontalScrollView view, @Nullable ReadableMap accessibilityCollection) { - view.setTag(R.id.accessibility_collection, accessibilityCollection); - } - /** Controls overScroll behaviour */ @ReactProp(name = "overScrollMode") public void setOverScrollMode(ReactHorizontalScrollView view, String value) { From e36b2610dcd2f7400fc454e9bd21dd684924aa7e Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 12:26:46 +0800 Subject: [PATCH 13/66] fix flow errors (more info in description) - incompatible types _getItemCount(data) and this.props.data _getItemCount takes as parameter ?Array For simplicity, data is just a plain array. If you want to use something else, like an immutable list, use the underlying `VirtualizedList` directly. data: ?$ReadOnlyArray, the local variable _getItemCountInternal is only available in function _getAccessibilityCollection. ```javascript _getAccessibilityCollection = () => { const _getItemCountInternal = (data: any): number => { return this._getItemCount(data); }; ``` - for the second issue see https://github.com/facebook/react-native/pull/33180/commits/062cdcd107e150fce8be8978eee85ab13e0b2a14 Full log of the flow errors https://app.circleci.com/pipelines/github/facebook/react-native/12280/workflows/f115b583-2f98-4aaf-9525-7b981588797d/jobs/237664/steps --- Libraries/Lists/FlatList.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 204b6ab8a57705..e36e5191894321 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -667,9 +667,13 @@ class FlatList extends React.PureComponent, void> { }; _getAccessibilityCollection = () => { + const _getItemCountInternal = (data: any): number => { + return this._getItemCount(data); + }; + const accessibilityCollectionProps = { itemCount: this.props.data ? this.props.data.length : 0, - rowCount: this._getItemCount(this.props.data), + rowCount: _getItemCountInternal(this.props.data), columnCount: numColumnsOrDefault(this.props.numColumns), hierarchical: false, }; @@ -693,7 +697,8 @@ class FlatList extends React.PureComponent, void> { keyExtractor={this._keyExtractor} accessibilityCollection={this._getAccessibilityCollection()} accessibilityRole={Platform.select({ - android: this.props.numColumns > 1 ? 'grid' : 'list', + android: + numColumnsOrDefault(this.props.numColumns) > 1 ? 'grid' : 'list', })} ref={this._captureRef} viewabilityConfigCallbackPairs={this._virtualizedListPairs} From 32676ebe5f7555809c9d3e51efaff73ee287f5bd Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 13:23:54 +0800 Subject: [PATCH 14/66] Fixing type flow errors https://app.circleci.com/pipelines/github/facebook/react-native/12283/workflows/5d591d36-f972-4b3d-92b6-cf68d7d54fd4/jobs/237717 --- Libraries/Components/View/ViewPropTypes.js | 16 ++++++++++++++++ Libraries/Lists/FlatList.js | 7 ++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 4e22c3b3b53b22..2155c0feae6349 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -432,6 +432,22 @@ export type ViewProps = $ReadOnly<{| */ accessibilityActions?: ?$ReadOnlyArray, + /** + * Prop used internally to announce with TalkBack rows and columns of a FlatList + * See https://bit.ly/3viYSh8 + * + * @platform android + * + */ + accessibilityCollectionItem?: ?{ + rowIndex: number, + rowSpan: number, + columnIndex: number, + columnSpan: number, + heading: boolean, + itemIndex: number, + }, + /** * Specifies the nativeID of the associated label text. When the assistive technology focuses on the component with this props, the text is read aloud. * diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index e36e5191894321..e9d2221a15374f 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -667,13 +667,10 @@ class FlatList extends React.PureComponent, void> { }; _getAccessibilityCollection = () => { - const _getItemCountInternal = (data: any): number => { - return this._getItemCount(data); - }; - const accessibilityCollectionProps = { itemCount: this.props.data ? this.props.data.length : 0, - rowCount: _getItemCountInternal(this.props.data), + //$FlowFixMe[incompatible-call] + rowCount: this._getItemCount(this.props.data), columnCount: numColumnsOrDefault(this.props.numColumns), hierarchical: false, }; From 3a9e6d81a0549993005e56ba66a8e5132d2764af Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 15:13:36 +0800 Subject: [PATCH 15/66] jest update FlatList snapshots - adding accessibilityCollection prop to the snap The prop includes the flatlist number of columns/rows ```json { "columnCount": 2, "hierarchical": false, "itemCount": 5, "rowCount": 3, } ``` - adding accessibilityCollectionItem prop to snap The prop includes each cell row/columnIndex --- .../__snapshots__/FlatList-test.js.snap | 481 ++++++++++++++++-- 1 file changed, 430 insertions(+), 51 deletions(-) diff --git a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap index c8b33bb98df2de..9da481fe66b42b 100644 --- a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap @@ -6,6 +6,14 @@ exports[`FlatList renders all the bells and whistles 1`] = ` ListEmptyComponent={[Function]} ListFooterComponent={[Function]} ListHeaderComponent={[Function]} + accessibilityCollection={ + Object { + "columnCount": 2, + "hierarchical": false, + "itemCount": 5, + "rowCount": 3, + } + } data={ Array [ Object { @@ -67,12 +75,50 @@ exports[`FlatList renders all the bells and whistles 1`] = ` } } > - - + + + + + + @@ -86,12 +132,50 @@ exports[`FlatList renders all the bells and whistles 1`] = ` } } > - - + + + + + + @@ -105,9 +189,28 @@ exports[`FlatList renders all the bells and whistles 1`] = ` } } > - + + + - - + + + + + + - + + + @@ -237,6 +421,14 @@ exports[`FlatList renders simple list (multiple columns) 1`] = ` exports[`FlatList renders simple list 1`] = ` - + + + - + + + - + + + @@ -298,6 +547,14 @@ exports[`FlatList renders simple list 1`] = ` exports[`FlatList renders simple list using ListItemComponent (multiple columns) 1`] = ` - - + + + + + + - + + + @@ -369,6 +683,14 @@ exports[`FlatList renders simple list using ListItemComponent (multiple columns) exports[`FlatList renders simple list using ListItemComponent 1`] = ` - + + + - + + + - + + + From 7ca9acd85bab1b97b440668282c94ccaf6a8a208 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 15:38:48 +0800 Subject: [PATCH 16/66] remove accessibilityCollection from AndroidHorizontalScrollViewNativeComponent --- .../ScrollView/AndroidHorizontalScrollViewNativeComponent.js | 1 - Libraries/Components/View/ViewPropTypes.js | 2 -- 2 files changed, 3 deletions(-) diff --git a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js index 142dc1c6b0ceec..c2f29322bcca32 100644 --- a/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +++ b/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js @@ -36,7 +36,6 @@ const AndroidHorizontalScrollViewNativeComponent: HostComponent = snapToStart: true, snapToOffsets: true, contentOffset: true, - accessibilityCollection: true, borderBottomLeftRadius: true, borderBottomRightRadius: true, borderRadius: true, diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 2155c0feae6349..468c86d29dd684 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -436,8 +436,6 @@ export type ViewProps = $ReadOnly<{| * Prop used internally to announce with TalkBack rows and columns of a FlatList * See https://bit.ly/3viYSh8 * - * @platform android - * */ accessibilityCollectionItem?: ?{ rowIndex: number, From deb4d6bfce16ab8a33f796d3acf963a7a61b465e Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 15:46:37 +0800 Subject: [PATCH 17/66] format and adding some comments --- Libraries/Lists/FlatList.js | 2 +- Libraries/Lists/VirtualizedList.js | 4 ++-- .../facebook/react/uimanager/ReactAccessibilityDelegate.java | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index e9d2221a15374f..ce0218e61e3abc 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -669,7 +669,7 @@ class FlatList extends React.PureComponent, void> { _getAccessibilityCollection = () => { const accessibilityCollectionProps = { itemCount: this.props.data ? this.props.data.length : 0, - //$FlowFixMe[incompatible-call] + //$FlowFixMe[incompatible-call] see https://bit.ly/3viYSh8 rowCount: this._getItemCount(this.props.data), columnCount: numColumnsOrDefault(this.props.numColumns), hierarchical: false, diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 2b571b30ef03b4..2d491d4a6c79b4 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -2056,8 +2056,8 @@ class CellRenderer extends React.Component< : inversionStyle; const result = !CellRendererComponent ? ( /* $FlowFixMe[incompatible-type-arg] (>=0.89.0 site=react_native_fb) * - This comment suppresses an error found when Flow v0.89 was deployed. * - To see the error, delete this comment and run Flow. */ + This comment suppresses an error found when Flow v0.89 was deployed. * + To see the error, delete this comment and run Flow. */ {element} {itemSeparator} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java index 58b5fc94aa29cf..9543e89116d4e3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java @@ -299,7 +299,6 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) // Set item count and current item index on accessibility events for adjustable // in order to make Talkback announce the value of the adjustable final ReadableMap accessibilityValue = (ReadableMap) host.getTag(R.id.accessibility_value); - if (accessibilityValue != null && accessibilityValue.hasKey("min") && accessibilityValue.hasKey("now") From 42de4dc21bf922b650dc4a4575a0e838f1873341 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sat, 26 Feb 2022 15:54:10 +0800 Subject: [PATCH 18/66] fixing flow error for prop accessibilityCollectionItem Reverts solution https://github.com/facebook/react-native/pull/33180/commits/32676ebe5f7555809c9d3e51efaff73ee287f5bd --- Libraries/Components/View/ViewPropTypes.js | 14 -------------- Libraries/Lists/FlatList.js | 2 ++ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 468c86d29dd684..4e22c3b3b53b22 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -432,20 +432,6 @@ export type ViewProps = $ReadOnly<{| */ accessibilityActions?: ?$ReadOnlyArray, - /** - * Prop used internally to announce with TalkBack rows and columns of a FlatList - * See https://bit.ly/3viYSh8 - * - */ - accessibilityCollectionItem?: ?{ - rowIndex: number, - rowSpan: number, - columnIndex: number, - columnSpan: number, - heading: boolean, - itemIndex: number, - }, - /** * Specifies the nativeID of the associated label text. When the assistive technology focuses on the component with this props, the text is read aloud. * diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index ce0218e61e3abc..1335d8cf2e5d50 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -624,6 +624,7 @@ class FlatList extends React.PureComponent, void> { }; const element = ( + // $FlowFixMe[prop-missing] https://bit.ly/3viYSh8 extends React.PureComponent, void> { }; return ( + // $FlowFixMe[prop-missing] https://bit.ly/3viYSh8 Date: Mon, 7 Mar 2022 10:34:40 +0800 Subject: [PATCH 19/66] moving ScrollView accessibility to seperate class as discussed in [comment][1], the logic is shared between ReactScrollView and ReactHorizontalScrollView. This first steps moves the logic to a separated class as done in [ReactSliderAccessibilityDelegate][2]. [1]: https://github.com/facebook/react-native/pull/33180#discussion_r820009306 [2]: https://github.com/fabriziobertoglio1987/react-native/blob/42de4dc21bf922b650dc4a4575a0e838f1873341/ReactAndroid/src/main/java/com/facebook/react/views/slider/ReactSliderManager.java#L312 --- .../react/views/scroll/ReactScrollView.java | 184 +++++++++--------- 1 file changed, 91 insertions(+), 93 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index ad7c6720baff33..830e1b50ddd3c1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -123,99 +123,7 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { setOnHierarchyChangeListener(this); setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY); - ViewCompat.setAccessibilityDelegate( - this, - new AccessibilityDelegateCompat() { - - @Override - public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(host, event); - event.setScrollable(mScrollEnabled); - final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); - - if (accessibilityCollection != null) { - event.setItemCount(accessibilityCollection.getInt("itemCount")); - View contentView = getContentView(); - Integer firstVisibleIndex = null; - Integer lastVisibleIndex = null; - - if (!(contentView instanceof ViewGroup)) { - return; - } - - for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { - View nextChild = ((ViewGroup) contentView).getChildAt(index); - boolean isVisible = isPartiallyScrolledInView(nextChild); - - ReadableMap accessibilityCollectionItem = - (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); - - if (!(nextChild instanceof ViewGroup)) { - return; - } - - int childCount = ((ViewGroup) nextChild).getChildCount(); - - // 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 (childCount > 0 && accessibilityCollectionItem == null) { - View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); - if (nestedNextChild != null) { - ReadableMap nestedChildAccessibility = - (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item); - if (nestedChildAccessibility != null) { - accessibilityCollectionItem = nestedChildAccessibility; - } - } - } - - if (isVisible == true && accessibilityCollectionItem != null) { - if (firstVisibleIndex == null) { - firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - } - lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - } - - if (firstVisibleIndex != null && lastVisibleIndex != null) { - event.setFromIndex(firstVisibleIndex); - event.setToIndex(lastVisibleIndex); - } - } - } - } - - @Override - public void onInitializeAccessibilityNodeInfo( - View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - - final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = - (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); - - if (accessibilityRole != null) { - ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); - } - - final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); - - if (accessibilityCollection != null) { - int rowCount = accessibilityCollection.getInt("rowCount"); - int columnCount = accessibilityCollection.getInt("columnCount"); - boolean hierarchical = accessibilityCollection.getBoolean("hierarchical"); - - AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = - AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain( - rowCount, columnCount, hierarchical); - info.setCollectionInfo(collectionInfoCompat); - } - - info.setScrollable(mScrollEnabled); - } - }); + ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate()); } @Override @@ -1245,4 +1153,94 @@ public void setPointerEvents(PointerEvents pointerEvents) { public PointerEvents getPointerEvents() { return mPointerEvents; } + + protected class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { + @Override + public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(host, event); + event.setScrollable(mScrollEnabled); + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); + + if (accessibilityCollection != null) { + event.setItemCount(accessibilityCollection.getInt("itemCount")); + View contentView = getContentView(); + Integer firstVisibleIndex = null; + Integer lastVisibleIndex = null; + + if (!(contentView instanceof ViewGroup)) { + return; + } + + for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { + View nextChild = ((ViewGroup) contentView).getChildAt(index); + boolean isVisible = isPartiallyScrolledInView(nextChild); + + ReadableMap accessibilityCollectionItem = + (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); + + if (!(nextChild instanceof ViewGroup)) { + return; + } + + int childCount = ((ViewGroup) nextChild).getChildCount(); + + // 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 (childCount > 0 && accessibilityCollectionItem == null) { + View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); + if (nestedNextChild != null) { + ReadableMap nestedChildAccessibility = + (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item); + if (nestedChildAccessibility != null) { + accessibilityCollectionItem = nestedChildAccessibility; + } + } + } + + if (isVisible == true && accessibilityCollectionItem != null) { + if (firstVisibleIndex == null) { + firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); + } + lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); + } + + if (firstVisibleIndex != null && lastVisibleIndex != null) { + event.setFromIndex(firstVisibleIndex); + event.setToIndex(lastVisibleIndex); + } + } + } + } + + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + + final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = + (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); + + if (accessibilityRole != null) { + ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); + } + + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); + + if (accessibilityCollection != null) { + int rowCount = accessibilityCollection.getInt("rowCount"); + int columnCount = accessibilityCollection.getInt("columnCount"); + boolean hierarchical = accessibilityCollection.getBoolean("hierarchical"); + + AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = + AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain( + rowCount, columnCount, hierarchical); + info.setCollectionInfo(collectionInfoCompat); + } + + info.setScrollable(mScrollEnabled); + } + }; } From 3fcc666c6d60be57e87c3b534518338074a5e6af Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 7 Mar 2022 11:16:06 +0800 Subject: [PATCH 20/66] ReactScrollViewADelegate (more info) 1) moving ReactScrollViewAccessibilityDelegate to separate class 2) moving ReactScrollView getters methods from private to public --- .../ReactScrollViewAccessibilityDelegate.java | 114 ++++++++++++++++++ .../react/views/scroll/ReactScrollView.java | 104 ++-------------- 2 files changed, 121 insertions(+), 97 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java new file mode 100644 index 00000000000000..eb4c2627a98da1 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -0,0 +1,114 @@ +/* + * 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.uimanager; + +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.ReadableMap; +import com.facebook.react.views.scroll.ReactScrollView; + +public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { + + public void onInitializeAccessibilityEvent(ReactScrollView host, AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(host, event); + // add check on type + ReactScrollView scrollView = (ReactScrollView) host; + if (scrollView != null) { + event.setScrollable(scrollView.getScrollEnabled()); + } + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); + + if (accessibilityCollection != null) { + event.setItemCount(accessibilityCollection.getInt("itemCount")); + View contentView = scrollView.getContentView(); + Integer firstVisibleIndex = null; + Integer lastVisibleIndex = null; + + if (!(contentView instanceof ViewGroup)) { + return; + } + + for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { + View nextChild = ((ViewGroup) contentView).getChildAt(index); + boolean isVisible = scrollView.isPartiallyScrolledInView(nextChild); + + ReadableMap accessibilityCollectionItem = + (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); + + if (!(nextChild instanceof ViewGroup)) { + return; + } + + int childCount = ((ViewGroup) nextChild).getChildCount(); + + // 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 (childCount > 0 && accessibilityCollectionItem == null) { + View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); + if (nestedNextChild != null) { + ReadableMap nestedChildAccessibility = + (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item); + if (nestedChildAccessibility != null) { + accessibilityCollectionItem = nestedChildAccessibility; + } + } + } + + if (isVisible == true && accessibilityCollectionItem != null) { + if (firstVisibleIndex == null) { + firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); + } + lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); + } + + if (firstVisibleIndex != null && lastVisibleIndex != null) { + event.setFromIndex(firstVisibleIndex); + event.setToIndex(lastVisibleIndex); + } + } + } + } + + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + + final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = + (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); + + if (accessibilityRole != null) { + ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); + } + + final ReadableMap accessibilityCollection = + (ReadableMap) host.getTag(R.id.accessibility_collection); + + if (accessibilityCollection != null) { + int rowCount = accessibilityCollection.getInt("rowCount"); + int columnCount = accessibilityCollection.getInt("columnCount"); + boolean hierarchical = accessibilityCollection.getBoolean("hierarchical"); + + AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = + AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain( + rowCount, columnCount, hierarchical); + info.setCollectionInfo(collectionInfoCompat); + } + + ReactScrollView scrollView = (ReactScrollView) host; + if (scrollView != null) { + info.setScrollable(scrollView.getScrollEnabled()); + } + } +}; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 830e1b50ddd3c1..13fd7f758330d4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -24,26 +24,22 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.OverScroller; import android.widget.ScrollView; import androidx.annotation.Nullable; -import androidx.core.view.AccessibilityDelegateCompat; import androidx.core.view.ViewCompat; -import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.react.R; -import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.PointerEvents; -import com.facebook.react.uimanager.ReactAccessibilityDelegate; import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ReactOverflowViewWithInset; +import com.facebook.react.uimanager.ReactScrollViewAccessibilityDelegate; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator; @@ -195,6 +191,10 @@ public void setScrollEnabled(boolean scrollEnabled) { mScrollEnabled = scrollEnabled; } + public boolean getScrollEnabled() { + return mScrollEnabled; + } + public void setPagingEnabled(boolean pagingEnabled) { mPagingEnabled = pagingEnabled; } @@ -310,7 +310,7 @@ private int getScrollDelta(View descendent) { } /** Returns whether the given descendent is partially scrolled in view */ - private boolean isPartiallyScrolledInView(View descendent) { + public boolean isPartiallyScrolledInView(View descendent) { int scrollDelta = getScrollDelta(descendent); descendent.getDrawingRect(mTempRect); return scrollDelta != 0 && Math.abs(scrollDelta) < mTempRect.width(); @@ -646,7 +646,7 @@ private int predictFinalScrollPosition(int velocityY) { + getFlingExtrapolatedDistance(velocityY); } - private View getContentView() { + public View getContentView() { return getChildAt(0); } @@ -1153,94 +1153,4 @@ public void setPointerEvents(PointerEvents pointerEvents) { public PointerEvents getPointerEvents() { return mPointerEvents; } - - protected class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { - @Override - public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(host, event); - event.setScrollable(mScrollEnabled); - final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); - - if (accessibilityCollection != null) { - event.setItemCount(accessibilityCollection.getInt("itemCount")); - View contentView = getContentView(); - Integer firstVisibleIndex = null; - Integer lastVisibleIndex = null; - - if (!(contentView instanceof ViewGroup)) { - return; - } - - for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { - View nextChild = ((ViewGroup) contentView).getChildAt(index); - boolean isVisible = isPartiallyScrolledInView(nextChild); - - ReadableMap accessibilityCollectionItem = - (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); - - if (!(nextChild instanceof ViewGroup)) { - return; - } - - int childCount = ((ViewGroup) nextChild).getChildCount(); - - // 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 (childCount > 0 && accessibilityCollectionItem == null) { - View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); - if (nestedNextChild != null) { - ReadableMap nestedChildAccessibility = - (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item); - if (nestedChildAccessibility != null) { - accessibilityCollectionItem = nestedChildAccessibility; - } - } - } - - if (isVisible == true && accessibilityCollectionItem != null) { - if (firstVisibleIndex == null) { - firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - } - lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - } - - if (firstVisibleIndex != null && lastVisibleIndex != null) { - event.setFromIndex(firstVisibleIndex); - event.setToIndex(lastVisibleIndex); - } - } - } - } - - @Override - public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - - final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = - (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); - - if (accessibilityRole != null) { - ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); - } - - final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); - - if (accessibilityCollection != null) { - int rowCount = accessibilityCollection.getInt("rowCount"); - int columnCount = accessibilityCollection.getInt("columnCount"); - boolean hierarchical = accessibilityCollection.getBoolean("hierarchical"); - - AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = - AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain( - rowCount, columnCount, hierarchical); - info.setCollectionInfo(collectionInfoCompat); - } - - info.setScrollable(mScrollEnabled); - } - }; } From fc6a75541a4649ed9dbc2a283d6a7ec95ff8208a Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 7 Mar 2022 11:47:22 +0800 Subject: [PATCH 21/66] moving logic to method onInitialize..Internal --- .../ReactScrollViewAccessibilityDelegate.java | 51 ++++++++++++++----- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java index eb4c2627a98da1..a7bf4e532764b1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -12,21 +12,35 @@ import android.view.accessibility.AccessibilityEvent; import androidx.core.view.AccessibilityDelegateCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; +import com.facebook.common.logging.FLog; import com.facebook.react.R; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.views.scroll.ReactScrollView; public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { + private final String TAG = ReactScrollViewAccessibilityDelegate.class.getSimpleName(); - public void onInitializeAccessibilityEvent(ReactScrollView host, AccessibilityEvent event) { + @Override + public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); - // add check on type - ReactScrollView scrollView = (ReactScrollView) host; - if (scrollView != null) { - event.setScrollable(scrollView.getScrollEnabled()); + if (host instanceof ReactScrollView) { + ReactScrollView scrollView = (ReactScrollView) host; + onInitializeAccessibilityEventInternal(scrollView, event); + } else { + FLog.w( + TAG, + TAG + + " method onInitializeAccessibilityNodeInfo was called with host: " + + host + + " not instanceof ReactScrollView"); } + } + + public void onInitializeAccessibilityEventInternal( + ReactScrollView scrollView, AccessibilityEvent event) { + event.setScrollable(scrollView.getScrollEnabled()); final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); + (ReadableMap) scrollView.getTag(R.id.accessibility_collection); if (accessibilityCollection != null) { event.setItemCount(accessibilityCollection.getInt("itemCount")); @@ -84,16 +98,30 @@ public void onInitializeAccessibilityEvent(ReactScrollView host, AccessibilityEv @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { super.onInitializeAccessibilityNodeInfo(host, info); + if (host instanceof ReactScrollView) { + ReactScrollView scrollView = (ReactScrollView) host; + onInitializeAccessibilityNodeInfoInternal(scrollView, info); + } else { + FLog.w( + TAG, + TAG + + " method onInitializeAccessibilityNodeInfo was called with host: " + + host + + " not instanceof ReactScrollView"); + } + }; + public void onInitializeAccessibilityNodeInfoInternal( + ReactScrollView scrollView, AccessibilityNodeInfoCompat info) { final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = - (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); + (ReactAccessibilityDelegate.AccessibilityRole) scrollView.getTag(R.id.accessibility_role); if (accessibilityRole != null) { - ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); + ReactAccessibilityDelegate.setRole(info, accessibilityRole, scrollView.getContext()); } final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); + (ReadableMap) scrollView.getTag(R.id.accessibility_collection); if (accessibilityCollection != null) { int rowCount = accessibilityCollection.getInt("rowCount"); @@ -106,9 +134,6 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo info.setCollectionInfo(collectionInfoCompat); } - ReactScrollView scrollView = (ReactScrollView) host; - if (scrollView != null) { - info.setScrollable(scrollView.getScrollEnabled()); - } + info.setScrollable(scrollView.getScrollEnabled()); } }; From cd392c378a8e39aac13c058fbcdbff330b045f06 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 08:49:27 +0800 Subject: [PATCH 22/66] draft solution with refactoring --- .../com/facebook/react/uimanager/List.java | 7 +++ .../ReactScrollViewAccessibilityDelegate.java | 53 ++++++++++++------- .../scroll/ReactHorizontalScrollView.java | 8 ++- .../react/views/scroll/ReactScrollView.java | 17 +++++- 4 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java new file mode 100644 index 00000000000000..21ce4af1bf1c11 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java @@ -0,0 +1,7 @@ +package com.facebook.react.uimanager; + +public interface List { + void setValue(T value); + + T getValue(); +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java index a7bf4e532764b1..51f618650c0889 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -7,44 +7,57 @@ package com.facebook.react.uimanager; +import android.util.Log; 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.common.logging.FLog; import com.facebook.react.R; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.views.scroll.ReactScrollView; -public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { +public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { private final String TAG = ReactScrollViewAccessibilityDelegate.class.getSimpleName(); + T obj; + + public ReactScrollViewAccessibilityDelegate(T obj) { + super(); + this.obj = obj; + } + + public T getObject() { + return this.obj; + } + + public void sayHello() { + Log.w("TESTING::ReactScrollView", "sayHello"); + } @Override public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); - if (host instanceof ReactScrollView) { - ReactScrollView scrollView = (ReactScrollView) host; - onInitializeAccessibilityEventInternal(scrollView, event); - } else { - FLog.w( - TAG, - TAG - + " method onInitializeAccessibilityNodeInfo was called with host: " - + host - + " not instanceof ReactScrollView"); - } + onInitializeAccessibilityEventInternal(host, event); } - public void onInitializeAccessibilityEventInternal( - ReactScrollView scrollView, AccessibilityEvent event) { - event.setScrollable(scrollView.getScrollEnabled()); + public boolean isPartiallyScrolledInView(T view, View nextChild) { + Log.w(TAG, "isPartiallyScrolledInView not implemented"); + return false; + } + + public View getContentView(T view) { + Log.w(TAG, "getContentView not implemented"); + return (View) view; + } + + public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent event) { + if (!(view instanceof ReactScrollView)) return; final ReadableMap accessibilityCollection = - (ReadableMap) scrollView.getTag(R.id.accessibility_collection); + (ReadableMap) view.getTag(R.id.accessibility_collection); if (accessibilityCollection != null) { event.setItemCount(accessibilityCollection.getInt("itemCount")); - View contentView = scrollView.getContentView(); + View contentView = getContentView((T) view); Integer firstVisibleIndex = null; Integer lastVisibleIndex = null; @@ -54,7 +67,7 @@ public void onInitializeAccessibilityEventInternal( for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { View nextChild = ((ViewGroup) contentView).getChildAt(index); - boolean isVisible = scrollView.isPartiallyScrolledInView(nextChild); + boolean isVisible = isPartiallyScrolledInView((T) view, nextChild); ReadableMap accessibilityCollectionItem = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); @@ -102,7 +115,7 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo ReactScrollView scrollView = (ReactScrollView) host; onInitializeAccessibilityNodeInfoInternal(scrollView, info); } else { - FLog.w( + Log.w( TAG, TAG + " method onInitializeAccessibilityNodeInfo was called with host: " diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index ce96c3e60e8a51..71eeb82df246e2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -220,6 +220,10 @@ public void onInitializeAccessibilityNodeInfo( : ViewCompat.LAYOUT_DIRECTION_LTR); } + public boolean getScrollEnabled() { + return mScrollEnabled; + } + @Nullable private OverScroller getOverScrollerFromParent() { OverScroller scroller; @@ -481,7 +485,7 @@ private boolean isScrolledInView(View descendent) { } /** Returns whether the given descendent is partially scrolled in view */ - private boolean isPartiallyScrolledInView(View descendent) { + public boolean isPartiallyScrolledInView(View descendent) { int scrollDelta = getScrollDelta(descendent); descendent.getDrawingRect(mTempRect); return scrollDelta != 0 && Math.abs(scrollDelta) < mTempRect.width(); @@ -737,7 +741,7 @@ private int getSnapInterval() { return getWidth(); } - private View getContentView() { + public View getContentView() { return getChildAt(0); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 13fd7f758330d4..e43048ea77adc5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -20,6 +20,7 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -119,7 +120,21 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { setOnHierarchyChangeListener(this); setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY); - ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate()); + ReactScrollViewAccessibilityDelegate delegate = + new ReactScrollViewAccessibilityDelegate(this) { + + // possible move the method to ReactScrollViewAccessibilityDelegate + // if can not be improved with a generic + public boolean isPartiallyScrolledInView(ReactScrollView view, View nextChild) { + return view.isPartiallyScrolledInView(nextChild); + } + + public View getContentView(ReactScrollView view) { + Log.w("TESTING::ReactScrollView", "in react scroll view"); + return view.getContentView(); + } + }; + ViewCompat.setAccessibilityDelegate(this, delegate); } @Override From b7e5365204a53628e5a84bfc0a86593c2d2df147 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 13:07:56 +0800 Subject: [PATCH 23/66] Avoid code duplication in AccessibilityDelegate logic --- .../ReactScrollViewAccessibilityDelegate.java | 51 +++------ .../scroll/ReactHorizontalScrollView.java | 103 ++---------------- .../react/views/scroll/ReactScrollView.java | 10 +- 3 files changed, 35 insertions(+), 129 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java index 51f618650c0889..743d2c3b443d71 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -15,24 +15,11 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.facebook.react.R; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.views.scroll.ReactHorizontalScrollView; import com.facebook.react.views.scroll.ReactScrollView; public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { private final String TAG = ReactScrollViewAccessibilityDelegate.class.getSimpleName(); - T obj; - - public ReactScrollViewAccessibilityDelegate(T obj) { - super(); - this.obj = obj; - } - - public T getObject() { - return this.obj; - } - - public void sayHello() { - Log.w("TESTING::ReactScrollView", "sayHello"); - } @Override public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { @@ -40,18 +27,25 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) onInitializeAccessibilityEventInternal(host, event); } + // could be refactored in an interface with default methods + // https://stackoverflow.com/a/13992641/7295772 public boolean isPartiallyScrolledInView(T view, View nextChild) { - Log.w(TAG, "isPartiallyScrolledInView not implemented"); + Log.w(TAG, "isPartiallyScrolledInView not implemented: " + view.getClass().getSimpleName()); return false; } public View getContentView(T view) { - Log.w(TAG, "getContentView not implemented"); + Log.w(TAG, "getContentView not implemented for class " + view.getClass().getSimpleName()); return (View) view; } + public boolean getScrollEnabled(T view) { + Log.w(TAG, "getScrollEnabled not implemented for class " + view.getClass().getSimpleName()); + return false; + } + public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent event) { - if (!(view instanceof ReactScrollView)) return; + if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; final ReadableMap accessibilityCollection = (ReadableMap) view.getTag(R.id.accessibility_collection); @@ -111,30 +105,21 @@ public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { super.onInitializeAccessibilityNodeInfo(host, info); - if (host instanceof ReactScrollView) { - ReactScrollView scrollView = (ReactScrollView) host; - onInitializeAccessibilityNodeInfoInternal(scrollView, info); - } else { - Log.w( - TAG, - TAG - + " method onInitializeAccessibilityNodeInfo was called with host: " - + host - + " not instanceof ReactScrollView"); - } + onInitializeAccessibilityNodeInfoInternal(host, info); }; public void onInitializeAccessibilityNodeInfoInternal( - ReactScrollView scrollView, AccessibilityNodeInfoCompat info) { + View view, AccessibilityNodeInfoCompat info) { + if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = - (ReactAccessibilityDelegate.AccessibilityRole) scrollView.getTag(R.id.accessibility_role); + (ReactAccessibilityDelegate.AccessibilityRole) view.getTag(R.id.accessibility_role); if (accessibilityRole != null) { - ReactAccessibilityDelegate.setRole(info, accessibilityRole, scrollView.getContext()); + ReactAccessibilityDelegate.setRole(info, accessibilityRole, view.getContext()); } final ReadableMap accessibilityCollection = - (ReadableMap) scrollView.getTag(R.id.accessibility_collection); + (ReadableMap) view.getTag(R.id.accessibility_collection); if (accessibilityCollection != null) { int rowCount = accessibilityCollection.getInt("rowCount"); @@ -147,6 +132,6 @@ public void onInitializeAccessibilityNodeInfoInternal( info.setCollectionInfo(collectionInfoCompat); } - info.setScrollable(scrollView.getScrollEnabled()); + info.setScrollable(getScrollEnabled((T) view)); } }; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 71eeb82df246e2..7db564ad4b228f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -25,27 +25,22 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; import android.widget.HorizontalScrollView; import android.widget.OverScroller; import androidx.annotation.Nullable; -import androidx.core.view.AccessibilityDelegateCompat; import androidx.core.view.ViewCompat; -import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; -import com.facebook.react.R; -import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.ReactConstants; import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.MeasureSpecAssertions; import com.facebook.react.uimanager.PointerEvents; -import com.facebook.react.uimanager.ReactAccessibilityDelegate; import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ReactOverflowViewWithInset; +import com.facebook.react.uimanager.ReactScrollViewAccessibilityDelegate; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator; @@ -121,96 +116,22 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe mReactBackgroundManager = new ReactViewBackgroundManager(this); mFpsListener = fpsListener; - ViewCompat.setAccessibilityDelegate( - this, - new AccessibilityDelegateCompat() { - @Override - public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(host, event); - event.setScrollable(mScrollEnabled); - final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); - - if (accessibilityCollection != null) { - event.setItemCount(accessibilityCollection.getInt("itemCount")); - View contentView = getContentView(); - Integer firstVisibleIndex = null; - Integer lastVisibleIndex = null; - - if (!(contentView instanceof ViewGroup)) { - return; - } - - for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { - View nextChild = ((ViewGroup) contentView).getChildAt(index); - boolean isVisible = isPartiallyScrolledInView(nextChild); - - ReadableMap accessibilityCollectionItem = - (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); - - if (!(nextChild instanceof ViewGroup)) { - return; - } - - int childCount = ((ViewGroup) nextChild).getChildCount(); - - // 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 (childCount > 0 && accessibilityCollectionItem == null) { - View nestedNextChild = ((ViewGroup) nextChild).getChildAt(0); - if (nestedNextChild != null) { - ReadableMap nestedChildAccessibilityInfo = - (ReadableMap) nestedNextChild.getTag(R.id.accessibility_collection_item); - if (nestedChildAccessibilityInfo != null) { - accessibilityCollectionItem = nestedChildAccessibilityInfo; - } - } - } - - if (isVisible == true && accessibilityCollectionItem != null) { - if (firstVisibleIndex == null) { - firstVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - } - lastVisibleIndex = accessibilityCollectionItem.getInt("itemIndex"); - } + ReactScrollViewAccessibilityDelegate delegate = + new ReactScrollViewAccessibilityDelegate() { - if (firstVisibleIndex != null && lastVisibleIndex != null) { - event.setFromIndex(firstVisibleIndex); - event.setToIndex(lastVisibleIndex); - } - } - } + public boolean isPartiallyScrolledInView(ReactHorizontalScrollView view, View nextChild) { + return view.isPartiallyScrolledInView(nextChild); } - @Override - public void onInitializeAccessibilityNodeInfo( - View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - info.setScrollable(mScrollEnabled); - final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = - (ReactAccessibilityDelegate.AccessibilityRole) host.getTag(R.id.accessibility_role); - - if (accessibilityRole != null) { - ReactAccessibilityDelegate.setRole(info, accessibilityRole, host.getContext()); - } - - final ReadableMap accessibilityCollection = - (ReadableMap) host.getTag(R.id.accessibility_collection); - - if (accessibilityCollection != null) { - int rowCount = accessibilityCollection.getInt("rowCount"); - int columnCount = accessibilityCollection.getInt("columnCount"); - boolean hierarchical = accessibilityCollection.getBoolean("hierarchical"); + public View getContentView(ReactHorizontalScrollView view) { + return view.getContentView(); + } - AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfoCompat = - AccessibilityNodeInfoCompat.CollectionInfoCompat.obtain( - rowCount, columnCount, hierarchical); - info.setCollectionInfo(collectionInfoCompat); - } + public boolean getScrollEnabled(ReactHorizontalScrollView view) { + return view.getScrollEnabled(); } - }); + }; + ViewCompat.setAccessibilityDelegate(this, delegate); mScroller = getOverScrollerFromParent(); mReactScrollViewScrollState = diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index e43048ea77adc5..19c29067c511f7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -20,7 +20,6 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -121,18 +120,19 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY); ReactScrollViewAccessibilityDelegate delegate = - new ReactScrollViewAccessibilityDelegate(this) { + new ReactScrollViewAccessibilityDelegate() { - // possible move the method to ReactScrollViewAccessibilityDelegate - // if can not be improved with a generic public boolean isPartiallyScrolledInView(ReactScrollView view, View nextChild) { return view.isPartiallyScrolledInView(nextChild); } public View getContentView(ReactScrollView view) { - Log.w("TESTING::ReactScrollView", "in react scroll view"); return view.getContentView(); } + + public boolean getScrollEnabled(ReactScrollView view) { + return view.getScrollEnabled(); + } }; ViewCompat.setAccessibilityDelegate(this, delegate); } From 3fc34d40ff2e125524ddc11f3165d5a2841f4bb1 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 14:08:52 +0800 Subject: [PATCH 24/66] Removing Generic and using check out Type --- .../ReactScrollViewAccessibilityDelegate.java | 61 ++++++++++--------- .../scroll/ReactHorizontalScrollView.java | 16 +---- .../react/views/scroll/ReactScrollView.java | 18 +----- 3 files changed, 37 insertions(+), 58 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java index 743d2c3b443d71..ca47cb1ead73bb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -7,7 +7,6 @@ package com.facebook.react.uimanager; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; @@ -18,7 +17,7 @@ import com.facebook.react.views.scroll.ReactHorizontalScrollView; import com.facebook.react.views.scroll.ReactScrollView; -public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { +public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { private final String TAG = ReactScrollViewAccessibilityDelegate.class.getSimpleName(); @Override @@ -27,22 +26,11 @@ public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) onInitializeAccessibilityEventInternal(host, event); } - // could be refactored in an interface with default methods - // https://stackoverflow.com/a/13992641/7295772 - public boolean isPartiallyScrolledInView(T view, View nextChild) { - Log.w(TAG, "isPartiallyScrolledInView not implemented: " + view.getClass().getSimpleName()); - return false; - } - - public View getContentView(T view) { - Log.w(TAG, "getContentView not implemented for class " + view.getClass().getSimpleName()); - return (View) view; - } - - public boolean getScrollEnabled(T view) { - Log.w(TAG, "getScrollEnabled not implemented for class " + view.getClass().getSimpleName()); - return false; - } + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + onInitializeAccessibilityNodeInfoInternal(host, info); + }; public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent event) { if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; @@ -51,7 +39,16 @@ public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent if (accessibilityCollection != null) { event.setItemCount(accessibilityCollection.getInt("itemCount")); - View contentView = getContentView((T) view); + View contentView; + if (view instanceof ReactScrollView) { + ReactScrollView scrollView = (ReactScrollView) view; + contentView = scrollView.getContentView(); + } else if (view instanceof ReactHorizontalScrollView) { + ReactHorizontalScrollView scrollView = (ReactHorizontalScrollView) view; + contentView = scrollView.getContentView(); + } else { + return; + } Integer firstVisibleIndex = null; Integer lastVisibleIndex = null; @@ -61,8 +58,16 @@ public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { View nextChild = ((ViewGroup) contentView).getChildAt(index); - boolean isVisible = isPartiallyScrolledInView((T) view, nextChild); - + boolean isVisible = false; + if (view instanceof ReactScrollView) { + ReactScrollView scrollView = (ReactScrollView) view; + isVisible = scrollView.isPartiallyScrolledInView(nextChild); + } else if (view instanceof ReactHorizontalScrollView) { + ReactHorizontalScrollView scrollView = (ReactHorizontalScrollView) view; + isVisible = scrollView.isPartiallyScrolledInView(nextChild); + } else { + return; + } ReadableMap accessibilityCollectionItem = (ReadableMap) nextChild.getTag(R.id.accessibility_collection_item); @@ -102,12 +107,6 @@ public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent } } - @Override - public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - onInitializeAccessibilityNodeInfoInternal(host, info); - }; - public void onInitializeAccessibilityNodeInfoInternal( View view, AccessibilityNodeInfoCompat info) { if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; @@ -132,6 +131,12 @@ public void onInitializeAccessibilityNodeInfoInternal( info.setCollectionInfo(collectionInfoCompat); } - info.setScrollable(getScrollEnabled((T) view)); + if (view instanceof ReactScrollView) { + ReactScrollView scrollView = (ReactScrollView) view; + info.setScrollable(scrollView.getScrollEnabled()); + } else if (view instanceof ReactHorizontalScrollView) { + ReactHorizontalScrollView scrollView = (ReactHorizontalScrollView) view; + info.setScrollable(scrollView.getScrollEnabled()); + } } }; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 085fd9338a94fb..6016276209a450 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -116,21 +116,7 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe mReactBackgroundManager = new ReactViewBackgroundManager(this); mFpsListener = fpsListener; - ReactScrollViewAccessibilityDelegate delegate = - new ReactScrollViewAccessibilityDelegate() { - - public boolean isPartiallyScrolledInView(ReactHorizontalScrollView view, View nextChild) { - return view.isPartiallyScrolledInView(nextChild); - } - - public View getContentView(ReactHorizontalScrollView view) { - return view.getContentView(); - } - - public boolean getScrollEnabled(ReactHorizontalScrollView view) { - return view.getScrollEnabled(); - } - }; + ReactScrollViewAccessibilityDelegate delegate = new ReactScrollViewAccessibilityDelegate(); ViewCompat.setAccessibilityDelegate(this, delegate); mScroller = getOverScrollerFromParent(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index a4bad7426f4057..0f96673654fa6e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -20,6 +20,7 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -119,26 +120,13 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { setOnHierarchyChangeListener(this); setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY); - ReactScrollViewAccessibilityDelegate delegate = - new ReactScrollViewAccessibilityDelegate() { - - public boolean isPartiallyScrolledInView(ReactScrollView view, View nextChild) { - return view.isPartiallyScrolledInView(nextChild); - } - - public View getContentView(ReactScrollView view) { - return view.getContentView(); - } - - public boolean getScrollEnabled(ReactScrollView view) { - return view.getScrollEnabled(); - } - }; + ReactScrollViewAccessibilityDelegate delegate = new ReactScrollViewAccessibilityDelegate(); ViewCompat.setAccessibilityDelegate(this, delegate); } @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + Log.w("TESTING::ReactScrollView", "ReactScrollView onInitializeAccessibilityNodeInfo"); super.onInitializeAccessibilityNodeInfo(info); // Expose the testID prop as the resource-id name of the view. Black-box E2E/UI testing From 389761d41abeed05e162cb31cce7c7ba584b58b8 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 14:14:38 +0800 Subject: [PATCH 25/66] remove log --- .../java/com/facebook/react/views/scroll/ReactScrollView.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 0f96673654fa6e..916fc58b96ee66 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -20,7 +20,6 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -126,7 +125,6 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - Log.w("TESTING::ReactScrollView", "ReactScrollView onInitializeAccessibilityNodeInfo"); super.onInitializeAccessibilityNodeInfo(info); // Expose the testID prop as the resource-id name of the view. Black-box E2E/UI testing From fc48b991730b9030bcbf8d39409ac132b051326f Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 14:16:20 +0800 Subject: [PATCH 26/66] Delete file List.java --- .../src/main/java/com/facebook/react/uimanager/List.java | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java deleted file mode 100644 index 21ce4af1bf1c11..00000000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/List.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.facebook.react.uimanager; - -public interface List { - void setValue(T value); - - T getValue(); -} From b97e5e1c25d675e3c5c843b1e63ce72b593be0e1 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 14:19:24 +0800 Subject: [PATCH 27/66] change RNScrollDelegate methods to private --- .../react/uimanager/ReactScrollViewAccessibilityDelegate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java index ca47cb1ead73bb..b358a5c87a5f09 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -32,7 +32,7 @@ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCo onInitializeAccessibilityNodeInfoInternal(host, info); }; - public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent event) { + private void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent event) { if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; final ReadableMap accessibilityCollection = (ReadableMap) view.getTag(R.id.accessibility_collection); @@ -107,7 +107,7 @@ public void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent } } - public void onInitializeAccessibilityNodeInfoInternal( + private void onInitializeAccessibilityNodeInfoInternal( View view, AccessibilityNodeInfoCompat info) { if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = From 6062029395188211686d71b89d31469d93979677 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 14:33:58 +0800 Subject: [PATCH 28/66] log soft exception if RSCADelegate is used in wrong class --- .../ReactScrollViewAccessibilityDelegate.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java index b358a5c87a5f09..bcf8034587128f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -13,6 +13,8 @@ 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.views.scroll.ReactHorizontalScrollView; import com.facebook.react.views.scroll.ReactScrollView; @@ -23,17 +25,32 @@ public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateC @Override public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); - onInitializeAccessibilityEventInternal(host, event); + if (host instanceof ReactScrollView || host instanceof ReactHorizontalScrollView) { + onInitializeAccessibilityEventInternal(host, event); + } else { + ReactSoftExceptionLogger.logSoftException( + TAG, + new AssertionException( + "ReactScrollViewAccessibilityDelegate should only be used with ReactScrollView or ReactHorizontalScrollView, not with class: " + + host.getClass().getSimpleName())); + } } @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { super.onInitializeAccessibilityNodeInfo(host, info); - onInitializeAccessibilityNodeInfoInternal(host, info); + if (host instanceof ReactScrollView || host instanceof ReactHorizontalScrollView) { + onInitializeAccessibilityNodeInfoInternal(host, info); + } else { + ReactSoftExceptionLogger.logSoftException( + TAG, + new AssertionException( + "ReactScrollViewAccessibilityDelegate should only be used with ReactScrollView or ReactHorizontalScrollView, not with class: " + + host.getClass().getSimpleName())); + } }; private void onInitializeAccessibilityEventInternal(View view, AccessibilityEvent event) { - if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; final ReadableMap accessibilityCollection = (ReadableMap) view.getTag(R.id.accessibility_collection); @@ -109,7 +126,6 @@ private void onInitializeAccessibilityEventInternal(View view, AccessibilityEven private void onInitializeAccessibilityNodeInfoInternal( View view, AccessibilityNodeInfoCompat info) { - if (!(view instanceof ReactScrollView) && !(view instanceof ReactHorizontalScrollView)) return; final ReactAccessibilityDelegate.AccessibilityRole accessibilityRole = (ReactAccessibilityDelegate.AccessibilityRole) view.getTag(R.id.accessibility_role); From 6515fba657cd45430556d9950fa2cc4757b0357d Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 14:37:53 +0800 Subject: [PATCH 29/66] remove default value of false to isVisible --- .../react/uimanager/ReactScrollViewAccessibilityDelegate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java index bcf8034587128f..f1831249ba018d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java @@ -75,7 +75,7 @@ private void onInitializeAccessibilityEventInternal(View view, AccessibilityEven for (int index = 0; index < ((ViewGroup) contentView).getChildCount(); index++) { View nextChild = ((ViewGroup) contentView).getChildAt(index); - boolean isVisible = false; + boolean isVisible; if (view instanceof ReactScrollView) { ReactScrollView scrollView = (ReactScrollView) view; isVisible = scrollView.isPartiallyScrolledInView(nextChild); From 09be9f138ca0fcbe26c35dca7be689e030571d9a Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 14:51:08 +0800 Subject: [PATCH 30/66] minor change --- .../facebook/react/views/scroll/ReactHorizontalScrollView.java | 3 +-- .../java/com/facebook/react/views/scroll/ReactScrollView.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 6016276209a450..c81470faf7ac3a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -116,8 +116,7 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe mReactBackgroundManager = new ReactViewBackgroundManager(this); mFpsListener = fpsListener; - ReactScrollViewAccessibilityDelegate delegate = new ReactScrollViewAccessibilityDelegate(); - ViewCompat.setAccessibilityDelegate(this, delegate); + ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate()); mScroller = getOverScrollerFromParent(); mReactScrollViewScrollState = diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 916fc58b96ee66..3b15174ff4ca88 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -119,8 +119,7 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { setOnHierarchyChangeListener(this); setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY); - ReactScrollViewAccessibilityDelegate delegate = new ReactScrollViewAccessibilityDelegate(); - ViewCompat.setAccessibilityDelegate(this, delegate); + ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate()); } @Override From 70e83a2cbb4f81ea373f3876abd9caf9f35a50a3 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 18:19:01 +0800 Subject: [PATCH 31/66] moving ReactScrollViewAccessibilityDelegate to /react/views/scroll --- .../react/views/scroll/ReactHorizontalScrollView.java | 1 - .../com/facebook/react/views/scroll/ReactScrollView.java | 1 - .../scroll}/ReactScrollViewAccessibilityDelegate.java | 5 ++--- 3 files changed, 2 insertions(+), 5 deletions(-) rename ReactAndroid/src/main/java/com/facebook/react/{uimanager => views/scroll}/ReactScrollViewAccessibilityDelegate.java (97%) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index c81470faf7ac3a..b183c5ee265042 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -40,7 +40,6 @@ import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ReactOverflowViewWithInset; -import com.facebook.react.uimanager.ReactScrollViewAccessibilityDelegate; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 3b15174ff4ca88..f0ff6984e7ac17 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -39,7 +39,6 @@ import com.facebook.react.uimanager.ReactClippingViewGroup; import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ReactOverflowViewWithInset; -import com.facebook.react.uimanager.ReactScrollViewAccessibilityDelegate; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.events.NativeGestureUtil; import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator; diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java similarity index 97% rename from ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java rename to ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java index f1831249ba018d..57f26d9c44909a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.uimanager; +package com.facebook.react.views.scroll; import android.view.View; import android.view.ViewGroup; @@ -16,8 +16,7 @@ import com.facebook.react.bridge.AssertionException; import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.views.scroll.ReactHorizontalScrollView; -import com.facebook.react.views.scroll.ReactScrollView; +import com.facebook.react.uimanager.ReactAccessibilityDelegate; public class ReactScrollViewAccessibilityDelegate extends AccessibilityDelegateCompat { private final String TAG = ReactScrollViewAccessibilityDelegate.class.getSimpleName(); From 6bc0f5af7fb24a84cc60e83e99d62546f4c70297 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 11 Mar 2022 18:45:00 +0800 Subject: [PATCH 32/66] adding itemIndex variable as index is used twice >now that index is used twice, it would be nice to declare it as a const ex const itemIndex = index * numColumns + kk just to avoid errors where someone changes the calculation on one line but not the other. https://github.com/facebook/react-native/pull/33180#discussion_r820863403 --- Libraries/Lists/FlatList.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 1335d8cf2e5d50..3391036e3cd419 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -614,13 +614,14 @@ class FlatList extends React.PureComponent, void> { return ( {item.map((it, kk) => { + const itemIndex = index * numColumns + kk; const accessibilityCollectionItem = { rowIndex: index, rowSpan: 1, - columnIndex: (index * numColumns + kk) % numColumns, + columnIndex: itemIndex % numColumns, columnSpan: 1, heading: false, - itemIndex: index * numColumns + kk, + itemIndex: itemIndex, }; const element = ( From 4c3182a304f258823107338b93c45a69b7bdd50d Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sun, 13 Mar 2022 12:12:38 +0800 Subject: [PATCH 33/66] Removing container View in renderItem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/facebook/react-native/pull/33180#discussion_r820860260 >What's the reason for adding this cellStyle here? - we are adding a [View container][1] to each [cell][2] ([renderItem prop][3]) - `{flex: 1}` makes the container View take the full width of the parent container https://reactnative.dev/docs/flexbox#flex >[flex](https://reactnative.dev/docs/layout-props#flex) will define how your items are going to “fill” over the available space along your main axis. Space will be divided according to each element's flex property. | without `{flex: 1}` | with `{flex: 1}` | |:-------------------------:|:-------------------------:| | | | [1]: https://github.com/fabriziobertoglio1987/react-native/blob/70e83a2cbb4f81ea373f3876abd9caf9f35a50a3/Libraries/Lists/FlatList.js#L628-L630 "the View container added to each cell" [2]: https://github.com/fabriziobertoglio1987/react-native/blob/70e83a2cbb4f81ea373f3876abd9caf9f35a50a3/Libraries/Lists/FlatList.js#L581-L601 "the logic responsible to render cells (renderItem prop)" [3]: https://reactnative.dev/docs/next/flatlist#required-renderitem "renderItem prop" original post https://github.com/fabriziobertoglio1987/react-native-notes/issues/6#issuecomment-1064983239 --- Libraries/Lists/FlatList.js | 20 +++++++------------ .../examples/FlatList/FlatList-multiColumn.js | 9 +++++++-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 3391036e3cd419..cfbeac7391edd1 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -624,19 +624,13 @@ class FlatList extends React.PureComponent, void> { itemIndex: itemIndex, }; - const element = ( - // $FlowFixMe[prop-missing] https://bit.ly/3viYSh8 - - {renderer({ - item: it, - index: index * numColumns + kk, - separators: info.separators, - })} - - ); + const element = renderer({ + item: it, + index: index * numColumns + kk, + separators: info.separators, + accessibilityCollectionItem: accessibilityCollectionItem, + }); + return element != null ? ( {element} ) : null; diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js b/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js index a4ec63a8c4d397..7b199aa1a9c876 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js @@ -140,10 +140,15 @@ class MultiColumnExample extends React.PureComponent< getItemLayout(data, index).length + 2 * (CARD_MARGIN + BORDER_WIDTH); return {length, offset: length * index, index}; } - _renderItemComponent = ({item}: RenderItemProps) => { + _renderItemComponent = (props: any) => { + const {item, accessibilityCollectionItem} = props; return ( - + Date: Sun, 13 Mar 2022 12:31:37 +0800 Subject: [PATCH 34/66] draft --- Libraries/Lists/FlatList.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index cfbeac7391edd1..605250933e88de 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -649,15 +649,7 @@ class FlatList extends React.PureComponent, void> { itemIndex: index, }; - return ( - // $FlowFixMe[prop-missing] https://bit.ly/3viYSh8 - - {renderer(info)} - - ); + return renderer({info, accessibilityCollectionItem}); } }, }; From 1a98f56d9ae0dad56395484ab585194b32da3f0a Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sun, 13 Mar 2022 13:44:52 +0800 Subject: [PATCH 35/66] removing container View in renderItem callback https://github.com/facebook/react-native/pull/33180/commits/4c3182a304f258823107338b93c45a69b7bdd50d The accessibilityCollectionItem is available in the parameter item.accessibilityCollectionItem As in the below rn-tester example, the collectionItem is set as follows ```jsx ``` --- Libraries/Lists/FlatList.js | 27 ++++++++++++------- .../js/examples/FlatList/FlatList-basic.js | 25 ++++++++++------- .../examples/FlatList/FlatList-multiColumn.js | 6 ++--- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 605250933e88de..66ebe02dbe1b3c 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -600,6 +600,13 @@ class FlatList extends React.PureComponent, void> { } }; + const defaultAccessibilityCollectionItem = { + rowSpan: 1, + columnIndex: 0, + columnSpan: 1, + heading: false, + }; + return { /* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb) * This comment suppresses an error found when Flow v0.111 was deployed. @@ -611,24 +618,23 @@ class FlatList extends React.PureComponent, void> { Array.isArray(item), 'Expected array of items with numColumns > 1', ); + return ( {item.map((it, kk) => { const itemIndex = index * numColumns + kk; const accessibilityCollectionItem = { + ...defaultAccessibilityCollectionItem, rowIndex: index, - rowSpan: 1, columnIndex: itemIndex % numColumns, - columnSpan: 1, - heading: false, itemIndex: itemIndex, }; + const accessibleItem = {...it, accessibilityCollectionItem}; const element = renderer({ - item: it, + item: accessibleItem, index: index * numColumns + kk, separators: info.separators, - accessibilityCollectionItem: accessibilityCollectionItem, }); return element != null ? ( @@ -641,15 +647,16 @@ class FlatList extends React.PureComponent, void> { const {index} = info; const accessibilityCollectionItem = { + ...defaultAccessibilityCollectionItem, rowIndex: index, - rowSpan: 1, - columnIndex: 0, - columnSpan: 1, - heading: false, itemIndex: index, }; + const accessibleInfo = { + ...info, + item: {...info.item, accessibilityCollectionItem}, + }; - return renderer({info, accessibilityCollectionItem}); + return renderer(accessibleInfo); } }, }; diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-basic.js b/packages/rn-tester/js/examples/FlatList/FlatList-basic.js index 259daccc7b45ac..613c7f1321b11a 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-basic.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-basic.js @@ -276,17 +276,22 @@ class FlatListExample extends React.PureComponent { /* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb) * This comment suppresses an error found when Flow v0.111 was deployed. * To see the error, delete this comment and run Flow. */ - [flatListPropKey]: ({item, separators}) => { + [flatListPropKey]: ({item, separators, accessibilityCollectionItem}) => { return ( - + + + ); }, }; diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js b/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js index 7b199aa1a9c876..69b6649c31e059 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-multiColumn.js @@ -140,15 +140,13 @@ class MultiColumnExample extends React.PureComponent< getItemLayout(data, index).length + 2 * (CARD_MARGIN + BORDER_WIDTH); return {length, offset: length * index, index}; } - _renderItemComponent = (props: any) => { - const {item, accessibilityCollectionItem} = props; + _renderItemComponent = ({item}: RenderItemProps) => { return ( Date: Sun, 13 Mar 2022 13:49:43 +0800 Subject: [PATCH 36/66] rename accessibleItem to collectionItem --- Libraries/Lists/FlatList.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 66ebe02dbe1b3c..2b2ac53180dcd2 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -629,10 +629,10 @@ class FlatList extends React.PureComponent, void> { columnIndex: itemIndex % numColumns, itemIndex: itemIndex, }; - const accessibleItem = {...it, accessibilityCollectionItem}; + const collectionItem = {...it, accessibilityCollectionItem}; const element = renderer({ - item: accessibleItem, + item: collectionItem, index: index * numColumns + kk, separators: info.separators, }); @@ -651,12 +651,12 @@ class FlatList extends React.PureComponent, void> { rowIndex: index, itemIndex: index, }; - const accessibleInfo = { + const collectionItem = { ...info, item: {...info.item, accessibilityCollectionItem}, }; - return renderer(accessibleInfo); + return renderer(collectionItem); } }, }; From f5b35816a6afa4ae5b798005134246746f7548ca Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sun, 13 Mar 2022 13:51:51 +0800 Subject: [PATCH 37/66] removing collectionItem variable --- Libraries/Lists/FlatList.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 2b2ac53180dcd2..0e118fb1211b8e 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -629,10 +629,9 @@ class FlatList extends React.PureComponent, void> { columnIndex: itemIndex % numColumns, itemIndex: itemIndex, }; - const collectionItem = {...it, accessibilityCollectionItem}; const element = renderer({ - item: collectionItem, + item: {...it, accessibilityCollectionItem}, index: index * numColumns + kk, separators: info.separators, }); @@ -651,12 +650,11 @@ class FlatList extends React.PureComponent, void> { rowIndex: index, itemIndex: index, }; - const collectionItem = { + + return renderer({ ...info, item: {...info.item, accessibilityCollectionItem}, - }; - - return renderer(collectionItem); + }); } }, }; From 4e64a528a39d54eddf1d48d44aa2a3ed4c9a66d1 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sun, 13 Mar 2022 13:53:39 +0800 Subject: [PATCH 38/66] removing const {index} = info; --- Libraries/Lists/FlatList.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 0e118fb1211b8e..8dea8fc8712be0 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -643,12 +643,10 @@ class FlatList extends React.PureComponent, void> { ); } else { - const {index} = info; - const accessibilityCollectionItem = { ...defaultAccessibilityCollectionItem, - rowIndex: index, - itemIndex: index, + rowIndex: info.index, + itemIndex: info.index, }; return renderer({ From 828fdd72d6187c1cdf01f451b30bd11ebbfdbc4a Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sun, 13 Mar 2022 14:17:00 +0800 Subject: [PATCH 39/66] adding new prop to renderItem accessibilityCollectionItem - remove the wrapper View and cellstyle flex: 1 - add prop accessibilityCollectionItem to FlatList renderItem to allow users set the accessibilityInformation - update rn-tester flatlist examples Follow up of https://github.com/fabriziobertoglio1987/react-native/commit/1a98f56d9ae0dad56395484ab585194b32da3f0a Related https://github.com/fabriziobertoglio1987/react-native-notes/issues/6#issuecomment-1064983239 --- Libraries/Lists/FlatList.js | 8 +++--- .../js/examples/FlatList/FlatList-basic.js | 2 +- .../examples/FlatList/FlatList-multiColumn.js | 4 +-- .../js/examples/FlatList/FlatList-nested.js | 25 +++++++++++-------- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 8dea8fc8712be0..c5f843a28c5c68 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -631,9 +631,10 @@ class FlatList extends React.PureComponent, void> { }; const element = renderer({ - item: {...it, accessibilityCollectionItem}, + item: it, index: index * numColumns + kk, separators: info.separators, + accessibilityCollectionItem, }); return element != null ? ( @@ -651,7 +652,7 @@ class FlatList extends React.PureComponent, void> { return renderer({ ...info, - item: {...info.item, accessibilityCollectionItem}, + accessibilityCollectionItem, }); } }, @@ -661,7 +662,7 @@ class FlatList extends React.PureComponent, void> { _getAccessibilityCollection = () => { const accessibilityCollectionProps = { itemCount: this.props.data ? this.props.data.length : 0, - //$FlowFixMe[incompatible-call] see https://bit.ly/3viYSh8 + //$FlowFixMe[incompatible-call] see https://bit.ly/3MJiZLL rowCount: this._getItemCount(this.props.data), columnCount: numColumnsOrDefault(this.props.numColumns), hierarchical: false, @@ -702,7 +703,6 @@ class FlatList extends React.PureComponent, void> { const styles = StyleSheet.create({ row: {flexDirection: 'row'}, - cellStyle: {flex: 1}, }); module.exports = FlatList; diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-basic.js b/packages/rn-tester/js/examples/FlatList/FlatList-basic.js index 613c7f1321b11a..63b235d12e6eb1 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-basic.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-basic.js @@ -280,7 +280,7 @@ class FlatListExample extends React.PureComponent { return ( ) => { + _renderItemComponent = ({item, accessibilityCollectionItem}) => { return ( ( - - {title} +const Item = ({item, accessibilityCollectionItem}) => ( + + {item.title} ); -const renderItem = ({ item }) => ; +const renderItem = (props) => ; -const renderFlatList = ({ item }) => ( - - Flatlist {item} - - -); +const renderFlatList = ({item}) => { + return ( + + Flatlist {item} + + + ); +}; const FlatListNested = () => { return ( From ce18d88eb12e50e40b5e6c02bc08da74a5ed5392 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sun, 13 Mar 2022 14:23:14 +0800 Subject: [PATCH 40/66] avoid adding new lines --- Libraries/Lists/FlatList.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index c5f843a28c5c68..b72eafbf0def3b 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -618,7 +618,6 @@ class FlatList extends React.PureComponent, void> { Array.isArray(item), 'Expected array of items with numColumns > 1', ); - return ( {item.map((it, kk) => { @@ -629,14 +628,12 @@ class FlatList extends React.PureComponent, void> { columnIndex: itemIndex % numColumns, itemIndex: itemIndex, }; - const element = renderer({ item: it, index: index * numColumns + kk, separators: info.separators, accessibilityCollectionItem, }); - return element != null ? ( {element} ) : null; From f49caa490eb2378466bfa3eeb672aa6eab5b65b7 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Sun, 13 Mar 2022 14:56:03 +0800 Subject: [PATCH 41/66] Move Logic to virtualized list https://github.com/fabriziobertoglio1987/react-native-notes/issues/6#issuecomment-1066037420 --- Libraries/Lists/FlatList.js | 14 +------------- Libraries/Lists/VirtualizedList.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index b72eafbf0def3b..76f1ca2d234593 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -656,18 +656,6 @@ class FlatList extends React.PureComponent, void> { }; }; - _getAccessibilityCollection = () => { - const accessibilityCollectionProps = { - itemCount: this.props.data ? this.props.data.length : 0, - //$FlowFixMe[incompatible-call] see https://bit.ly/3MJiZLL - rowCount: this._getItemCount(this.props.data), - columnCount: numColumnsOrDefault(this.props.numColumns), - hierarchical: false, - }; - - return accessibilityCollectionProps; - }; - render(): React.Node { const { numColumns, @@ -682,7 +670,7 @@ class FlatList extends React.PureComponent, void> { getItem={this._getItem} getItemCount={this._getItemCount} keyExtractor={this._keyExtractor} - accessibilityCollection={this._getAccessibilityCollection()} + numColumns={numColumnsOrDefault(this.props.numColumns)} accessibilityRole={Platform.select({ android: numColumnsOrDefault(this.props.numColumns) > 1 ? 'grid' : 'list', diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 2d491d4a6c79b4..af5580ca802573 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1233,6 +1233,17 @@ class VirtualizedList extends React.PureComponent { ); } + _getAccessibilityCollection = () => { + const accessibilityCollectionProps = { + itemCount: this.props.data ? this.props.data.length : 0, + rowCount: this.props.getItemCount(this.props.data), + columnCount: this.props.numColumns, + hierarchical: false, + }; + + return accessibilityCollectionProps; + }; + _defaultRenderScrollComponent = props => { const onRefresh = props.onRefresh; if (this._isNestedWithSameOrientation()) { @@ -1249,6 +1260,7 @@ class VirtualizedList extends React.PureComponent { // $FlowFixMe[prop-missing] Invalid prop usage Date: Mon, 14 Mar 2022 11:25:30 +0800 Subject: [PATCH 42/66] move accessibilityCollectionItem logic to VirtList further info at https://github.com/fabriziobertoglio1987/react-native-notes/issues/6#issuecomment-1066041327 - Adds support for SectionList, VirtualizedList - Sharing common logic between components The accessibilityCollectionItem is calculated in the VirtualizedList and passed as a 4th parameter to renderItem function https://github.com/fabriziobertoglio1987/react-native-notes/blob/f49caa490eb2378466bfa3eeb672aa6eab5b65b7/Libraries/Lists/VirtualizedList.js#L1995-L2023 ```javascript renderItem({ item, index, separators: this._separators, accessibilityCollectionItem, }); ``` adding accessibilityCollectionItem would make the FlatList cell or VirtualizedList row announce row 1 column 1, row 2 column 2 ... https://reactnative.dev/docs/next/flatlist#required-renderitem The main difference between FlatList and VirtualizedList is that FlatList can have numColumns > 1 and the computation of accessibilityCollectionItem is changed in the FlatList based on the numColumns value. TODO - Move logic to ScrollView and add support for ScrollView - Add accessibilityCollectionItem prop to View. The user can change this prop and it is part of the public API --- Libraries/Lists/FlatList.js | 29 +++--------------- Libraries/Lists/VirtualizedList.js | 48 ++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 76f1ca2d234593..99a890be998ef6 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -600,13 +600,6 @@ class FlatList extends React.PureComponent, void> { } }; - const defaultAccessibilityCollectionItem = { - rowSpan: 1, - columnIndex: 0, - columnSpan: 1, - heading: false, - }; - return { /* $FlowFixMe[invalid-computed-prop] (>=0.111.0 site=react_native_fb) * This comment suppresses an error found when Flow v0.111 was deployed. @@ -623,14 +616,13 @@ class FlatList extends React.PureComponent, void> { {item.map((it, kk) => { const itemIndex = index * numColumns + kk; const accessibilityCollectionItem = { - ...defaultAccessibilityCollectionItem, - rowIndex: index, + ...info.accessibilityCollectionItem, columnIndex: itemIndex % numColumns, itemIndex: itemIndex, }; const element = renderer({ item: it, - index: index * numColumns + kk, + index: itemIndex, separators: info.separators, accessibilityCollectionItem, }); @@ -641,16 +633,7 @@ class FlatList extends React.PureComponent, void> { ); } else { - const accessibilityCollectionItem = { - ...defaultAccessibilityCollectionItem, - rowIndex: info.index, - itemIndex: info.index, - }; - - return renderer({ - ...info, - accessibilityCollectionItem, - }); + return renderer(info); } }, }; @@ -670,11 +653,7 @@ class FlatList extends React.PureComponent, void> { getItem={this._getItem} getItemCount={this._getItemCount} keyExtractor={this._keyExtractor} - numColumns={numColumnsOrDefault(this.props.numColumns)} - accessibilityRole={Platform.select({ - android: - numColumnsOrDefault(this.props.numColumns) > 1 ? 'grid' : 'list', - })} + numColumns={numColumnsOrDefault(numColumns)} ref={this._captureRef} viewabilityConfigCallbackPairs={this._virtualizedListPairs} removeClippedSubviews={removeClippedSubviewsOrDefault( diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index af5580ca802573..6fc24cc76baf6e 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -12,6 +12,7 @@ const Batchinator = require('../Interaction/Batchinator'); const FillRateHelper = require('./FillRateHelper'); const ReactNative = require('../Renderer/shims/ReactNative'); const RefreshControl = require('../Components/RefreshControl/RefreshControl'); +const Platform = require('../Utilities/Platform'); const ScrollView = require('../Components/ScrollView/ScrollView'); const StyleSheet = require('../StyleSheet/StyleSheet'); const View = require('../Components/View/View'); @@ -305,6 +306,11 @@ type Props = {| ...OptionalProps, |}; +// numColumnsOrDefault(this.props.numColumns) +function numColumnsOrDefault(numColumns: ?number) { + return numColumns ?? 1; +} + let _usedIndexForKey = false; let _keylessItemComponentName: string = ''; @@ -1233,18 +1239,8 @@ class VirtualizedList extends React.PureComponent { ); } - _getAccessibilityCollection = () => { - const accessibilityCollectionProps = { - itemCount: this.props.data ? this.props.data.length : 0, - rowCount: this.props.getItemCount(this.props.data), - columnCount: this.props.numColumns, - hierarchical: false, - }; - - return accessibilityCollectionProps; - }; - _defaultRenderScrollComponent = props => { + const {getItemCount, data} = props; const onRefresh = props.onRefresh; if (this._isNestedWithSameOrientation()) { // $FlowFixMe[prop-missing] - Typing ReactNativeComponent revealed errors @@ -1256,11 +1252,22 @@ class VirtualizedList extends React.PureComponent { JSON.stringify(props.refreshing ?? 'undefined') + '`', ); + const numColumns = numColumnsOrDefault(props.numColumns); + const accessibilityRole = Platform.select({ + android: numColumns > 1 ? 'grid' : 'list', + }); + const accessibilityCollection = { + itemCount: data ? data.length : 0, + rowCount: getItemCount(data), + columnCount: numColumnsOrDefault(numColumns), + hierarchical: false, + }; return ( // $FlowFixMe[prop-missing] Invalid prop usage { ); } else { // $FlowFixMe[prop-missing] Invalid prop usage - return ; + return ( + + ); } }; @@ -2015,10 +2028,19 @@ class CellRenderer extends React.Component< } if (renderItem) { + const accessibilityCollectionItem = { + itemIndex: index, + rowIndex: index, + rowSpan: 1, + columnIndex: 0, + columnSpan: 1, + heading: false, + }; return renderItem({ item, index, separators: this._separators, + accessibilityCollectionItem, }); } From fb30b84a4c903726cf9b1b168944fd4c1228ffdb Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 11:58:36 +0800 Subject: [PATCH 43/66] Fix failure is caused by the missing prop type accessibilityCollectionItem Fixing https://github.com/fabriziobertoglio1987/react-native-notes/issues/6#issuecomment-1064998378 Reintroducing https://github.com/facebook/react-native/commit/32676ebe5f7555809c9d3e51efaff73ee287f5bd --- Libraries/Components/View/ViewPropTypes.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index b151095d696f95..be09897c7ad80e 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -441,6 +441,22 @@ export type ViewProps = $ReadOnly<{| */ accessibilityActions?: ?$ReadOnlyArray, + /** + * Prop used internally to announce with TalkBack rows and columns of a FlatList + * See https://bit.ly/3viYSh8 + * + * @platform android + * + */ + accessibilityCollectionItem?: ?{ + rowIndex: number, + rowSpan: number, + columnIndex: number, + columnSpan: number, + heading: boolean, + itemIndex: number, + }, + /** * Specifies the nativeID of the associated label text. When the assistive technology focuses on the component with this props, the text is read aloud. * From 4554dcc9c6262c78a949e2e0620b0fc969cfebb2 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 12:16:01 +0800 Subject: [PATCH 44/66] fix VirtList flow errors --- Libraries/Lists/VirtualizedList.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 6fc24cc76baf6e..54747de5eed58d 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -52,10 +52,20 @@ export type Separators = { ... }; +type AccessibilityCollectionItem = { + itemIndex: number, + rowIndex: number, + rowSpan: number, + columnIndex: number, + columnSpan: number, + heading: boolean, +}; + export type RenderItemProps = { item: ItemT, index: number, separators: Separators, + accessibilityCollectionItem: AccessibilityCollectionItem, ... }; @@ -74,6 +84,11 @@ type ViewabilityHelperCallbackTuple = { }; type RequiredProps = {| + /** + * The number of columns. Default is 1. Used to calculated accessibilityCollection prop. + */ + numColumns?: number, + /** * The default accessor functions assume this is an Array<{key: string} | {id: string}> but you can override * getItem, getItemCount, and keyExtractor to handle any type of index-based data. From 31c720f500cb7bee3c251aec1f32343756d90ef3 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 12:16:26 +0800 Subject: [PATCH 45/66] fix error undefined accessibilityRole in SectionList --- Libraries/Lists/VirtualizedList.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 54747de5eed58d..5ff7132aee7d31 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1257,6 +1257,16 @@ class VirtualizedList extends React.PureComponent { _defaultRenderScrollComponent = props => { const {getItemCount, data} = props; const onRefresh = props.onRefresh; + const numColumns = numColumnsOrDefault(props.numColumns); + const accessibilityRole = Platform.select({ + android: numColumns > 1 ? 'grid' : 'list', + }); + const accessibilityCollection = { + itemCount: data ? data.length : 0, + rowCount: getItemCount(data), + columnCount: numColumnsOrDefault(numColumns), + hierarchical: false, + }; if (this._isNestedWithSameOrientation()) { // $FlowFixMe[prop-missing] - Typing ReactNativeComponent revealed errors return ; @@ -1267,16 +1277,6 @@ class VirtualizedList extends React.PureComponent { JSON.stringify(props.refreshing ?? 'undefined') + '`', ); - const numColumns = numColumnsOrDefault(props.numColumns); - const accessibilityRole = Platform.select({ - android: numColumns > 1 ? 'grid' : 'list', - }); - const accessibilityCollection = { - itemCount: data ? data.length : 0, - rowCount: getItemCount(data), - columnCount: numColumnsOrDefault(numColumns), - hierarchical: false, - }; return ( // $FlowFixMe[prop-missing] Invalid prop usage Date: Mon, 14 Mar 2022 12:19:11 +0800 Subject: [PATCH 46/66] fix flow errors (deleted ) --- Libraries/Lists/VirtualizedList.js | 4 ++-- packages/rn-tester/js/examples/FlatList/FlatList-basic.js | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 5ff7132aee7d31..10a3b301fc8f9b 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1297,12 +1297,12 @@ class VirtualizedList extends React.PureComponent { /> ); } else { - // $FlowFixMe[prop-missing] Invalid prop usage return ( + // $FlowFixMe[prop-missing] Invalid prop usage ); } diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-basic.js b/packages/rn-tester/js/examples/FlatList/FlatList-basic.js index 63b235d12e6eb1..07afd006de7abc 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-basic.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-basic.js @@ -280,8 +280,7 @@ class FlatListExample extends React.PureComponent { return ( + accessibilityCollectionItem={accessibilityCollectionItem}> Date: Mon, 14 Mar 2022 13:20:03 +0800 Subject: [PATCH 47/66] passing accessibilityCollectionItem to SectionList renderItem --- Libraries/Lists/VirtualizedSectionList.js | 14 +++++++++++++- .../SectionList/SectionList-scrollable.js | 18 +++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Libraries/Lists/VirtualizedSectionList.js b/Libraries/Lists/VirtualizedSectionList.js index 8c031d54975bc6..14ace2f609d6cd 100644 --- a/Libraries/Lists/VirtualizedSectionList.js +++ b/Libraries/Lists/VirtualizedSectionList.js @@ -338,7 +338,16 @@ class VirtualizedSectionList< _renderItem = (listItemCount: number) => - ({item, index}: {item: Item, index: number, ...}) => { + ({ + item, + index, + accessibilityCollectionItem, + }: { + item: Item, + index: number, + accessibilityCollectionItem: any, + ... + }) => { const info = this._subExtractor(index); if (!info) { return null; @@ -367,6 +376,7 @@ class VirtualizedSectionList< LeadingSeparatorComponent={ infoIndex === 0 ? this.props.SectionSeparatorComponent : undefined } + accessibilityCollectionItem={accessibilityCollectionItem} cellKey={info.key} index={infoIndex} item={item} @@ -496,6 +506,7 @@ function ItemWithSeparator(props: ItemWithSeparatorProps): React.Node { index, section, inverted, + accessibilityCollectionItem, } = props; const [leadingSeparatorHiglighted, setLeadingSeparatorHighlighted] = @@ -569,6 +580,7 @@ function ItemWithSeparator(props: ItemWithSeparatorProps): React.Node { index, section, separators, + accessibilityCollectionItem, }); const leadingSeparator = LeadingSeparatorComponent != null && ( ( const renderItemComponent = setItemState => - ({item, separators}) => { + ({item, separators, accessibilityCollectionItem}) => { if (isNaN(item.key)) { return; } @@ -119,12 +119,16 @@ const renderItemComponent = }; return ( - + + + ); }; From a1dfa7751188253ef0492a6d1eff651e9b1c7772 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 13:55:04 +0800 Subject: [PATCH 48/66] VList adding AccessibilityCollectionItem type --- Libraries/Lists/VirtualizedList.js | 2 +- Libraries/Lists/VirtualizedSectionList.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 10a3b301fc8f9b..29bd853fe623d7 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -52,7 +52,7 @@ export type Separators = { ... }; -type AccessibilityCollectionItem = { +export type AccessibilityCollectionItem = { itemIndex: number, rowIndex: number, rowSpan: number, diff --git a/Libraries/Lists/VirtualizedSectionList.js b/Libraries/Lists/VirtualizedSectionList.js index 14ace2f609d6cd..4d9e62e8c3af4d 100644 --- a/Libraries/Lists/VirtualizedSectionList.js +++ b/Libraries/Lists/VirtualizedSectionList.js @@ -11,6 +11,7 @@ import invariant from 'invariant'; import type {ViewToken} from './ViewabilityHelper'; import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils'; +import type {AccessibilityCollectionItem} from './VirtualizedList'; import {View, VirtualizedList} from 'react-native'; import * as React from 'react'; @@ -345,7 +346,7 @@ class VirtualizedSectionList< }: { item: Item, index: number, - accessibilityCollectionItem: any, + accessibilityCollectionItem: AccessibilityCollectionItem, ... }) => { const info = this._subExtractor(index); @@ -489,6 +490,7 @@ type ItemWithSeparatorProps = $ReadOnly<{| updatePropsFor: (prevCellKey: string, value: Object) => void, renderItem: Function, inverted: boolean, + accessibilityCollectionItem: AccessibilityCollectionItem, |}>; function ItemWithSeparator(props: ItemWithSeparatorProps): React.Node { From 97c402b526643680228141dbe67f7373dc968a64 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 14:11:56 +0800 Subject: [PATCH 49/66] adding grid role to AccessibilityRole type ``` Error ----------------------------------------------------------------------- Libraries/Lists/VirtualizedList.js:1261:47 Cannot call `Platform.select` with object literal bound to `spec` because string [1] is incompatible with literal union [2] in property `android`. [incompatible-call] Libraries/Lists/VirtualizedList.js:1261:47 v 1261| const accessibilityRole = Platform.select({ 1262| android: numColumns > 1 ? 'grid' : 'list', 1263| }); ^ References: Libraries/Lists/VirtualizedList.js:1262:33 1262| android: numColumns > 1 ? 'grid' : 'list', ^^^^^^ [1] Libraries/Components/View/ViewPropTypes.js:430:24 430| accessibilityRole?: ?AccessibilityRole, ^^^^^^^^^^^^^^^^^ [2] ``` https://app.circleci.com/pipelines/github/facebook/react-native/12473/workflows/d7224f32-111c-4b12-a6ae-04a4e467af12/jobs/240238 --- Libraries/Components/View/ViewAccessibility.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Components/View/ViewAccessibility.js b/Libraries/Components/View/ViewAccessibility.js index 51343752c55e4e..182112160c680e 100644 --- a/Libraries/Components/View/ViewAccessibility.js +++ b/Libraries/Components/View/ViewAccessibility.js @@ -43,6 +43,7 @@ export type AccessibilityRole = | 'tablist' | 'timer' | 'list' + | 'grid' | 'toolbar'; // the info associated with an accessibility action From 6e59c555f69c68e66a3ed8b9c10b458c0a9bd634 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 14:21:17 +0800 Subject: [PATCH 50/66] update comments on accessibilityCollectionItem The [collection item][1] is set in ReactAccessibilityDelegate with method setCollectionItemInfo https://github.com/androidx/androidx/blob/150112ca4e1e670fb4eb6756993f3a25df0a5da9/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java#L3007-L3013 [1]: https://developer.android.com/reference/androidx/core/view/accessibility/AccessibilityNodeInfoCompat.CollectionItemInfoCompat --- Libraries/Components/View/ViewPropTypes.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index be09897c7ad80e..4f6f8e61238aca 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -442,8 +442,9 @@ export type ViewProps = $ReadOnly<{| accessibilityActions?: ?$ReadOnlyArray, /** - * Prop used internally to announce with TalkBack rows and columns of a FlatList - * See https://bit.ly/3viYSh8 + * + * Class with information if a node is a collection item of a FlatList, VirtualizedList or SectionList. + * A collection item starts at a given row and column in the collection, and spans one or more rows and columns. * * @platform android * From 623d9a9b52e1421d0b5b7ed623bace22f2fa069b Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 14:49:01 +0800 Subject: [PATCH 51/66] yarn test Libraries/Lists/__tests__/VirtualizedList-test.js -u --- .../VirtualizedList-test.js.snap | 360 ++++++++++++++++++ 1 file changed, 360 insertions(+) diff --git a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap index ad93703101b2ad..f86812e7591d84 100644 --- a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap @@ -3,6 +3,14 @@ exports[`VirtualizedList forwards correct stickyHeaderIndices when ListHeaderComponent present 1`] = ` Object { @@ -1566,6 +1718,14 @@ exports[`VirtualizedList test getItem functionality where data is not an Array 1 exports[`VirtualizedList warns if both renderItem or ListItemComponent are specified. Uses ListItemComponent 1`] = ` Date: Mon, 14 Mar 2022 14:52:40 +0800 Subject: [PATCH 52/66] yarn test Libraries/Lists/__tests__/VirtualizedSectionList-test.js -u --- .../VirtualizedSectionList-test.js.snap | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap index d0fc9fa107c237..5c32fe8f76d8bb 100644 --- a/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap @@ -2,6 +2,14 @@ exports[`VirtualizedSectionList handles nested lists 1`] = ` Date: Mon, 14 Mar 2022 14:54:30 +0800 Subject: [PATCH 53/66] update FlatList-test.js snapshot --- .../__snapshots__/FlatList-test.js.snap | 432 +++--------------- 1 file changed, 58 insertions(+), 374 deletions(-) diff --git a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap index 9da481fe66b42b..ef5df52685d0f6 100644 --- a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap @@ -37,6 +37,7 @@ exports[`FlatList renders all the bells and whistles 1`] = ` getItemCount={[Function]} getItemLayout={[Function]} keyExtractor={[Function]} + numColumns={2} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} @@ -75,50 +76,12 @@ exports[`FlatList renders all the bells and whistles 1`] = ` } } > - - - - - - + + @@ -132,50 +95,12 @@ exports[`FlatList renders all the bells and whistles 1`] = ` } } > - - - - - - + + @@ -189,28 +114,9 @@ exports[`FlatList renders all the bells and whistles 1`] = ` } } > - - - + - - - - - - + + - - - + @@ -445,6 +297,7 @@ exports[`FlatList renders simple list 1`] = ` getItem={[Function]} getItemCount={[Function]} keyExtractor={[Function]} + numColumns={1} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} @@ -463,82 +316,25 @@ exports[`FlatList renders simple list 1`] = ` onLayout={[Function]} style={null} > - - - + - - - + - - - + @@ -571,6 +367,7 @@ exports[`FlatList renders simple list using ListItemComponent (multiple columns) getItem={[Function]} getItemCount={[Function]} keyExtractor={[Function]} + numColumns={2} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} @@ -595,50 +392,12 @@ exports[`FlatList renders simple list using ListItemComponent (multiple columns) } } > - - - - - - + + - - - + @@ -707,6 +447,7 @@ exports[`FlatList renders simple list using ListItemComponent 1`] = ` getItem={[Function]} getItemCount={[Function]} keyExtractor={[Function]} + numColumns={1} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} @@ -724,82 +465,25 @@ exports[`FlatList renders simple list using ListItemComponent 1`] = ` onLayout={[Function]} style={null} > - - - + - - - + - - - + From 7269008b9afc1fe916cbeb0788173a5bcac6b857 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Mon, 14 Mar 2022 15:07:45 +0800 Subject: [PATCH 54/66] update SectionList snapshot tests --- .../__snapshots__/SectionList-test.js.snap | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap index 8e63455db938e0..139204914c5315 100644 --- a/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap @@ -2,6 +2,14 @@ exports[`SectionList rendering empty section headers is fine 1`] = ` Date: Mon, 14 Mar 2022 15:42:12 +0800 Subject: [PATCH 55/66] update accessibilityCollectionItem comments --- Libraries/Components/View/ViewPropTypes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 4f6f8e61238aca..ceb524fcab207a 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -443,7 +443,7 @@ export type ViewProps = $ReadOnly<{| /** * - * Class with information if a node is a collection item of a FlatList, VirtualizedList or SectionList. + * Node Information of a FlatList, VirtualizedList or SectionList collection item. * A collection item starts at a given row and column in the collection, and spans one or more rows and columns. * * @platform android From 2b9abe060e153116c99cbce4527fb95984edb876 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 15 Mar 2022 11:47:19 +0800 Subject: [PATCH 56/66] correct imports alphabetical order --- Libraries/Lists/VirtualizedList.js | 11 +++++------ Libraries/Lists/VirtualizedSectionList.js | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 29bd853fe623d7..3e45a59f0ded35 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -84,11 +84,6 @@ type ViewabilityHelperCallbackTuple = { }; type RequiredProps = {| - /** - * The number of columns. Default is 1. Used to calculated accessibilityCollection prop. - */ - numColumns?: number, - /** * The default accessor functions assume this is an Array<{key: string} | {id: string}> but you can override * getItem, getItemCount, and keyExtractor to handle any type of index-based data. @@ -102,6 +97,10 @@ type RequiredProps = {| * Determines how many items are in the data blob. */ getItemCount: (data: any) => number, + /** + * The number of columns. Default is 1. Used to calculated accessibilityCollection prop. + */ + numColumns?: number, |}; type OptionalProps = {| renderItem?: ?RenderItemType, @@ -1264,7 +1263,7 @@ class VirtualizedList extends React.PureComponent { const accessibilityCollection = { itemCount: data ? data.length : 0, rowCount: getItemCount(data), - columnCount: numColumnsOrDefault(numColumns), + columnCount: numColumns, hierarchical: false, }; if (this._isNestedWithSameOrientation()) { diff --git a/Libraries/Lists/VirtualizedSectionList.js b/Libraries/Lists/VirtualizedSectionList.js index 4d9e62e8c3af4d..05e9077612e78f 100644 --- a/Libraries/Lists/VirtualizedSectionList.js +++ b/Libraries/Lists/VirtualizedSectionList.js @@ -10,8 +10,8 @@ import invariant from 'invariant'; import type {ViewToken} from './ViewabilityHelper'; -import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils'; import type {AccessibilityCollectionItem} from './VirtualizedList'; +import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils'; import {View, VirtualizedList} from 'react-native'; import * as React from 'react'; From 489ebe4f87f89d0f9a2691e681c368e7b826485f Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 15 Mar 2022 12:02:48 +0800 Subject: [PATCH 57/66] use getChildAt instead of getContentView --- .../scroll/ReactScrollViewAccessibilityDelegate.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java index 57f26d9c44909a..6cf22db90c04e1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java @@ -56,12 +56,9 @@ private void onInitializeAccessibilityEventInternal(View view, AccessibilityEven if (accessibilityCollection != null) { event.setItemCount(accessibilityCollection.getInt("itemCount")); View contentView; - if (view instanceof ReactScrollView) { - ReactScrollView scrollView = (ReactScrollView) view; - contentView = scrollView.getContentView(); - } else if (view instanceof ReactHorizontalScrollView) { - ReactHorizontalScrollView scrollView = (ReactHorizontalScrollView) view; - contentView = scrollView.getContentView(); + if (view instanceof ViewGroup) { + ViewGroup viewGroup = (ViewGroup) view; + contentView = viewGroup.getChildAt(0); } else { return; } From 3a11bff4be8ef30b73faad1167fe45ef0de6d2cc Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 15 Mar 2022 13:28:53 +0800 Subject: [PATCH 58/66] add numColumns to restProps passed to VirtualizedList --- Libraries/Lists/FlatList.js | 2 -- Libraries/Lists/VirtualizedList.js | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Libraries/Lists/FlatList.js b/Libraries/Lists/FlatList.js index 99a890be998ef6..f9611f8ac13265 100644 --- a/Libraries/Lists/FlatList.js +++ b/Libraries/Lists/FlatList.js @@ -641,7 +641,6 @@ class FlatList extends React.PureComponent, void> { render(): React.Node { const { - numColumns, columnWrapperStyle, removeClippedSubviews: _removeClippedSubviews, ...restProps @@ -653,7 +652,6 @@ class FlatList extends React.PureComponent, void> { getItem={this._getItem} getItemCount={this._getItemCount} keyExtractor={this._keyExtractor} - numColumns={numColumnsOrDefault(numColumns)} ref={this._captureRef} viewabilityConfigCallbackPairs={this._virtualizedListPairs} removeClippedSubviews={removeClippedSubviewsOrDefault( diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 3e45a59f0ded35..11f1f36c072564 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -98,7 +98,8 @@ type RequiredProps = {| */ getItemCount: (data: any) => number, /** - * The number of columns. Default is 1. Used to calculated accessibilityCollection prop. + * The number of columns used in FlatList. + * The default of 1 is used in other components to calculate the accessibilityCollection prop. */ numColumns?: number, |}; From d50fd1a68112f40f4be3ac3aa4d67f96df33e387 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 15 Mar 2022 14:35:38 +0800 Subject: [PATCH 59/66] adding prop getCellsInItemCount to VirtualizedList getItemCount does not calculate the exact number of accessible collection Items (cells) of a virtualized list for example, a list can have 2 columns and 2 rows, but only 3 items. getItemCount would return the number of rows 2 and not the number of items 3. +--------+--------+ | item 1 | item 2 | +--------+--------+ | item 3 | | +--------+--------+ the result is calculated by dividing data.lenght / numColumns https://github.com/fabriziobertoglio1987/react-native/blob/3a11bff4be8ef30b73faad1167fe45ef0de6d2cc/Libraries/Lists/FlatList.js#L508-L515 ```javascript _getItemCount = (data: ?Array): number => { if (data) { const numColumns = numColumnsOrDefault(this.props.numColumns); return numColumns > 1 ? Math.ceil(data.length / numColumns) : data.length; } else { return 0; } }; ``` https://github.com/fabriziobertoglio1987/react-native-notes/blob/3a11bff4be8ef30b73faad1167fe45ef0de6d2cc/Libraries/Lists/VirtualizedList.js#L87-L91 ``` /** * The default accessor functions assume this is an Array<{key: string} | {id: string}> but you can override * getItem, getItemCount, and keyExtractor to handle any type of index-based data. */ data?: any, /** * Determines how many items are in the data blob. */ getItemCount: (data: any) => number, ``` this commit adds a prop getCellsInItemCount which calculates by default the correct number of items in a VirtualizedList when using data of type Array, but allows developers to over-ride this method and calculate the number of items/cells in the list with other data types. --- Libraries/Lists/VirtualizedList.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 11f1f36c072564..f4da2dbd1a2a3f 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -94,14 +94,18 @@ type RequiredProps = {| */ getItem: (data: any, index: number) => ?Item, /** - * Determines how many items are in the data blob. + * Determines how many items (rows) are in the data blob. */ getItemCount: (data: any) => number, + /** + * Determines how many cells are in the data blob + */ + getCellsInItemCount: (data: any) => number, /** * The number of columns used in FlatList. * The default of 1 is used in other components to calculate the accessibilityCollection prop. */ - numColumns?: number, + numColumns?: ?number, |}; type OptionalProps = {| renderItem?: ?RenderItemType, @@ -1254,6 +1258,13 @@ class VirtualizedList extends React.PureComponent { ); } + _getCellsInItemCount = props => { + const {getCellsInItemCount, data} = props; + if (getCellsInItemCount) return getCellsInItemCount(data); + if (Array.isArray(data)) return data.length; + return 0; + }; + _defaultRenderScrollComponent = props => { const {getItemCount, data} = props; const onRefresh = props.onRefresh; @@ -1261,9 +1272,12 @@ class VirtualizedList extends React.PureComponent { const accessibilityRole = Platform.select({ android: numColumns > 1 ? 'grid' : 'list', }); + const rowCount = getItemCount(data); const accessibilityCollection = { - itemCount: data ? data.length : 0, - rowCount: getItemCount(data), + // over-ride _getCellsInItemCount to handle Objects or other data formats + // see commit + itemCount: this._getCellsInItemCount(props), + rowCount, columnCount: numColumns, hierarchical: false, }; From 40085dc4542e4c557750d7396e5d69c89b8fc53c Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 15 Mar 2022 16:03:24 +0800 Subject: [PATCH 60/66] adding link to comment --- Libraries/Lists/VirtualizedList.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index f4da2dbd1a2a3f..e2df96480f6244 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -99,6 +99,7 @@ type RequiredProps = {| getItemCount: (data: any) => number, /** * Determines how many cells are in the data blob + * see https://bit.ly/35RKX7H */ getCellsInItemCount: (data: any) => number, /** From 1cdaf6502634ce552d6901d572ee702ff0af46cf Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 15 Mar 2022 16:13:06 +0800 Subject: [PATCH 61/66] getCellsInItemCount is optional --- Libraries/Lists/VirtualizedList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index e2df96480f6244..e4d949a7fb2044 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -101,7 +101,7 @@ type RequiredProps = {| * Determines how many cells are in the data blob * see https://bit.ly/35RKX7H */ - getCellsInItemCount: (data: any) => number, + getCellsInItemCount?: (data: any) => number, /** * The number of columns used in FlatList. * The default of 1 is used in other components to calculate the accessibilityCollection prop. From c0893d20470e5971eaee5ccc74196dbe8ec84770 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 15 Mar 2022 16:16:24 +0800 Subject: [PATCH 62/66] add link to comment --- Libraries/Lists/VirtualizedList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index e4d949a7fb2044..b0bc2dca90f88e 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1276,7 +1276,7 @@ class VirtualizedList extends React.PureComponent { const rowCount = getItemCount(data); const accessibilityCollection = { // over-ride _getCellsInItemCount to handle Objects or other data formats - // see commit + // see https://bit.ly/35RKX7H itemCount: this._getCellsInItemCount(props), rowCount, columnCount: numColumns, From cad423e389b2d0773f4fd03943078d7a5a149be1 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Wed, 16 Mar 2022 09:19:14 +0800 Subject: [PATCH 63/66] updating snapshot based on new behaviour introduced with https://github.com/fabriziobertoglio1987/react-native/commit/d50fd1a68112f40f4be3ac3aa4d67f96df33e387 --- .../Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap index f86812e7591d84..790aff7ea22e05 100644 --- a/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/VirtualizedList-test.js.snap @@ -1678,7 +1678,7 @@ exports[`VirtualizedList test getItem functionality where data is not an Array 1 Object { "columnCount": 1, "hierarchical": false, - "itemCount": undefined, + "itemCount": 0, "rowCount": 1, } } From 7e12fb6c67d6524387427ba4808bba218a580020 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Wed, 16 Mar 2022 09:25:36 +0800 Subject: [PATCH 64/66] update snapshot based on changes done in https://github.com/fabriziobertoglio1987/react-native/commit/3a11bff4be8ef30b73faad1167fe45ef0de6d2cc --- Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap index ef5df52685d0f6..062bf63589c965 100644 --- a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap @@ -142,7 +142,6 @@ exports[`FlatList renders empty list 1`] = ` getItem={[Function]} getItemCount={[Function]} keyExtractor={[Function]} - numColumns={1} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} @@ -173,7 +172,6 @@ exports[`FlatList renders null list 1`] = ` getItem={[Function]} getItemCount={[Function]} keyExtractor={[Function]} - numColumns={1} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} @@ -297,7 +295,6 @@ exports[`FlatList renders simple list 1`] = ` getItem={[Function]} getItemCount={[Function]} keyExtractor={[Function]} - numColumns={1} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} @@ -447,7 +444,6 @@ exports[`FlatList renders simple list using ListItemComponent 1`] = ` getItem={[Function]} getItemCount={[Function]} keyExtractor={[Function]} - numColumns={1} onContentSizeChange={[Function]} onLayout={[Function]} onMomentumScrollBegin={[Function]} From 6780e00fcb515af04ff91fba7f28ff7152e3210f Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Tue, 22 Mar 2022 12:42:11 +0800 Subject: [PATCH 65/66] remove changes to getContentView moved to ReactScrollAccessibilityDelegate https://github.com/fabriziobertoglio1987/react-native/blob/2cfaf4ab7729bcba27fb946cde190515ac649499/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewAccessibilityDelegate.java#L61 --- .../facebook/react/views/scroll/ReactHorizontalScrollView.java | 2 +- .../java/com/facebook/react/views/scroll/ReactScrollView.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index b183c5ee265042..83f14c50c4c104 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -654,7 +654,7 @@ private int getSnapInterval() { return getWidth(); } - public View getContentView() { + private View getContentView() { return getChildAt(0); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index f0ff6984e7ac17..d33c08f1fdbc72 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -661,7 +661,7 @@ private int predictFinalScrollPosition(int velocityY) { + getFlingExtrapolatedDistance(velocityY); } - public View getContentView() { + private View getContentView() { return getChildAt(0); } From d647b469dc4fee65c4677e713cf5189a75f2fb51 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Thu, 31 Mar 2022 13:59:37 +0800 Subject: [PATCH 66/66] adding /ReactAndroid/hermes-engine/.cxx to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0ad070d45ae83f..35da812e054329 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ project.xcworkspace /ReactAndroid/gradlew /ReactAndroid/gradlew.bat /ReactAndroid/hermes-engine/build/ +/ReactAndroid/hermes-engine/.cxx/ /template/android/app/build/ /template/android/build/