6

I want to create a custom native component which renders a single line of text. The length of this text is dynamic and the typeface and size are configurable.

When I place my custom component in a standard <View /> the provided size constraints in View.onMeasure (native) are zero for height and this is MeasureSpec.EXACTLY. Returning any non-zero height in View.onMeasure does nothing.

class App extends React.Component<{}, undefined> {
  render() {
    return (
      <View style={{
          flex: 1,
        }}>
        <CustomComponent />
      </View>
    )
  }
}

How do I allow my custom native view to measure itself and provide this to React Native during measurement and layout?

marsaldev
  • 3,338
  • 2
  • 16
  • 27
Nick Marais
  • 131
  • 6

1 Answers1

7

After much time and effort I found the answer.

You need to override ViewManager.getShadowNodeClass and provide a custom implementation of ReactShadowNode.

Like so;

public class CustomShadowNode extends LayoutShadowNode implements YogaMeasureFunction {
    public CustomShadowNode() {
        this.setMeasureFunction(this);
    }

    @Override
    public long measure(
      YogaNode node,
      float width, YogaMeasureMode widthMode,
      float height, YogaMeasureMode heightMode) {
      return YogaMeasureOutput.make(0, 0);
    }
}

I used LayoutShadowNode as it appears to handle the standard layout and styling props.

I wrote more detail on the matter here.

Nick Marais
  • 131
  • 6
  • I'm trying this for myself, and I'm not even finding the getting the constructor of my shadow node called, much less the measure function. – Gabe Sechan Feb 13 '18 at 18:58
  • Thank you soooo much for shedding light on this. I'm currently in a situation where I'm trying to measure an android Native UI Component that extends `ReactRootView`, but neither `onLayout`, nor `onMeasure` seem to be running, therefore the component remains invisible. Any idea what I can do to measure it? Thanks – SudoPlz Apr 11 '18 at 12:38
  • I've not tried extending `ReactRootView` with this approach. Perhaps there is some logic which makes this view work differently. I suggest raising your issue as a new question, and linking to this question to provide some background. – Nick Marais Apr 16 '18 at 10:41