mirror of
https://github.com/status-im/react-native.git
synced 2025-01-13 19:15:05 +00:00
Add support for async callbacks in ReactFindViewUtil
Reviewed By: AaaChiuuu Differential Revision: D4841500 fbshipit-source-id: 16620d72bd636ad13085c15c38862e16da6c42d2
This commit is contained in:
parent
8fc3b48c65
commit
21819f1a99
@ -37,9 +37,28 @@ public class NativeIdTestCase extends ReactAppInstrumentationTestCase {
|
||||
"TextInput",
|
||||
"View");
|
||||
|
||||
private boolean mViewFound;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
mViewFound = false;
|
||||
ReactFindViewUtil.addViewListener(new ReactFindViewUtil.OnViewFoundListener() {
|
||||
@Override
|
||||
public String getNativeId() {
|
||||
return viewTags.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewFound(View view) {
|
||||
mViewFound = true;
|
||||
}
|
||||
});
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testPropertyIsSetForViews() {
|
||||
for (String nativeId : viewTags) {
|
||||
View viewWithTag = ReactFindViewUtil.findViewByNativeId(
|
||||
View viewWithTag = ReactFindViewUtil.findView(
|
||||
getActivity().getRootView(),
|
||||
nativeId);
|
||||
assertNotNull(
|
||||
@ -47,4 +66,28 @@ public class NativeIdTestCase extends ReactAppInstrumentationTestCase {
|
||||
viewWithTag);
|
||||
}
|
||||
}
|
||||
|
||||
public void testViewListener() {
|
||||
assertTrue("OnViewFound callback was never invoked", mViewFound);
|
||||
}
|
||||
|
||||
public void testFindView() {
|
||||
mViewFound = false;
|
||||
ReactFindViewUtil.findView(
|
||||
getActivity().getRootView(),
|
||||
new ReactFindViewUtil.OnViewFoundListener() {
|
||||
@Override
|
||||
public String getNativeId() {
|
||||
return viewTags.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewFound(View view) {
|
||||
mViewFound = true;
|
||||
}
|
||||
});
|
||||
assertTrue(
|
||||
"OnViewFound callback should have successfully been invoked synchronously",
|
||||
mViewFound);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ android_library(
|
||||
react_native_target("java/com/facebook/react/modules/i18nmanager:i18nmanager"),
|
||||
react_native_target("java/com/facebook/react/touch:touch"),
|
||||
react_native_target("java/com/facebook/react/uimanager/annotations:annotations"),
|
||||
react_native_target("java/com/facebook/react/uimanager/util:util"),
|
||||
react_native_target("res:uimanager"),
|
||||
],
|
||||
)
|
||||
|
@ -5,9 +5,11 @@ package com.facebook.react.uimanager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
import com.facebook.react.R;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.util.ReactFindViewUtil;
|
||||
|
||||
/**
|
||||
* Base class that should be suitable for the majority of subclasses of {@link ViewManager}.
|
||||
@ -96,6 +98,7 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||
@ReactProp(name = PROP_NATIVE_ID)
|
||||
public void setNativeId(T view, String nativeId) {
|
||||
view.setTag(R.id.view_tag_native_id, nativeId);
|
||||
ReactFindViewUtil.notifyViewRendered(view);
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_ACCESSIBILITY_LABEL)
|
||||
|
@ -4,6 +4,10 @@ package com.facebook.react.uimanager.util;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
@ -14,25 +18,98 @@ import com.facebook.react.R;
|
||||
*/
|
||||
public class ReactFindViewUtil {
|
||||
|
||||
private static final List<OnViewFoundListener> mOnViewFoundListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Finds a view that is tagged with {@param nativeId} as its `nativeID` prop
|
||||
* Callback to be invoked when a react native view has been found
|
||||
*/
|
||||
public static @Nullable View findViewByNativeId(View view, String nativeId) {
|
||||
Object tag = view.getTag(R.id.view_tag_native_id);
|
||||
if (tag instanceof String && tag.equals(nativeId)) {
|
||||
return view;
|
||||
public interface OnViewFoundListener {
|
||||
|
||||
/**
|
||||
* Returns the native id of the view of interest
|
||||
*/
|
||||
String getNativeId();
|
||||
|
||||
/**
|
||||
* Called when the view has been found
|
||||
* @param view
|
||||
*/
|
||||
void onViewFound(View view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a view that is tagged with {@param nativeId} as its nativeID prop
|
||||
* under the {@param root} view hierarchy. Returns the view if found, null otherwise.
|
||||
* @param root root of the view hierarchy from which to find the view
|
||||
*/
|
||||
public static @Nullable View findView(View root, String nativeId) {
|
||||
String tag = getNativeId(root);
|
||||
if (tag != null && tag.equals(nativeId)) {
|
||||
return root;
|
||||
}
|
||||
|
||||
if (view instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) view;
|
||||
if (root instanceof ViewGroup) {
|
||||
ViewGroup viewGroup = (ViewGroup) root;
|
||||
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
||||
View v = findViewByNativeId(viewGroup.getChildAt(i), nativeId);
|
||||
if (v != null) {
|
||||
return v;
|
||||
View view = findView(viewGroup.getChildAt(i), nativeId);
|
||||
if (view != null) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a view tagged with {@param onViewFoundListener}'s nativeID in the given {@param root}
|
||||
* view hierarchy. If the view does not exist yet due to React Native's async layout, a listener
|
||||
* will be added. When the view is found, the {@param onViewFoundListener} will be invoked.
|
||||
* @param root root of the view hierarchy from which to find the view
|
||||
*/
|
||||
public static void findView(View root, OnViewFoundListener onViewFoundListener) {
|
||||
View view = findView(root, onViewFoundListener.getNativeId());
|
||||
if (view != null) {
|
||||
onViewFoundListener.onViewFound(view);
|
||||
}
|
||||
addViewListener(onViewFoundListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an OnViewFoundListener to be invoked when a view with a matching nativeID is found.
|
||||
* Remove this listener using removeViewListener() if it's no longer needed.
|
||||
*/
|
||||
public static void addViewListener(OnViewFoundListener onViewFoundListener) {
|
||||
mOnViewFoundListeners.add(onViewFoundListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an OnViewFoundListener previously registered with addViewListener().
|
||||
*/
|
||||
public static void removeViewListener(OnViewFoundListener onViewFoundListener) {
|
||||
mOnViewFoundListeners.remove(onViewFoundListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes any listeners that are listening on this {@param view}'s native id
|
||||
*/
|
||||
public static void notifyViewRendered(View view) {
|
||||
String nativeId = getNativeId(view);
|
||||
if (nativeId == null) {
|
||||
return;
|
||||
}
|
||||
Iterator<OnViewFoundListener> iterator = mOnViewFoundListeners.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
OnViewFoundListener listener = iterator.next();
|
||||
if (nativeId != null && nativeId.equals(listener.getNativeId())) {
|
||||
listener.onViewFound(view);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable String getNativeId(View view) {
|
||||
Object tag = view.getTag(R.id.view_tag_native_id);
|
||||
return tag instanceof String ? (String) tag : null;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user