React native custom IOS native UI component
With React Native, all view components written in javascript can be rendered in both IOS and Android with one codebase. However, when a native IOS UI component is not available in React Native lib yet, the following are the basic steps needed to create a IOS native ui component, bridge it react native and use javascript to render the custom view component written in native IOS.
1. In XCode, create a new file: File -> New -> File… -> Cocoa Touch Class, name it NativeCustomView and add the following. This file is the main content for the custom view.
import UIKit class NativeCustomView: UIView { @objc var message: String? = "Hello Native Custom View" { didSet { self.setupView() } } @objc var bgColor: String? { didSet { self.setupView() } } @objc var onClick: RCTBubblingEventBlock? override init(frame: CGRect) { super.init(frame: frame) setupView() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupView() } private func hexStringToUIColor (hex:String) -> UIColor { var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() if (cString.hasPrefix("#")) { cString.remove(at: cString.startIndex) } if ((cString.count) != 6) { return UIColor.gray } var rgbValue:UInt64 = 0 Scanner(string: cString).scanHexInt64(&rgbValue) return UIColor( red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, blue: CGFloat(rgbValue & 0x0000FF) / 255.0, alpha: CGFloat(1.0) ) } private func setupView() { // set background color received from react native self.backgroundColor = (self.bgColor != nil) ? hexStringToUIColor(hex: self.bgColor!) : .red // make the view clickable self.isUserInteractionEnabled = true // add a text view and set the message received from react native let textView = UITextView() textView.center = self.center textView.textAlignment = NSTextAlignment.center textView.textColor = UIColor.blue textView.backgroundColor = UIColor.lightGray textView.text = self.message textView.isEditable = false textView.sizeToFit() self.addSubview(textView) // center the text view textView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ textView.widthAnchor.constraint(equalToConstant: 260), textView.heightAnchor.constraint(equalToConstant: 30), textView.centerXAnchor.constraint(equalTo: self.centerXAnchor), textView.centerYAnchor.constraint(equalTo: self.centerYAnchor) ]) } // when the view is clicked, send click event with some data to react native override func touchesEnded(_ touches: Set, with event: UIEvent?) { guard let onClick = self.onClick else { return } let params: [String : Any] = ["receivedBgColor":self.bgColor,"receivedMessage": self.message, "response":"hey, you've touched screen."] onClick(params) } }
2. In XCode, create another file with the same name NativeCustomView but choose Object c file: File -> New -> File… -> Objective-C File, and add the following. This file defines the properties for the custom view and expose them to React Native.
#import// NativeCustomViewManager maps to NativeCustomView in react native requireNativeComponent('NativeCustomView'); // message maps to the message prop on react native's view property // bgColor maps to the bgColor prop on react native's view property // onClick maps to the onClick prop on react native's view property @interface RCT_EXTERN_MODULE(NativeCustomViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(message, NSString) RCT_EXPORT_VIEW_PROPERTY(bgColor, NSString) RCT_EXPORT_VIEW_PROPERTY(onClick, RCTBubblingEventBlock) @end
3. On step 2, when creating the Object-C File, XCode will ask if you want to create a bridge file, select yes to create it. It will create a file YourProjectName-Bridgin-Header.h, open this file and add the following.
// // Use this file to import your target's public headers that you would like to expose to Swift. // #import#import #import #import #import #import
4. Create another swift file and name it NativeCustomViewManager, this registers NativeCustomView with React Native.
@objc (NativeCustomViewManager) class NativeCustomViewManager: RCTViewManager { override static func requiresMainQueueSetup() -> Bool { return true } override func view() -> UIView! { return NativeCustomView() } }
5. Back to the React Native using any IDE such as VSCode for javascript development, create a file NativeCustomView.tsx with the following.
import { requireNativeComponent } from 'react-native'; //Error "Tried to register two views with the same name AdMobView" //will be thrown during hot reload when any change is made to the //file that is calling this requireNativeComponent('AdMobView') call. //Leaving this on its own file will resolve this issue. const NativeCustomView = requireNativeComponent('NativeCustomView'); export default NativeCustomView;
6. Create another file to render the custom view MyNativeCustomView.tsx
mport React from 'react'; import { StyleProp, ViewStyle } from 'react-native'; import NativeCustomView from './NativeCustomView'; type IProps = { message: String, bgColor: String, onClick: Function, style: StyleProp| undefined, } const MyNativeCustomView: React.FC = (props) => { const {message, bgColor, onClick, style} = props; const _onClick = (event) => { if (!onClick) { return; } onClick(event.nativeEvent); } return }; export default MyNativeCustomView;
7. Lastly, you can render MyNativeCustomView anywhere in your react native codebase like this
{ console.log("Click event: " + JSON.stringify(event)) }} style={{ width: '100%', height: 100 }} />
8. Reinstall the app
react-native run-ios
9. The custom view should display the message ‘Hello, React Native IOS custom view’ with green background, click on the custom view, a log should be printed with something like this: Click event: {“receivedBgColor”:”#4CAF50″,”response”:”hey, you’ve touched screen.”,”receivedMessage”:”Hello, React Native IOS custom view”,”target”:425}
Reference:
https://reactnative.dev/docs/native-components-ios
Search within Codexpedia
Search the entire web