Skip to content

Commit 7684195

Browse files
authored
v4.1.0 #62
2 parents 53f5c30 + ec1ed7c commit 7684195

File tree

5 files changed

+214
-79
lines changed

5 files changed

+214
-79
lines changed

README.md

+32-46
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,39 @@ Start using the component
4242

4343
```jsx
4444
import MaterialTabs from 'react-native-material-tabs';
45+
```
46+
47+
## Usage
48+
49+
![Demo](https://user-images.githubusercontent.com/5962998/59991843-f2e43600-9616-11e9-913b-b8fb8a566d68.gif)
50+
51+
```jsx
52+
import React, { useState } from 'react';
53+
import { StyleSheet, SafeAreaView } from 'react-native';
54+
import MaterialTabs from 'react-native-material-tabs';
4555

46-
<MaterialTabs
47-
items={['One', 'Two', 'Three']}
48-
selectedIndex={this.state.selectedTab}
49-
onChange={index => this.setState({ selectedTab: index })}
50-
/>;
56+
const Example = () => {
57+
const [selectedTab, setSelectedTab] = useState(0);
58+
59+
return (
60+
<SafeAreaView style={styles.container}>
61+
<MaterialTabs
62+
items={['One', 'Two', 'Three', 'Four', 'Five']}
63+
selectedIndex={selectedTab}
64+
onChange={setSelectedTab}
65+
barColor="#1fbcd2"
66+
indicatorColor="#fffe94"
67+
activeTextColor="white"
68+
/>
69+
</SafeAreaView>
70+
);
71+
};
72+
73+
const styles = StyleSheet.create({
74+
container: {
75+
flex: 1,
76+
},
77+
});
5178
```
5279

5380
## Available Props
@@ -67,44 +94,3 @@ import MaterialTabs from 'react-native-material-tabs';
6794
| allowFontScaling | true | boolean | Specifies whether fonts should scale to respect Text Size accessibility settings |
6895
| uppercase | true | boolean | Specifies whether to uppercase the tab labels |
6996
| keyboardShouldPersistTaps | never | string | Specifies how the [ScrollView](https://facebook.github.io/react-native/docs/scrollview#keyboardshouldpersisttaps) should respond to taps while keyboard is open |
70-
71-
## Example
72-
73-
![Demo](https://user-images.githubusercontent.com/5962998/59991843-f2e43600-9616-11e9-913b-b8fb8a566d68.gif)
74-
75-
```jsx
76-
import React from 'react';
77-
import { StyleSheet, Text, SafeAreaView } from 'react-native';
78-
import MaterialTabs from 'react-native-material-tabs';
79-
80-
export default class Example extends React.Component {
81-
state = {
82-
selectedTab: 0,
83-
};
84-
85-
setTab = selectedTab => {
86-
this.setState({ selectedTab });
87-
};
88-
89-
render() {
90-
return (
91-
<SafeAreaView style={styles.container}>
92-
<MaterialTabs
93-
items={['One', 'Two', 'Three', 'Four', 'Five']}
94-
selectedIndex={this.state.selectedTab}
95-
onChange={this.setTab}
96-
barColor="#1fbcd2"
97-
indicatorColor="#fffe94"
98-
activeTextColor="white"
99-
/>
100-
</SafeAreaView>
101-
);
102-
}
103-
}
104-
105-
const styles = StyleSheet.create({
106-
container: {
107-
flex: 1,
108-
},
109-
});
110-
```

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-material-tabs",
3-
"version": "4.0.0",
3+
"version": "4.1.0",
44
"description": "Material Design implementation of Tabs",
55
"keywords": [
66
"react",

src/__tests__/__snapshots__/main.test.js.snap

+158
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,164 @@ exports[`Main should display tab labels not uppercased 1`] = `
480480
</View>
481481
`;
482482

483+
exports[`Main should render scrollable without errors 1`] = `
484+
<View
485+
barColor="#13897b"
486+
barHeight={48}
487+
onLayout={[Function]}
488+
style={
489+
Array [
490+
Object {
491+
"backgroundColor": "#13897b",
492+
"height": 48,
493+
},
494+
]
495+
}
496+
>
497+
<RCTScrollView
498+
horizontal={true}
499+
keyboardShouldPersistTaps="never"
500+
scrollEnabled={true}
501+
showsHorizontalScrollIndicator={false}
502+
>
503+
<View>
504+
<View
505+
barHeight={48}
506+
style={
507+
Array [
508+
Object {
509+
"flexDirection": "row",
510+
"height": 46,
511+
},
512+
]
513+
}
514+
>
515+
<View
516+
accessible={true}
517+
isTVSelectable={true}
518+
onResponderGrant={[Function]}
519+
onResponderMove={[Function]}
520+
onResponderRelease={[Function]}
521+
onResponderTerminate={[Function]}
522+
onResponderTerminationRequest={[Function]}
523+
onStartShouldSetResponder={[Function]}
524+
style={
525+
Object {
526+
"opacity": 1,
527+
"width": 0,
528+
}
529+
}
530+
>
531+
<View
532+
style={
533+
Array [
534+
Object {
535+
"alignItems": "center",
536+
"height": 48,
537+
"justifyContent": "center",
538+
"paddingLeft": 12,
539+
"paddingRight": 12,
540+
},
541+
]
542+
}
543+
tabHeight={48}
544+
>
545+
<Text
546+
allowFontScaling={true}
547+
color="#fff"
548+
style={
549+
Array [
550+
Object {
551+
"color": "#fff",
552+
"fontFamily": "System",
553+
"fontSize": 14,
554+
"fontWeight": "500",
555+
"minWidth": "100%",
556+
"textAlign": "center",
557+
},
558+
Object {},
559+
]
560+
}
561+
>
562+
TAB1
563+
</Text>
564+
</View>
565+
</View>
566+
<View
567+
accessible={true}
568+
isTVSelectable={true}
569+
onResponderGrant={[Function]}
570+
onResponderMove={[Function]}
571+
onResponderRelease={[Function]}
572+
onResponderTerminate={[Function]}
573+
onResponderTerminationRequest={[Function]}
574+
onStartShouldSetResponder={[Function]}
575+
style={
576+
Object {
577+
"opacity": 1,
578+
"width": 0,
579+
}
580+
}
581+
>
582+
<View
583+
style={
584+
Array [
585+
Object {
586+
"alignItems": "center",
587+
"height": 48,
588+
"justifyContent": "center",
589+
"paddingLeft": 12,
590+
"paddingRight": 12,
591+
},
592+
]
593+
}
594+
tabHeight={48}
595+
>
596+
<Text
597+
allowFontScaling={true}
598+
color="rgba(255, 255, 255, 0.7)"
599+
style={
600+
Array [
601+
Object {
602+
"color": "rgba(255, 255, 255, 0.7)",
603+
"fontFamily": "System",
604+
"fontSize": 14,
605+
"fontWeight": "500",
606+
"minWidth": "100%",
607+
"textAlign": "center",
608+
},
609+
Object {},
610+
]
611+
}
612+
>
613+
TAB2
614+
</Text>
615+
</View>
616+
</View>
617+
</View>
618+
<View
619+
color="#fff"
620+
style={
621+
Object {
622+
"backgroundColor": "#fff",
623+
"bottom": 0,
624+
"height": 2,
625+
"position": "absolute",
626+
"transform": Array [
627+
Object {
628+
"translateX": 0,
629+
},
630+
],
631+
"width": 0,
632+
}
633+
}
634+
tabWidth={0}
635+
/>
636+
</View>
637+
</RCTScrollView>
638+
</View>
639+
`;
640+
483641
exports[`Main should render without errors 1`] = `
484642
<View
485643
barColor="#13897b"

src/__tests__/main.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ describe('Main', () => {
3333
expect(tree).toMatchSnapshot();
3434
});
3535

36+
it('should render scrollable without errors', () => {
37+
const tree = create(
38+
<MaterialTabs selectedIndex={0} items={['Tab1', 'Tab2']} scrollable />
39+
).toJSON();
40+
expect(tree).toMatchSnapshot();
41+
});
42+
3643
it('should render with correct tabs', () => {
3744
const wrapper = shallow(component);
3845
const tabs = wrapper.find('Tab');

src/components/MaterialTabs.tsx

+16-32
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ScrollViewProps,
77
StyleProp,
88
TextStyle,
9+
I18nManager,
910
} from 'react-native';
1011

1112
import Tab from './Tab';
@@ -69,43 +70,24 @@ const MaterialTabs: React.FC<Props> = ({
6970
const getAnimateValues = () => {
7071
const scrollValue = !scrollable ? tabWidth : barWidth * 0.4;
7172

73+
const indicator = I18nManager.isRTL
74+
? -selectedIndex * scrollValue
75+
: selectedIndex * scrollValue;
76+
7277
// All props for fixed tabs are the same
7378
if (!scrollable) {
7479
return {
75-
indicatorPosition:
76-
selectedIndex === 0 ? 0 : selectedIndex * scrollValue,
80+
indicatorPosition: indicator,
7781
scrollPosition: 0,
7882
};
7983
}
8084

81-
switch (selectedIndex) {
82-
case 0: // First tab
83-
return {
84-
indicatorPosition: 0,
85-
scrollPosition: 0,
86-
};
87-
case 1: // Second tab
88-
return {
89-
indicatorPosition: barWidth * 0.5 - scrollValue / 4,
90-
scrollPosition: scrollValue * 0.25,
91-
};
92-
case items.length - 1: // Last tab
93-
return {
94-
indicatorPosition:
95-
scrollValue * (selectedIndex - 1) +
96-
(barWidth * 0.5 - scrollValue / 4),
97-
scrollPosition: scrollValue * (selectedIndex - 2) + scrollValue * 0.5,
98-
};
99-
default:
100-
// Any tabs between second and last
101-
return {
102-
indicatorPosition:
103-
scrollValue * (selectedIndex - 1) +
104-
(barWidth * 0.5 - scrollValue / 4),
105-
scrollPosition:
106-
scrollValue * 0.25 + scrollValue * (selectedIndex - 1),
107-
};
108-
}
85+
return {
86+
indicatorPosition: indicator,
87+
scrollPosition: I18nManager.isRTL
88+
? scrollValue * 0.25 + scrollValue * (items.length - selectedIndex - 2)
89+
: scrollValue * 0.25 + scrollValue * (selectedIndex - 1),
90+
};
10991
};
11092

11193
const getTabWidth = (width: number) => {
@@ -117,16 +99,18 @@ const MaterialTabs: React.FC<Props> = ({
11799
};
118100

119101
const selectTab = () => {
102+
const values = getAnimateValues();
103+
120104
Animated.spring(indicatorPosition, {
121-
toValue: getAnimateValues().indicatorPosition,
105+
toValue: values.indicatorPosition,
122106
tension: 300,
123107
friction: 20,
124108
useNativeDriver: true,
125109
}).start();
126110

127111
if (scrollView.current) {
128112
scrollView.current.scrollTo({
129-
x: getAnimateValues().scrollPosition,
113+
x: values.scrollPosition,
130114
});
131115
}
132116
};

0 commit comments

Comments
 (0)