Skip to content

Commit 63fe2ac

Browse files
committed
allow passing items to TabBar instead of children
1 parent a430f21 commit 63fe2ac

File tree

4 files changed

+123
-35
lines changed

4 files changed

+123
-35
lines changed

demo/src/screens/incubatorScreens/TabControllerScreen/index.js

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@ import Tab1 from './tab1';
66
import Tab2 from './tab2';
77
import Tab3 from './tab3';
88

9+
const TABS = ['tab1', 'tab2' , 'tab3', 'account', 'groups', 'blog'];
10+
911
class TabControllerScreen extends Component {
1012
state = {
1113
selectedIndex: 0,
14+
items: [
15+
..._.map(TABS, tab => ({label: tab, key: tab})),
16+
{key: 'addTabs', icon: Assets.icons.settings, ignore: true, onPress: this.addTab},
17+
],
18+
1219
tabsCount: 3,
1320
key: Date.now(),
1421
};
@@ -35,23 +42,31 @@ class TabControllerScreen extends Component {
3542
}
3643
};
3744

38-
renderTabItems() {
45+
getItems = () => {
3946
const {tabsCount} = this.state;
40-
const tabs = [
41-
<Incubator.TabController.TabBarItem key="tab1" label="tab1" onPress={() => console.warn('press tab1')} />,
42-
<Incubator.TabController.TabBarItem key="tab2" label="tab2" />,
43-
<Incubator.TabController.TabBarItem key="tab3" label="tab3" />,
44-
<Incubator.TabController.TabBarItem key="account" label="account" badge={{label: '9'}} />,
45-
<Incubator.TabController.TabBarItem key="groups" label="groups" />,
46-
<Incubator.TabController.TabBarItem key="blog" label="blog" />,
47-
];
48-
49-
return [
50-
..._.take(tabs, tabsCount),
51-
<Incubator.TabController.TabBarItem key="addTabs" icon={Assets.icons.settings} ignore onPress={this.addTab} />,
52-
];
47+
const items = _.chain(TABS).take(tabsCount).map(tab => ({label: tab, key: tab})).value();
48+
items.push({key: 'addTabs', icon: Assets.icons.settings, ignore: true, onPress: this.addTab});
49+
50+
return items;
5351
}
5452

53+
// renderTabItems() {
54+
// const {tabsCount} = this.state;
55+
// const tabs = [
56+
// <Incubator.TabController.TabBarItem key="tab1" label="tab1" onPress={() => console.warn('press tab1')} />,
57+
// <Incubator.TabController.TabBarItem key="tab2" label="tab2" />,
58+
// <Incubator.TabController.TabBarItem key="tab3" label="tab3" />,
59+
// <Incubator.TabController.TabBarItem key="account" label="account" badge={{label: '9'}} />,
60+
// <Incubator.TabController.TabBarItem key="groups" label="groups" />,
61+
// <Incubator.TabController.TabBarItem key="blog" label="blog" />,
62+
// ];
63+
64+
// return [
65+
// ..._.take(tabs, tabsCount),
66+
// <Incubator.TabController.TabBarItem key="addTabs" icon={Assets.icons.settings} ignore onPress={this.addTab} />,
67+
// ];
68+
// }
69+
5570
renderTabPages() {
5671
return (
5772
<View flex>
@@ -78,7 +93,7 @@ class TabControllerScreen extends Component {
7893
}
7994

8095
render() {
81-
const {key, selectedIndex} = this.state;
96+
const {key, selectedIndex, items} = this.state;
8297
return (
8398
<View flex bg-dark80>
8499
<View flex>
@@ -88,6 +103,7 @@ class TabControllerScreen extends Component {
88103
_onChangeIndex={index => console.warn('tab index is', index)}
89104
>
90105
<Incubator.TabController.TabBar
106+
items={this.getItems()}
91107
// key={key}
92108
uppercase
93109
// indicatorStyle={{backgroundColor: 'green', height: 3}}
@@ -98,7 +114,7 @@ class TabControllerScreen extends Component {
98114
// selectedIconColor={'blue'}
99115
activeBackgroundColor={Colors.blue60}
100116
>
101-
{this.renderTabItems()}
117+
{/* {this.renderTabItems()} */}
102118
</Incubator.TabController.TabBar>
103119
{this.renderTabPages()}
104120
</Incubator.TabController>

src/incubator/TabController/TabBar.js

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import PropTypes from 'prop-types';
77
import _ from 'lodash';
88

99
import TabBarContext from './TabBarContext';
10+
import TabBarItem from './TabBarItem';
1011
import ReanimatedObject from './ReanimatedObject';
1112
import {asBaseComponent, forwardRef} from '../../commons';
1213
import View from '../../components/view';
@@ -26,6 +27,10 @@ class TabBar extends PureComponent {
2627
static contextType = TabBarContext;
2728

2829
static propTypes = {
30+
/**
31+
* The list of tab bar items
32+
*/
33+
items: PropTypes.arrayOf(PropTypes.shape(TabBarItem)),
2934
/**
3035
* Tab Bar height
3136
*/
@@ -83,9 +88,12 @@ class TabBar extends PureComponent {
8388

8489
constructor(props, context) {
8590
super(props, context);
86-
const {registerTabItems} = this.context;
87-
const itemsCount = React.Children.count(this.children);
88-
const ignoredItems = [];
91+
92+
if (this.props.children) {
93+
console.warn('uilib: Please pass the "items" prop to TabController.TabBar instead of children');
94+
}
95+
96+
const itemsCount = this.itemsCount;
8997

9098
this.tabBar = React.createRef();
9199

@@ -102,18 +110,48 @@ class TabBar extends PureComponent {
102110
itemsWidths: undefined,
103111
};
104112

105-
React.Children.toArray(this.children).forEach((child, index) => {
106-
if (child.props.ignore) {
107-
ignoredItems.push(index);
108-
}
109-
});
110-
registerTabItems(itemsCount, ignoredItems);
113+
this.registerTabItems();
111114
}
112115

113116
get children() {
114117
return _.filter(this.props.children, child => !!child);
115118
}
116119

120+
get itemsCount() {
121+
const {items} = this.props;
122+
if (items) {
123+
return _.size(items);
124+
} else {
125+
return React.Children.count(this.children);
126+
}
127+
}
128+
129+
registerTabItems() {
130+
const {registerTabItems} = this.context;
131+
const {items} = this.props;
132+
const ignoredItems = [];
133+
let itemsCount;
134+
135+
if (items) {
136+
itemsCount = _.size(items);
137+
_.forEach(items, (item, index) => {
138+
if (item.ignore) {
139+
ignoredItems.push(index);
140+
}
141+
});
142+
// TODO: deprecate with props.children
143+
} else {
144+
itemsCount = React.Children.count(this.children);
145+
React.Children.toArray(this.children).forEach((child, index) => {
146+
if (child.props.ignore) {
147+
ignoredItems.push(index);
148+
}
149+
});
150+
}
151+
152+
registerTabItems(itemsCount, ignoredItems);
153+
}
154+
117155
onItemLayout = (itemWidth, itemIndex) => {
118156
this._itemsWidths[itemIndex] = itemWidth;
119157
if (!_.includes(this._itemsWidths, null)) {
@@ -170,6 +208,7 @@ class TabBar extends PureComponent {
170208
renderTabBarItems() {
171209
const {itemStates} = this.context;
172210
const {
211+
items,
173212
labelColor,
174213
selectedLabelColor,
175214
labelStyle,
@@ -178,7 +217,33 @@ class TabBar extends PureComponent {
178217
selectedIconColor,
179218
activeBackgroundColor,
180219
} = this.props;
181-
if (!_.isEmpty(itemStates)) {
220+
221+
if (_.isEmpty(itemStates)) {
222+
return;
223+
}
224+
225+
if (items) {
226+
return _.map(items, (item, index) => {
227+
return (
228+
<TabBarItem
229+
labelColor={labelColor}
230+
selectedLabelColor={selectedLabelColor}
231+
labelStyle={labelStyle}
232+
uppercase={uppercase}
233+
iconColor={iconColor}
234+
selectedIconColor={selectedIconColor}
235+
activeBackgroundColor={activeBackgroundColor}
236+
{...item}
237+
{...this.context}
238+
index={index}
239+
state={itemStates[index]}
240+
onLayout={this.onItemLayout}
241+
/>
242+
);
243+
});
244+
} else {
245+
// TODO: Remove once props.children is deprecated
246+
182247
if (this.tabBarItems) {
183248
return this.tabBarItems;
184249
}

src/incubator/TabController/TabBarItem.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export default class TabBarItem extends PureComponent {
110110
{
111111
nativeEvent: {state: this.props.state},
112112
},
113-
]);
113+
], {useNativeDriver: true});
114114

115115
onLayout = ({
116116
nativeEvent: {
@@ -191,7 +191,7 @@ export default class TabBarItem extends PureComponent {
191191

192192
return (
193193
<TouchableOpacity
194-
state={state}
194+
pressState={state}
195195
style={[styles.tabItem, this.getItemStyle()]}
196196
onLayout={this.onLayout}
197197
feedbackColor={activeBackgroundColor}

src/incubator/TouchableOpacity.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,36 @@ export default class TouchableOpacity extends Component {
1414
backgroundColor: PropTypes.string,
1515
activeOpacity: PropTypes.number,
1616
onPress: PropTypes.func,
17-
state: PropTypes.object,
17+
pressState: PropTypes.object,
1818
};
1919

2020
static defaultProps = {
2121
activeOpacity: 0.2,
2222
feedbackColor: 'transparent',
2323
onPress: _.noop,
24-
state: new Value(-1),
2524
};
2625

26+
state = {
27+
pressState: new Value(-1)
28+
}
29+
30+
get pressState() {
31+
return this.props.pressState || this.state.pressState;
32+
}
33+
2734
onStateChange = event([
2835
{
29-
nativeEvent: {state: this.props.state},
36+
nativeEvent: {state: this.pressState},
3037
},
31-
]);
38+
], {useNativeDriver: true});
3239

3340
_opacity = block([
34-
cond(eq(this.props.state, State.END), call([], () => this.props.onPress(this.props))),
35-
cond(eq(this.props.state, State.BEGAN), this.props.activeOpacity, 1),
41+
cond(eq(this.pressState, State.END), call([], () => this.props.onPress(this.props))),
42+
cond(eq(this.pressState, State.BEGAN), this.props.activeOpacity, 1),
3643
]);
3744

3845
_color = cond(
39-
eq(this.props.state, State.BEGAN),
46+
eq(this.pressState, State.BEGAN),
4047
processColor(this.props.feedbackColor || this.props.backgroundColor),
4148
processColor(this.props.backgroundColor),
4249
);

0 commit comments

Comments
 (0)