0

I'm working on a react native wrapper to a 3rd party library. I need to display a view that will display an image that is loaded via the third party library. So i first add a subclass of RCTView in the view hierarchy, start loading the image and when the image is loaded I resize the view to display the image with no cropping or padding.

The issue i'm running into is that I can resize my subclass of RCTView and that works fine, but other element around my view are not relayed out, so my view end up behind the view that is below it...

Here is the screenshot, the white part in the middle should be taller to display the full image. enter image description here

The important part of the code

class EquativDisplayView: ExpoView {
let container = UIView()
var bannerView:SASBannerView?

required init(appContext: AppContext? = nil) {
    super.init(appContext: appContext)
    clipsToBounds = true
    addSubview(container)
}

override func layoutSubviews() {
    //make sure all the view keep the same size
    container.frame = bounds
    bannerView?.frame = bounds
}

func setConfiguration(_ configuration: Configuration) {
    //load the image
    let bannerView = SASBannerView(frame: CGRect(x: 0, y: 0, width: bounds.width, height: 0))

    let adPlacement = SASAdPlacement.init(testAd: SASAdPlacementTest(rawValue:  testPlacementId) ?? .bannerMRAID)
    bannerView.load(with: adPlacement)
    
    bannerView.delegate = self
    
    // Adding the banner view to the current view controller
    container.addSubview(bannerView)
    self.bannerView = bannerView
}
}


extension EquativDisplayView :SASBannerViewDelegate
{
func bannerView(_ bannerView: SASBannerView, didDownloadAd ad: SASAd) {
    
    print("ad did load")
    let optimalHeight = bannerView.optimalAdViewHeight(forContainer: nil)
    let newFrame = CGRect(x: frame.origin.x,
                          y: frame.origin.y,
                          width: frame.size.width,
                          height: optimalHeight)
    frame = newFrame
    print("resizing %@", newFrame)
    setNeedsLayout()
    superview!.setNeedsLayout()      < ============ at this point I'm expecting the screen layout to get updated, but i'm clearly missing something
}
}

the react native side

export default function App() {
  return (
    <View style={styles.container}>
      <View style={{ height: 100 }} />
      <Text style={{ flex: 1, backgroundColor: "yellow", width: "100%", textAlign: "center" }}>
        {EquativDisplay.hello()}
      </Text>
      <EquativDisplay.EquativDisplayView
        style={{
          width: "100%",
          padding: 10,
          backgroundColor: "green",
        }}
        configuration={{
          testPlacementId: EquativDisplay.PlacementTest.BannerMRAID,
        }}
      />
      <Text style={{ flex: 1, backgroundColor: "yellow", width: "100%", textAlign: "center" }}>
        {EquativDisplay.hello()}
      </Text>
    </View>
  )
}

The output from the logs:

layoutSubviews %@ (0.0, 0.0, 393.0, 20.0)
ad did load
resizing %@ (0.0, 466.0, 393.0, 61.0)
layoutSubviews %@ (0.0, 0.0, 393.0, 61.0)

The height should be 61 which is correct, the bottom yellow view should be resized, but is not.

otusweb
  • 1,638
  • 1
  • 19
  • 30

1 Answers1

0

After a lot of searching around I found that the following code notify the bridge that the view changed size and cause a relayout:

   self.appContext?.reactBridge?.uiManager.setIntrinsicContentSize(frame.size, for: self)

Where self is the view, so I call this right after I change the frame of the view.

otusweb
  • 1,638
  • 1
  • 19
  • 30