I need some help to use React Native - react navigation library.
It is Tab bar, but the Upload button acted as floating action button.
I have try :
const click = () => {
console.log('click');
return (
<View>
<Text>a</Text>
</View>
);
};
tabBarOnPress: (tab) => {
click();
},
// Main Page Navigator
export const Main = TabNavigator({
Home: {
screen: HomeNavigator,
},
Explore: {
screen: ExploreNavigator,
},
Upload: {
screen: UploadMain,
navigationOptions: ({ navigation }) => ({
tabBarLabel: 'Upload',
tabBarIcon: ({ tintColor }) => (
<View>
<Icon name="camera" size={26} color={tintColor} />
</View>
),
tabBarOnPress: (tab) => {
click();
},
}),
},
}, {
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
backBehavior: 'none',
swipeEnabled: false,
lazy: true,
animationEnabled: false,
showIcon: true,
tabBarOptions: {
activeTintColor: 'black',
},
});
The Upload button is need to act as floating action button, when it clicked, it already logging, but not rendering the component.
Any workaround to create the floating action button?
I've some tricks like this https://github.com/react-navigation/react-navigation/pull/1335
But, it is only click and dispatch navigation, not doing floating action button
Regards,
Charlie
you should write this code to your component!
-- you can use ‘react-native-tab-navigator' --
import TabNavigator from 'react-native-tab-navigator';
...
render(){
// console.log('TabRouter this.state:',this.state);
let tabs = [<Home {...this.props}/>,<Chat {...this.props}/>,<Web {...this.props}/>,<User {...this.props}/>];
let a = this.state.loginData.tabList.map((item,key)=>{
// console.log('item:',item);
return(
<TabNavigator.Item
key={key}
selected={this.state.selectedTab === item.type}
title={item.name}
renderIcon={() => <Image source={{uri:item.iconUnselectedUrl}} style={{width:24,height:24,}}/>}
renderSelectedIcon={() => <Image source={{uri:item.iconSelectedUrl}} style={{width:24,height:24}} />}
badgeText={this.state.tabBadge}
onPress={() => this.setState({
selectedTab: item.type,
tabBadge:0,
})}
>
{tabs[key]}
</TabNavigator.Item>
)
});
// console.log('a:',a);
return(
<TabNavigator
hidesTabTouch={true}
sceneStyle={{backgroundColor:'#fff'}}>
{a[0]}
{a[1]}
<TouchableOpacity
key={'add'}
style={{}}
renderIcon={() => <View style={{borderRadius:5,backgroundColor:'#46aee3',
width:width/5,height:49,justifyContent:'center',alignItems:'center'}}>
<Text style={{fontSize:49,padding:0,color:'#ffffff',backgroundColor:'rgba(0,0,0,0)'}}>+</Text></View>}
onPress={()=>this.props.navigation.navigate('SendBlog')}
/>
{a[2]}
{a[3]}
</TabNavigator>
)
}
...
-- update 2018/01/22 --
I think you should
let that;
class UploadMain extends Component {
constructor(props){
super(props);
that = this;
this.state = {
change:false,
};
}
changeState = () => {
this.setState({change:!change});
};
navigationOptions: ({ navigation }) => ({
tabBarLabel: 'Upload',
tabBarIcon: ({ tintColor }) => (
<View>
{that.state.change ? <Text>loading...</Text>:<Icon name="camera" size={26} color={tintColor} />}
</View>
),
tabBarOnPress: () => {
that.changeState;
},
}),
render(){
return (
<View>
....
</View>
)
}
}
If you are using react-navigation version 5.x, you should use tabBarButton to modify.
the code detail you can read
https://medium.com/#my.maithi/react-native-navigation-add-custom-button-in-the-middle-of-tabbar-6c390201a2bb
Hope can help you.
Related
i am using react-navigation v4 and i want to change the title and the approach i am using is slow while rendering(title that is set in the stack navigator is rendered first and then new one is rendered),is there better way i can render only the new one
export default NewsList = ({ results, navigation}) => {
return <View >
<FlatList
data={results}
keyExtractor={result => result.id}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => navigation.navigate( 'news',title: item.title)}>
<NewsCard result={item} />
</TouchableOpacity>)
}}
/>
</View>
};
////////////////////////////////////////////////////////////////////
export default NewsScreen = ({ navigation}) => {
NewsScreen.navigationOptions = {
title: navigation.getParam("title");,
};
}
////////////////////////////////////////////////////////////////////
const NewsStack = createStackNavigator({
NewsList :NewsList,
News :NewsScreen
},{
initialRouteName:'NewsList',
defaultNavigationOptions: {
headerStyle: {
backgroundColor: '#4BB5C3',
},
},
navigationOptions: {
tabBarLabel: 'NewsList',
},
});
export default createAppContainer(NewsStack);
Ciao, try to set title before navigate into NewsList like this:
export default NewsList = ({ results, navigation}) => {
return <View >
<FlatList
data={results}
keyExtractor={result => result.id}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => {
navigation.setParams({ otherParam: item.title });
navigation.navigate('news');
}
}>
<NewsCard result={item} />
</TouchableOpacity>)
}}
/>
</View>
};
And I think you could remove navigationOptions in NewsScreen.
const AppStackLog = createDrawerNavigator(
{
Login: {
screen: LogintStack,
navigationOptions: (navOpt) => ({
drawerLabel: ({focused}) =>(
<TouchableOpacity style={[styles.button]} onPress={() => this.navigation.navigate('App')}>
<Text><Icon
size={17}
name="log-in"
family="Galio"
color={focused ? 'white' : materialTheme.COLORS.MUTED} />
<Text size={18}> Logout</Text></Text>
</TouchableOpacity>
),
}),
},
},
Menu
);
export default createSwitchNavigator(
{
App: AppStack,
Home: HomeStack,
Auth:AppStackLog,
},
{
initialRouteName: 'App',
}
);
this is not going to point to some particular component, it's going to point to whatever this was equal to when this code was defined. Instead, the navOpt parameter has what you need on it:
<TouchableOpacity style={[styles.button]} onPress={() => navOpt.navigation.navigate('App')}>
I wonder there's a way to using headerRight onPress to doing something like calling Alert:
I have a function inside MyPet.js with the code :
_alert=()=>{
alert('saving')
}
and in router.js I have a list of all screen I've used to navigating with a piece of code like :
export const MyPatientStack = StackNavigator({
MyPatient: {
screen: MyPatient,
navigationOptions: {
tabBarLabel: 'My Patient',
tabBarIcon: ({ tintColor, focused }) => <FontAwesome name="wheelchair" size={25} color={tintColor} />,
headerTitle: 'My Patient',
headerStyle: {
backgroundColor: '#8B0000',
},
headerLeft: <HeaderBackButton tintColor="#FFF" onPress={() => navigation.goBack()} />,
// and here I want to call the function of _alert() from MyPet.js
headerRight: <FontAwesome name='search' size={20} color="#FFF" onPress={_alert()}/>,
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
textAlign:'center',
flex:1
},
}
}
})
Have tried it and the code doesn't find variable _alert
How can I do that?
any feedback are welcome
Since your Navigation component has no reference to what is in your Pet.js component, you may try the following way
Use navigationOptions in your Pet.js component as
// Inside the class
// Since navigationOptions have no access to this parameter of the class, therefore you need to pass them as params
static navigationOptions = ({navigation}) => {
const {params}} = navigation.state;
return {
headerRight: <FontAwesome name='search' size={20} color="#FFF" onPress={() => params.showAlert()}/> />
};
};
componentDidMount() {
this.props.navigation.setParams({
showAlert: this.alertShower
});
}
alertShower = () => Alert.alert('Success', 'Hello')
When I am on settings screen, I see that the Review Icon (favorite) is missing. It shows when I am back on Review screen. Why is that happening. See the screenshot I took. Pasting relevant code snippet from my project for reference.
const MainNavigator = TabNavigator({
map: { screen: MapScreen },
deck: { screen: DeckScreen },
review: {
screen: StackNavigator({
review: { screen: ReviewScreen },
settings: { screen: SettingsScreen }
})
}
}, {
tabBarPosition: 'bottom',
tabBarOptions: {
labelStyle: { fontSize: 12 }
}
});
class ReviewScreen extends Component {
static navigationOptions = props => {
const {navigation} = props;
const {navigate} = navigation;
return {
tabBarIcon: ({ tintColor }) => {
return <Icon name="favorite" size={30} color={tintColor} />
},
headerTitle: 'Review Jobs',
headerRight: (
<Button
title="Settings"
onPress={() => navigate('settings')}
backgroundColor="rgba(0,0,0,0)"
color="rgba(0, 122, 255, 1)"
/>
)
}
}
Leads here is appreciated.
There is an issue with your code, since you're setting every icon's tintColor in the static navigationOptions as
tabBarIcon: ({tintColor}) => {
return <Icon name="favorite" size={30} color={tintColor}/>
}
and there is none for the Settings Screen, which also expects an Icon as it is inside the TabNavigator, therefore null is being rendered there.
Therefore you need to set the navigationOptions in the Settings Screen as
static navigationOptions = props => {
const {navigation} = props;
const {navigate} = navigation;
return {
tabBarIcon: ({tintColor}) => {
return <Icon name="favorite" size={30} color={tintColor}/>
}
}
}
or you may add the default icons in your App.js navigation file as
screen: TabNavigator({
map: { screen: MapScreen,
navigationOptions: {
tabBarIcon: ({ tintColor }) => (
<Icon name="favorite" size={30} color={tintColor}/>
)
}
},
// ....so on
Hope it helps!
I am very new to react-native. I am trying to create a drawer using react-navigation. I could use DrawerNavigator but could not show the header/navbar on all the screens. That is why i create a NavScreen component with profile icon, title and back icon. However they are not aligned properly. I need profile icon to be shown on the left side, title on the center and back button on the right side. How can i do this?
Here is my code
const styles = StyleSheet.create({
container: {
marginTop: Platform.OS === 'ios' ? 20 : 10,
},
});
const NavScreen = ({ navigation, banner }) => (
<ScrollView style={styles.container}>
<Text>{banner}</Text>
<Icon
name="ios-contact-outline"
size={30}
color="#000"
onPress={() => navigation.navigate('DrawerOpen')}
/>
<Icon
name="ios-arrow-round-back-outline"
size={30}
color="#000"
onPress={() => navigation.goBack(null)}
/>
</ScrollView>
);
export default NavScreen;
class App extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: `${navigation.state.routeName}`,
drawerTitle: `${navigation.state.routeName}`,
drawerLabel: 'Home',
drawerIcon: ({ whiteColor }) => (
<MaterialIcons name="drafts" size={14} style={{ color: whiteColor }} />
),
})
render() {
const { navigation } = this.props;
return (
<ScrollView>
<NavScreen navigation={navigation} banner={'Main'} />
<Text>Main Screen</Text>
</ScrollView>
);
}
}
export default App;
I need similar to the below image
First, try to build a StackNavigation, at headerRight, and headerLeft you define your custom buttons (the above), now you can very easy customize the align/padding whatever you need with your icons/buttons.
const stackNavigatorConfiguration = {
// set first Screen
initialRouteName: 'Home',
mode: Platform.OS === 'ios' ? 'card' : 'card',
navigationOptions: ({navigation}) => ({
headerRight: <DrawerButton navigation={navigation} />,
headerLeft: <YourProfileButton navigation={navigation} />,
headerBackTitle: null
})
}
const YourProfileButton = ({ navigation }) => (
<TouchableOpacity>
<Ionicons
style={styles.profileButton}
name='ios-menu-outline'
size={32}
onPress={() => navigation.goBack(null)}
/>
</TouchableOpacity>
)
const DrawerButton = ({ navigation }) => (
<TouchableOpacity>
<Ionicons
style={styles.drawerIcon}
name='ios-menu-outline'
size={32}
onPress={() => navigation.navigate('DrawerOpen')}
/>
</TouchableOpacity>
)