How to avoid setting manual UIView width and height on native side for Fabric component when using CAGradientLayer?

253 views Asked by At

I am trying to create a fabric module for iOS using react-native's new architecture

In my objective-c++ file while setting a UIView, I have to assign a CGRect at time of init of UIView. If I don't on the native side and just give it on js side the view is not visible.

Following does not work

Objective-C++

_view = [[UIView alloc] init];
_gradient = [CAGradientLayer layer];
_gradient.frame = _view.bounds;
    _gradient.startPoint = CGPointZero;
    _gradient.endPoint = CGPointMake(1, 1);
 _gradient.colors = @[(id)[UIColor redColor].CGColor,(id)[UIColor blackColor].CGColor,(id)[UIColor blueColor].CGColor];
    [_view.layer insertSublayer:_gradient atIndex:0];
self.contentView = _view;

JS

 <YourEdgeLinearGradientView
          style={{height: 200, width: 200, margin: 20}}
/>

Following works

Objective-C++ 

_view = [[UIView alloc] initWithFrame:CGRectMake(0,0,400,400)];
...
...

JS

 <YourEdgeLinearGradientView
          style={{height: 200, width: 200, margin: 20}}
/>

but the issue is it occupies the width and height set on the native side and ignores js side I want to use

_view = [[UIView alloc] init];

without setting width and height on native side but setting it on js side

To add on more to this if I take a UIButton or a UILAbel instead of CAGradientLayer and apply constraints to UIView then I don't have to set CGRectMake to UIView

Also I don't want to pass width and height from the specs file, whatever I set from the style property should be applied. It works fine for android component but not for iOS.

I am currently using

view = [[UIView alloc] init];

which causes issue and is not visible on JS side

If I use like below

_view = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,200)];

then it works but I don't want to set width and height on iOS side. I want to use view = [[UIView alloc] init]; and whatever width and height I define in styles on react-native side, the view should occupy that

1

There are 1 answers

0
iUrii On BEST ANSWER

The problem is related to your custom CAGradientLayer layer that has the same frame from its parent view, such as: zero frame by default - [[UIView alloc] init] or provided one - [[UIView alloc] initWithFrame:CGRectMake(0,0,400,400)].

...
_gradient.frame = _view.bounds;
...

And this layer's frame is not changed automatically when the view is resized so that you observe this behaviour and to fix this you should update the frame with (void)updateLayoutMetrics:oldLayoutMetrics: method of RCTComponentViewProtocol:

- (void)updateLayoutMetrics:(facebook::react::LayoutMetrics const &)layoutMetrics oldLayoutMetrics:(facebook::react::LayoutMetrics const &)oldLayoutMetrics {
  [super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
  
  _gradient.frame = _view.bounds;
}