Skip to content

Commit f09b54e

Browse files
authored
feat: Add support for images (#101)
1 parent 7f5f76b commit f09b54e

9 files changed

+66
-20
lines changed

example/assets/images/user.png

533 Bytes
Loading
944 Bytes
Loading
1.33 KB
Loading

example/src/App.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,24 @@ export default class App extends React.Component<{}, $FlowFixMeState> {
2020
return (
2121
<ScrollView contentContainerStyle={styles.container}>
2222
<View style={styles.segmentContainer}>
23-
<Text style={styles.text}>Segmented controls can have values</Text>
24-
<SegmentedControl values={['One', 'Two']} />
23+
<Text style={styles.text}>
24+
Segmented controls can have values and images
25+
</Text>
26+
<SegmentedControl
27+
values={['One', 'Two', require('../assets/images/user.png')]}
28+
/>
2529
</View>
2630
<View style={styles.segmentSection}>
27-
<SegmentedControl values={['One', 'Two', 'Three', 'Four', 'Five']} />
31+
<SegmentedControl
32+
values={[
33+
'One',
34+
'Two',
35+
require('../assets/images/user.png'),
36+
'Three',
37+
'Four',
38+
'Five',
39+
]}
40+
/>
2841
</View>
2942
<View style={styles.segmentSection}>
3043
<Text style={styles.text}>

ios/RNCSegmentedControl.m

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,21 @@ - (instancetype)initWithFrame:(CGRect)frame {
2323
return self;
2424
}
2525

26-
- (void)setValues:(NSArray<NSString *> *)values {
27-
[self removeAllSegments];
28-
for (NSString *value in values) {
29-
[self insertSegmentWithTitle:value
30-
atIndex:self.numberOfSegments
31-
animated:NO];
32-
}
33-
super.selectedSegmentIndex = _selectedIndex;
26+
- (void)setValues:(NSArray *)values {
27+
[self removeAllSegments];
28+
for (id segment in values) {
29+
if ([segment isKindOfClass:[NSMutableDictionary class]]){
30+
UIImage *image = [[RCTConvert UIImage:segment] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
31+
[self insertSegmentWithImage:image
32+
atIndex:self.numberOfSegments
33+
animated:NO];
34+
} else {
35+
[self insertSegmentWithTitle:(NSString *)segment
36+
atIndex:self.numberOfSegments
37+
animated:NO];
38+
}
39+
}
40+
super.selectedSegmentIndex = _selectedIndex;
3441
}
3542

3643
- (void)setSelectedIndex:(NSInteger)selectedIndex {
@@ -69,8 +76,9 @@ - (void)setTintColor:(UIColor *)tintColor {
6976
- (void)didChange {
7077
_selectedIndex = self.selectedSegmentIndex;
7178
if (_onChange) {
79+
NSString *segmentTitle = [self titleForSegmentAtIndex:_selectedIndex];
7280
_onChange(@{
73-
@"value" : [self titleForSegmentAtIndex:_selectedIndex],
81+
@"value" : (segmentTitle) ? segmentTitle : [self imageForSegmentAtIndex:_selectedIndex],
7482
@"selectedSegmentIndex" : @(_selectedIndex)
7583
});
7684
}

ios/RNCSegmentedControlManager.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ - (UIView *)view {
1919
return [RNCSegmentedControl new];
2020
}
2121

22-
RCT_EXPORT_VIEW_PROPERTY(values, NSArray<NSString *>)
22+
RCT_EXPORT_VIEW_PROPERTY(values, NSArray)
2323
RCT_EXPORT_VIEW_PROPERTY(selectedIndex, NSInteger)
2424
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
2525
RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor)

js/SegmentedControl.ios.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
'use strict';
1111

1212
import * as React from 'react';
13-
import {StyleSheet, processColor} from 'react-native';
13+
import {StyleSheet, Image, processColor} from 'react-native';
1414

1515
import RNCSegmentedControlNativeComponent from './RNCSegmentedControlNativeComponent';
1616
import type {Event, SegmentedControlProps} from './types';
@@ -54,7 +54,13 @@ class SegmentedControlIOS extends React.Component<Props> {
5454
};
5555

5656
render() {
57-
const {forwardedRef, fontStyle, activeFontStyle, ...props} = this.props;
57+
const {
58+
forwardedRef,
59+
fontStyle,
60+
activeFontStyle,
61+
values,
62+
...props
63+
} = this.props;
5864
return (
5965
<RNCSegmentedControlNativeComponent
6066
fontStyle={
@@ -79,6 +85,9 @@ class SegmentedControlIOS extends React.Component<Props> {
7985
}
8086
: undefined
8187
}
88+
values={values.map((val) =>
89+
typeof val === 'string' ? val : Image.resolveAssetSource(val),
90+
)}
8291
{...props}
8392
ref={forwardedRef}
8493
style={[styles.segmentedControl, this.props.style]}

js/SegmentedControlTab.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
'use strict';
66

77
import * as React from 'react';
8-
import {StyleSheet, View, Text, TouchableOpacity} from 'react-native';
8+
import {StyleSheet, View, Text, Image, TouchableOpacity} from 'react-native';
99
import type {FontStyle} from './types';
1010

1111
type Props = $ReadOnly<{|
12-
value: string,
12+
value: string | number | Object,
1313
tintColor?: ?string,
1414
onSelect: () => void,
1515
selected: boolean,
@@ -18,6 +18,11 @@ type Props = $ReadOnly<{|
1818
activeFontStyle?: FontStyle,
1919
|}>;
2020

21+
function isBase64(str) {
22+
const regex = /^data:image\/(?:gif|png|jpeg|bmp|webp)(?:;charset=utf-8)?;base64,(?:[A-Za-z0-9]|[+/])+={0,2}/;
23+
return str && regex.test(str);
24+
}
25+
2126
export const SegmentedControlTab = ({
2227
onSelect,
2328
value,
@@ -64,7 +69,13 @@ export const SegmentedControlTab = ({
6469
disabled={!enabled}
6570
onPress={onSelect}>
6671
<View style={[styles.default]}>
67-
<Text style={[idleStyle, selected && activeStyle]}>{value}</Text>
72+
{typeof value === 'number' || typeof value === 'object' ? (
73+
<Image source={value} style={styles.segmentImage} />
74+
) : isBase64(value) ? (
75+
<Image source={{uri: value}} style={styles.segmentImage} />
76+
) : (
77+
<Text style={[idleStyle, selected && activeStyle]}>{value}</Text>
78+
)}
6879
</View>
6980
</TouchableOpacity>
7081
);
@@ -82,4 +93,9 @@ const styles = StyleSheet.create({
8293
activeText: {
8394
fontWeight: '700',
8495
},
96+
segmentImage: {
97+
width: 17,
98+
height: 17,
99+
resizeMode: 'contain',
100+
},
85101
});

js/types.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export type SegmentedControlProps = $ReadOnly<{|
3333
/**
3434
* The labels for the control's segment buttons, in order.
3535
*/
36-
values: $ReadOnlyArray<string>,
36+
values: $ReadOnlyArray<string | number | Object>,
3737
/**
3838
* The index in `props.values` of the segment to be (pre)selected.
3939
*/
@@ -42,7 +42,7 @@ export type SegmentedControlProps = $ReadOnly<{|
4242
* Callback that is called when the user taps a segment;
4343
* passes the segment's value as an argument
4444
*/
45-
onValueChange?: ?(value: string) => mixed,
45+
onValueChange?: ?(value: string | number | Object) => mixed,
4646
/**
4747
* Callback that is called when the user taps a segment;
4848
* passes the event as an argument

0 commit comments

Comments
 (0)