Issue
I have a react native project, and I need to embed a third-party native control (which I don't have the source code to or any influence over).
I have defined my own wrapper component:
public class MyWrapperView extends LinearLayout {
private ThirdPartyView mThirdPartyView;
public MyWrapperView(ThemedReactContext context) {
super(context);
mThirdPartyView = new ThirdPartyView();
addView(mThirdPartyView);
}
}
This works, and the view is visible, but my problem is that the size of the view is decided by the react-native layout algorithm. I.e, if I do
function SomeComponent() {
return (
<View>
<MyWrapperView />
</View>
);
}
my wrapper component will be invisible because it is given a height of 0.
I could add
function SomeComponent() {
return (
<View>
<MyWrapperView style={{height: 50}} />
</View>
);
}
which will make the component visible, but the problem is: I don't know which height to use. The height can also change dynamically depending on external communication in the component.
I have verified that onMeasure
is invoked with MeasureSpec.EXACTLY
, so React native clearly wants to decide how big my view should be.
How can I specify that I want my view to be as big as it wants, and then the container should adapt to it?
How can I
Solution
I worked around the problem with code like this:
public void initializeSizeChecker() {
Choreographer.getInstance().postFrameCallback(new
Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
View childView = getTheChildView();
int width = childView.getWidth();
int height = childView.getHeight();
if (width != getWidth() || height != getHeight()) {
measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
int left = getLeft();
int top = getTop();
layout(left, top, left + width, top + height);
onSizeChange((int)PixelUtil.toDIPFromPixel(width), (int)PixelUtil.toDIPFromPixel(height));
getViewTreeObserver().dispatchOnGlobalLayout();
}
Choreographer.getInstance().postFrameCallback(this);
}
});
}
private void onSizeChange(int width, int height) {
WritableMap event = Arguments.createMap();
event.putInt("width", width);
event.putInt("height", height);
ReactContext reactContext = (ReactContext)getContext();
reactContext
.getJSModule(RCTEventEmitter.class)
.receiveEvent(getId(), "sizeChange", event);
}
and then in my JS:
function ComponentWrapper() => {
const [height, setHeight] = React.useState(0);
const onSizeChange = React.useCallback(e => {
setHeight(e.nativeEvent.height);
}, []);
return <NativeComponent style={{ height }} onSizeChange={onSizeChange} />;
}
Answered By - erikkallen
Answer Checked By - Candace Johnson (JavaFixing Volunteer)