Skip to content

Commit

Permalink
refactor: tab-bar support custom icon close #158
Browse files Browse the repository at this point in the history
  • Loading branch information
BANG88 committed Dec 14, 2018
1 parent f7130cf commit 714e5b2
Show file tree
Hide file tree
Showing 34 changed files with 126 additions and 169 deletions.
2 changes: 1 addition & 1 deletion components/icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default class Icon extends React.Component<IconProps, any> {
static defaultProps = {
size: 'md',
};

static displayName = 'Icon';
render() {
const { size, color, name, ...rest } = this.props;
const sizeMap: { [key: string]: number } = {
Expand Down
18 changes: 9 additions & 9 deletions components/tab-bar/PropsType.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import React from 'react';
import { ImageRequireSource, ImageURISource } from 'react-native';

export interface TabBarProps {
barTintColor?: string;
tintColor?: string;
unselectedTintColor?: string;

/** default: false */
animated?: boolean;
/** default: false */
swipeable?: boolean;
/** rn android only**/
styles?: any;
}
export type TabIcon = React.ReactElement<any> | { uri: string };
export interface TabBarItemProps {
export type TabBarIcon =
| ImageURISource
| ImageURISource[]
| ImageRequireSource
| React.ReactNode;
export interface TabBarItemProps {
badge?: string | number;
onPress?: () => void;
selected?: boolean;
icon?: TabIcon;
selectedIcon?: TabIcon;
icon?: TabBarIcon;
selectedIcon?: TabBarIcon;
title: string;
}
58 changes: 28 additions & 30 deletions components/tab-bar/TabBarItem.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
import React from 'react';
import {
Image,
ImageRequireSource,
ImageStyle,
ImageURISource,
StyleProp,
Text,
TouchableWithoutFeedback,
View,
} from 'react-native';
import React, { isValidElement } from 'react';
import { Image, ImageStyle, StyleProp, Text, TouchableWithoutFeedback, View } from 'react-native';
import Icon, { IconProps } from '../icon';
import { TabBarIcon } from './PropsType';
import TabBarItemStyles from './style';

export interface TabBarItemProps {
badge?: string | number;
onPress?: () => void;
selected?: boolean;
icon?: ImageURISource | ImageURISource[] | ImageRequireSource;
selectedIcon?: ImageURISource | ImageURISource[] | ImageRequireSource;
icon?: TabBarIcon;
selectedIcon?: TabBarIcon;
title: string;
tintColor?: string;
unselectedTintColor?: string;
/*react-native android only*/
iconStyle?: StyleProp<ImageStyle>;
renderAsOriginal?: boolean;
/* react-native only */
styles?: any;
styles?: ReturnType<typeof TabBarItemStyles>;
}

const wrapperIcon = (IconElement: any, props: any) => {
return <IconElement {...props} />;
};
export default class TabBarItem extends React.Component<TabBarItemProps, any> {
static defaultProps = {
onPress() {},
Expand All @@ -40,9 +34,9 @@ export default class TabBarItem extends React.Component<TabBarItemProps, any> {
selectedIcon,
onPress,
badge,
styles,
iconStyle,
} = this.props;
const styles = this.props.styles!;
const itemSelectedStyle = selected ? styles.barItemSelected : null;
const badgeDom = badge ? (
<View style={[styles.badge]}>
Expand All @@ -53,26 +47,30 @@ export default class TabBarItem extends React.Component<TabBarItemProps, any> {
const source =
selected && selectedIcon !== undefined
? selectedIcon
: icon !== undefined ? icon : null;
: icon !== undefined
? icon
: null;
const color = selected ? tintColor : unselectedTintColor;
const isIcon =
source &&
(source as any).type &&
(source as any).type.displayName === 'Icon';
return (
<TouchableWithoutFeedback onPress={onPress}>
<View style={[styles.barItem, itemSelectedStyle]}>
<View>
{source === null ? null : (
// tslint:disable-next-line:jsx-no-multiline-js
{source === null ? null : isValidElement(source) ? (
isIcon ? (
<Icon color={color} {...source.props as IconProps} />
) : (
source
)
) : (
<Image source={source} style={[styles.barIcon, iconStyle]} />
)}
{badgeDom}
</View>
<Text
// tslint:disable-next-line:jsx-no-multiline-js
style={[
styles.barItemTitle,
{ color: selected ? tintColor : unselectedTintColor },
]}
>
{title}
</Text>
<Text style={[styles.barItemTitle, { color }]}>{title}</Text>
</View>
</TouchableWithoutFeedback>
);
Expand Down
Binary file removed components/tab-bar/demo/alipay.png
Binary file not shown.
Binary file removed components/tab-bar/demo/alipay@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/alipay@3x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/alipay_sel.png
Binary file not shown.
Binary file removed components/tab-bar/demo/alipay_sel@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/alipay_sel@3x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/alipay_web.png
Binary file not shown.
Binary file removed components/tab-bar/demo/alipay_web_sel.png
Binary file not shown.
17 changes: 7 additions & 10 deletions components/tab-bar/demo/basic.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { View, Text } from 'react-native';
import { TabBar, SearchBar } from '../../';
import { Text, View } from 'react-native';
import { SearchBar, TabBar } from '../../';
import Icon from '../../icon';

export default class BasicTabBarExample extends React.Component<any, any> {
constructor(props: any) {
Expand Down Expand Up @@ -34,16 +35,14 @@ export default class BasicTabBarExample extends React.Component<any, any> {
>
<TabBar.Item
title="Life"
icon={require('./alipay.png')}
selectedIcon={require('./alipay_sel.png')}
icon={<Icon name="home" />}
selected={this.state.selectedTab === 'blueTab'}
onPress={() => this.onChangeTab('blueTab')}
>
{this.renderContent('Life Tab')}
</TabBar.Item>
<TabBar.Item
icon={require('./koubei.png')}
selectedIcon={require('./koubei_sel.png')}
icon={<Icon name='ordered-list' />}
title="Koubei"
badge={2}
selected={this.state.selectedTab === 'redTab'}
Expand All @@ -52,17 +51,15 @@ export default class BasicTabBarExample extends React.Component<any, any> {
{this.renderContent('Koubei Tab')}
</TabBar.Item>
<TabBar.Item
icon={require('./friend.png')}
selectedIcon={require('./friend_sel.png')}
icon={<Icon name="like" />}
title="Friend"
selected={this.state.selectedTab === 'greenTab'}
onPress={() => this.onChangeTab('greenTab')}
>
{this.renderContent('Friend Tab')}
</TabBar.Item>
<TabBar.Item
icon={require('./busi.png')}
selectedIcon={require('./busi_sel.png')}
icon={<Icon name="user" />}
title="My"
selected={this.state.selectedTab === 'yellowTab'}
onPress={() => this.onChangeTab('yellowTab')}
Expand Down
Binary file removed components/tab-bar/demo/busi.png
Binary file not shown.
Binary file removed components/tab-bar/demo/busi@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/busi@3x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/busi_sel.png
Binary file not shown.
Binary file removed components/tab-bar/demo/busi_sel@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/busi_sel@3x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/friend.png
Binary file not shown.
Binary file removed components/tab-bar/demo/friend@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/friend@3x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/friend_sel.png
Binary file not shown.
Binary file removed components/tab-bar/demo/friend_sel@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/friend_sel@3x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/koubei.png
Binary file not shown.
Binary file removed components/tab-bar/demo/koubei@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/koubei@3x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/koubei_sel.png
Binary file not shown.
Binary file removed components/tab-bar/demo/koubei_sel@2x.png
Binary file not shown.
Binary file removed components/tab-bar/demo/koubei_sel@3x.png
Diff not rendered.
83 changes: 79 additions & 4 deletions components/tab-bar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,80 @@
import { Platform } from 'react-native';
import TabBarAndroid from './tabbar.android';
import TabBarIOS from './tabbar.ios';
import React from 'react';
import { View } from 'react-native';
import { WithTheme } from '../style';
import { TabBarProps } from './PropsType';
import TabBarStyles, { TabBarStyle } from './style/index';
import TabBarItem from './TabBarItem';

export default (Platform.OS === 'ios' ? TabBarIOS : TabBarAndroid);
export interface TabBarNativeProps extends TabBarProps {
styles?: TabBarStyle;
}

class TabBar extends React.Component<TabBarNativeProps, any> {
static defaultProps = {
barTintColor: 'white',
tintColor: '#108ee9',
unselectedTintColor: '#888',
};

static Item = TabBarItem;

getPanes(styles: ReturnType<typeof TabBarStyles>, content: boolean) {
const { tintColor, unselectedTintColor, children } = this.props;
// ios 规则: selected 为多个则只选中最后一个, selected 为 0 个则选中第一个;
let selectedIndex = 0;
[].concat(children as any).forEach((child: any, idx: number) => {
if (child.props.selected) {
selectedIndex = idx;
}
});
const newChildren: any[] = [];
React.Children.map(children, (child: any, idx) => {
if (content) {
newChildren.push(
<View
key={idx}
style={[
styles.contentItem,
idx === selectedIndex ? styles.contentItemSelected : undefined,
]}
>
{child.props.children}
</View>,
);
} else {
newChildren.push(
React.cloneElement(child, {
key: idx,
tintColor,
unselectedTintColor,
styles,
}),
);
}
});

return newChildren;
}

render() {
return (
<WithTheme styles={this.props.styles} themeStyles={TabBarStyles}>
{styles => (
<View style={styles.tabbar}>
<View style={styles.content}>{this.getPanes(styles, true)}</View>
<View
style={[
styles.tabs,
{ backgroundColor: this.props.barTintColor },
]}
>
{this.getPanes(styles, false)}
</View>
</View>
)}
</WithTheme>
);
}
}

export default TabBar;
4 changes: 2 additions & 2 deletions components/tab-bar/style/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { StyleSheet, TextStyle, ViewStyle } from 'react-native';
import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from 'react-native';
import { Theme } from '../../style';

export interface TabBarStyle {
tabbar: ViewStyle;
content: ViewStyle;
tabs: ViewStyle;
barItem: ViewStyle;
barIcon: ViewStyle;
barIcon: ImageStyle;
barItemSelected: ViewStyle;
barItemTitle: TextStyle;
contentItem: ViewStyle;
Expand Down
83 changes: 0 additions & 83 deletions components/tab-bar/tabbar.android.tsx

This file was deleted.

Loading

0 comments on commit 714e5b2

Please sign in to comment.