React Native に UISegmentedControl がないじゃん っていうのを見かけて。どうやって実装しているのか興味あったのでやり方を覚えた。
ソースコード直接みてるのでドキュメントちゃんと読んでないので間違ったこと書いているかもしれないことを留意。
まず Libraries/Components/SegmentedControlIOS/SegmentedControlIOS.ios.js を掘ってJSでReactコンポーネントを作る
var SegmentedControlIOS = React.createClass({
mixins: [NativeMethodsMixin],
propTypes: {
tintColor: PropTypes.string,
},
getDefaultProps: function(): DefaultProps {
return {
tintColor: "#007AFF",
};
},
render: function() {
return (
<View
style={[{height: 29, width: 140}, this.props.style]}>
<UISegmentedControl style={[{height: 29, width: 140}]} />
</View>
);
}
});
Viewでラップする。試したいだけだからheight,widthはとりあえずハードコードしちゃう。
var UISegmentedControl = createReactIOSNativeComponentClass({
validAttributes: {},
uiViewClassName: 'UISegmentedControl',
});
createReactIOSNativeComponentClass
で呼び出したいクラスを書く。
Libraries/react-native/react-native.js
の中に追加する
PickerIOS: require('PickerIOS'),
Navigator: require('Navigator'),
ScrollView: require('ScrollView'),
+ SegmentedControlIOS: require('SegmentedControlIOS'),
SliderIOS: require('SliderIOS'),
SwitchIOS: require('SwitchIOS'),
TabBarIOS: require('TabBarIOS'),
React/Views/RCTUISegmentedControlManager.m で呼び出される側のObjective-Cのクラスを書く。
@interface RCTUISegmentedControlManager : RCTViewManager
RCTViewManager
を継承したクラスがそのViewの管理をする。
- (UIView *)view
{
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"WIP1", @"WIP2", @"WIP3"]];
[segmentedControl addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged];
return segmentedControl;
}
-view
が目的のViewを初期化返す。上記は仮のコード。
これは UISegmentedControl を直接使っているけど、React Native 用の処理を加えたかったら継承して RCTSegmentedControl
のような名前のクラスをつくるのが作法のようだ。
- (void)onChange:(UISegmentedControl *)sender
{
[self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:@{
@"target": sender.reactTag,
@"value": @(sender.selectedSegmentIndex)
}];
}
onChange:
ではJavaScript側に送信する処理を書く。上記はとくに何もやってない仮のコード。
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor);
RCT_EXPORT_VIEW_PROPERTY(momentary, BOOL);
クラスのプロパティをRCT_EXPORT_VIEW_PROPERTY
で公開して、JSXから設定できるようにする(ここも仮)。
そうすると
return (<SegmentedControlIOS />);
でとりあえず描画できるようになった。