Skip to content

Commit 16e50fb

Browse files
jorge-cabfacebook-github-bot
authored andcommitted
Add fabric implementation to find Top-Most relative and relevant parent of a child view (#50404)
Summary: Pull Request resolved: #50404 Add another function to fabric to get the topmost stacking context parent given a root and a child. This is to be used on focus searching algorithm in the case where the next focusable child is deeper in the hierarchy meaning we need to find the top most parent in the Android hierarchy and lay that out as well before transferring focus. If we don't lay out the parent as well as the next focusable view: - The next focusable view might lack context given by the parent - If the parent is a scrollview and has removeClippedSubviews enabled then laying out the next focusable view will not work - If the view is deeper in the android hierarchy in some cases it won't be layed out unless the parent is Differential Revision: D72178408
1 parent 865cc37 commit 16e50fb

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

Diff for: packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManagerBinding.kt

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ internal class FabricUIManagerBinding : HybridClassBase() {
5757

5858
external fun findNextFocusableElement(parentTag: Int, focusedTag: Int, direction: Int): Int
5959

60+
external fun findRelativeTopMostParent(rootTag: Int, childTag: Int): Int
61+
6062
external fun stopSurface(surfaceId: Int)
6163

6264
external fun stopSurfaceWithSurfaceHandler(surfaceHandler: SurfaceHandlerBinding)

Diff for: packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,40 @@ jint FabricUIManagerBinding::findNextFocusableElement(
244244
return nextNode->getTag();
245245
}
246246

247+
jint FabricUIManagerBinding::findRelativeTopMostParent(
248+
jint rootTag,
249+
jint childTag) {
250+
std::shared_ptr<UIManager> uimanager = getScheduler()->getUIManager();
251+
252+
ShadowNode::Shared childShadowNode =
253+
uimanager->findShadowNodeByTag_DEPRECATED(childTag);
254+
ShadowNode::Shared rootShadowNode =
255+
uimanager->findShadowNodeByTag_DEPRECATED(rootTag);
256+
257+
if (childShadowNode == nullptr || rootShadowNode == nullptr) {
258+
return -1;
259+
}
260+
261+
ShadowNode::AncestorList ancestorList =
262+
childShadowNode->getFamily().getAncestors(*rootShadowNode);
263+
264+
if (ancestorList.empty() || ancestorList.size() < 2) {
265+
return -1;
266+
}
267+
268+
// ignore the first ancestor as it is the rootShadowNode itself
269+
for (auto it = std::next(ancestorList.begin()); it != ancestorList.end();
270+
++it) {
271+
auto& ancestor = *it;
272+
if (ancestor.first.get().getTraits().check(
273+
ShadowNodeTraits::Trait::FormsStackingContext)) {
274+
return ancestor.first.get().getTag();
275+
}
276+
}
277+
278+
return -1;
279+
}
280+
247281
// Used by non-bridgeless+Fabric
248282
void FabricUIManagerBinding::startSurfaceWithConstraints(
249283
jint surfaceId,
@@ -719,6 +753,9 @@ void FabricUIManagerBinding::registerNatives() {
719753
makeNativeMethod(
720754
"findNextFocusableElement",
721755
FabricUIManagerBinding::findNextFocusableElement),
756+
makeNativeMethod(
757+
"findRelativeTopMostParent",
758+
FabricUIManagerBinding::findRelativeTopMostParent),
722759
});
723760
}
724761

Diff for: packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ class FabricUIManagerBinding : public jni::HybridClass<FabricUIManagerBinding>,
135135
jint
136136
findNextFocusableElement(jint parentTag, jint focusedTag, jint direction);
137137

138+
jint findRelativeTopMostParent(jint rootTag, jint childTag);
139+
138140
void uninstallFabricUIManager();
139141

140142
// Private member variables

0 commit comments

Comments
 (0)