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