I'm writing a custom view for React Native iOS.
Basically I have to make the text as large as possible (based on the view of the current view). I've done it by overriding reactSetFrame
and changing the frame. The only issue is that the position of the view is wrong, here's a screenshot:
It seems that the "layout manager" of react native thinks that the views have height 0.
Here the code:
- (void)reactSetFrame:(CGRect)frame {
[super reactSetFrame:frame];
NSLog(@"react set frame %@", NSStringFromCGRect(frame));
[self fitText:self.text];
}
- (void)fitText:(NSString *)text {
// ... get the correct font size and expected size
[self setFont:font];
CGRect newFrame = self.frame;
newFrame.size.height = expectedLabelSize.height;
NSLog(@"new frame is %@", NSStringFromCGRect(newFrame));
self.frame = newFrame;
}
basically when the frame changes I'm updating the frame with the correct dimensions based on the text that was passed.
The logs output is this:
2017-06-25 16:43:16.434 ABC[44836:6551225] react set frame {{0, 0}, {375, 0}}
2017-06-25 16:43:16.435 ABC[44836:6551225] new frame is {{0, 0}, {375, 69.197000000000017}}
2017-06-25 16:43:16.435 ABC[44836:6551225] react set frame {{0, 0}, {375, 0}}
2017-06-25 16:43:16.436 ABC[44836:6551225] new frame is {{0, 0}, {375, 85.996999999999986}}
I've tried calling reactSetFrame
with the new frame again but it is not working. Is there a way to tell React Native that the size of a view has changed?
The general way to set the dimensions of a component is by adding a fixed width and height to style. All dimensions in React Native are unitless, and represent density-independent pixels.
import { Dimensions } from 'react-native'; You can get the application window's width and height using the following code: const windowWidth = Dimensions. get('window').
To get the parent height and width in React: Set the ref prop on the element. In the useEffect hook, update the state variables for the height and width. Use the offsetHeight and offsetWidth properties to get the height and width of the element.
onLayout This event is fired immediately once the layout has been calculated, but the new layout may not yet be reflected on the screen at the time the event is received, especially if a layout animation is in progress. Type.
So I finally found a way to do this; basically react native utilise a shadow view to get the layout information. So I had to add this code to my manager
- (RCTShadowView *)shadowView
{
return [FitTextShadowView new];
}
which is basically telling what's the shadow view for my component.
Then I had to change the implementation of the measure function that is used by Yoga to get the correct height:
@implementation FitTextShadowView
static YGSize RCTMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode)
{
FitTextShadowView *shadowText = (__bridge FitTextShadowView *)YGNodeGetContext(node);
YGSize result;
result.width = width;
result.height = [shadowText getHeight:shadowText.text thatFits:width];
return result;
}
- (instancetype)init
{
if ((self = [super init])) {
YGNodeSetMeasureFunc(self.yogaNode, RCTMeasure);
}
return self;
}
@end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With