i'm creating a screen using react-native-paper. When i use a Appbar as header with three dots menu, the options appear at the wrong side of the screen. It should appear at the right side, not the left one.
My code:
import React, { useEffect,useState } from 'react'
import {
SafeAreaView,
StyleSheet,
Platform
} from 'react-native'
import {connect} from 'react-redux'
...
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
import {Appbar,Menu} from 'react-native-paper'
import MComponent from './subpages/component'
const Tab = createMaterialTopTabNavigator();
const TAG = 'TAG'
const MPage = ({ navigation,handleLoadData,isLoading }) => {
useEffect(() => {
handleLoadData()
}, [])
const [openMenu,setOpenMenu] = useState(false)
return (
<SafeAreaView style={styles.container}>
<Menu
style={styles.menu}
visible={openMenu}
onDismiss={()=>{
setOpenMenu(false)
}}
anchor={
<Appbar.Header
statusBarHeight={0}
>
<Appbar.BackAction
onPress={()=>{
navigation.goBack()
}}
/>
<Appbar.Content
title="App Screen"
/>
<Appbar.Action icon="dots-vertical" onPress={()=>{
setOpenMenu(true)}}
/>
</Appbar.Header>
}
>
<Menu.Item onPress={() => {
setOpenMenu(false)
handleLoadServiceOrders()
}} title="Option 1" />
<Menu.Item onPress={() => {}} title="Option 2" />
</Menu>
<Loading
loading={isLoading}
/>
<Tab.Navigator>
<Tab.Screen name={OPTIONS.PAGE_A} component={MComponent} />
<Tab.Screen name={OPTIONS.PAGE_B} component={MComponent } />
</Tab.Navigator>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
container: {
marginTop: Platform.OS === 'android' ? 30 : 0,
justifyContent: 'center',
flex:1
}
})
...
Images showing what happened:
https://imgur.com/a/xq3Gcac
I'm using react-native with react-native-paper lib to create the Appbar. The Menu component also belongs to react-native-paper.
You have to pass the correct anchor prop. It accepts a React.ReactNode or an Object like this type { x: number; y: number }. I posted an example for you with the anchor anchor={{ x: windowWidth, y: 100 }}. This will work. Also you don't have to combine Appbar with Menu. It will work if you seperate them.
<Appbar.Header>
<Appbar.BackAction onPress={_goBack} />
<Appbar.Content title="Title" subtitle="Subtitle" />
<Appbar.Action icon="magnify" onPress={openMenu} />
<Appbar.Action icon="dots-vertical" onPress={openMenu} />
</Appbar.Header>
<Provider>
<View>
<Menu
visible={visible}
onDismiss={closeMenu}
anchor={{ x: windowWidth, y: 100 }}>
<Menu.Item onPress={() => { }} title="Item 1" />
<Menu.Item onPress={() => { }} title="Item 2" />
<Divider />
<Menu.Item onPress={() => { }} title="Item 3" />
</Menu>
</View>
</Provider>
The menu position is set relative to its anchor. In your original example, the entire Appbar is the anchor, so the menu appears to the left side of that.
Instead, you can make the anchor just be the Appbar.Action, which will make the menu appear next to the vertical dots.
Here is similar example using a Menu:
<Card.Title
title={item.name}
subtitle={item.description}
style={{overflow: 'visible'}}
left={(props) => <Avatar.Icon {...props} icon={require('../assets/icon.png')} />}
right={(props) =>
<Menu
visible={menuvisible}
onDismiss={handleMenuDismiss}
anchor={ <IconButton {...props} icon="dots-vertical" onPress={handleMenuShow}></IconButton>}
>
<Menu.Item onPress={() => {alert('item1')}} title="Item 1" />
<Menu.Item onPress={() => {}} title="Item 2" />
<Menu.Item onPress={() => {}} title="Item 3" />
</Menu>
}
/>
Related
Modal only displays button but not FlatList item.
I am trying to build a custom app picker for my react-native-app which renders a list of items on a modal.
AppPicker.js
const AppPicker = ({ icon, items, placeholder }) => {
const [modalVisible, setModalVisible] = React.useState(false)
return (
<>
<TouchableWithoutFeedback onPress={() => setModalVisible(true)} >
<View style={styles.container}>
{icon && <MaterialCommunityIcons name={icon} size={20} style={styles.icon} />}
<AppText style={styles.text}> {placeholder} </AppText>
<MaterialCommunityIcons name="chevron-down" size={20} />
</View>
</TouchableWithoutFeedback>
<Modal visible={modalVisible} animationType="slide" >
<Button title="Close" onPress={() => setModalVisible(false)} />
<FlatList
data={items}
keyExtractor={item => item.value.toString()}
renderItem={({ item }) =>
<PickerItem
lable={item.label}
onPress={() => console.log(item)}
/>}
/>
</Modal>
</>
)
}
the <PickerItem/> that should be rendered by the flatlist is a component that just displays the items from the list.
PickerItem.js
const PickerItem = ({ label, onPress }) => {
return (
<TouchableOpacity onPress={onPress}>
<AppText> {label} </AppText>
</TouchableOpacity>
)
}
export default PickerItem;
when I randomly tap on the modal screen however the onPress() on the FlatList triggers the console.log(item) and the items are displayed on the console. Any help on this will be appreciated.
** App.js **
const categories = [
{ label: "furniture", value: 1 },
{ label: "clothing", value: 2 },
{ label: "phone", value: 3 },
]
export default function App() {
return (
<Screen style={styles.container}>
<AppPicker items={categories} icon="apps" placeholder="category" />
<AppTextInput icon="email" placeholder="email" />
</Screen>
);
}
NOTE: I am using expo to run the application.
I'm trying to fetch the date and format it using moment , the solution i found is to store the date in a variable , and i've been having a problem with that followed this awnser since i hade the same problem . although i managed to get rid of the unexpected token error but i got my self in another one . MY FLAT LIST IS NOT SHOWING ANYMORE.
here is my code :
import React, { Component } from "react";
import {View,StyleSheet,FlatList,ListView} from "react-native";
import {Container, Header, Left, Body, Right, Title, Subtitle,Icon ,Content, Footer, FooterTab, Button, Text,Badge , List , ListItem} from 'native-base'
import Icon0 from 'react-native-vector-icons/MaterialCommunityIcons'
import Icon1 from 'react-native-vector-icons/FontAwesome'
import CountDown from 'react-native-countdown-component';
import moment from 'moment';
class Consulter extends Component{
state ={
data:[]
}
fetchData= async()=>{
const response = await fetch('http://192.168.1.4:3000/rendezvous/1');
const rendezvous =await response.json();
this.setState({data:rendezvous});
}
componentDidMount() {
this.fetchData();
}
render() {
const today = this.state.currentDate;
const day = moment(today).format("dddd");
const date = moment(today).format("MMMM D, YYYY");
return (
<Container>
<Content >
<View style ={{ flex:1}}>
<FlatList
data={this.state.data}
keyExtractor={(item,index) => index.toString()}
renderItem={({item}) =>
{let dates=item.date;
<View style={{backgroundColor:'#e6e6e6',padding:10,margin:10}}>
<ListItem icon>
<Left>
<Button style={{ backgroundColor: "white" }}>
<Icon0 active name="doctor" />
</Button>
</Left>
<Body>
<Text>Nom du Docteur : Dr. {item.nom}</Text>
</Body>
</ListItem>
<ListItem icon>
<Left>
<Button style={{ backgroundColor: "white" }}>
<Icon1 active name="calendar" />
</Button>
</Left>
<Body>
<Text>Date du rendez-vous :</Text>
<Text> dates </Text>
</Body>
</ListItem>
<ListItem icon>
<Left>
<Button style={{ backgroundColor: "white" }}>
<Icon1 active name="calendar"/>
</Button>
</Left>
<Body>
<CountDown
until= {item.date}
timetoShow={('H', 'M', 'S')}
onFinish={() => alert('finished')}
onPress={() => alert('hello')}
size={10}
/>
</Body>
</ListItem>
</View>
}}
/>
</View>
</Content>
</Container>
);
}
}
export default Consulter;
const styles =StyleSheet.create({
container : {
flex: 1,
}
})
Ps : there is no compilation errors.
you need to use a return statement, like that:
<FlatList
data={this.state.data}
keyExtractor={(item,index) => index.toString()}
renderItem={({item}) =>
{let dates=item.date;
return(
<View style={{backgroundColor:'#e6e6e6',padding:10,margin:10}}>
<ListItem icon>
...
);
renderItem expects you to return some jsx ... and you didn't
Try this:
<FlatList
data={this.state.data}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item: { date } }) => (<View>// the rest of your jsx</View>)}
/>
I wants to change button when I clicked on button. I have list of users. I want when I clicked on follow button the button change to following button. Right now when I clicked on button my all button changes to following button. I want to change current button. Here is my code.
import React, { Component } from "react";
import { TouchableOpacity,StatusBar,View,Modal,
TouchableHighlight,StyleSheet,Image } from "react-native";
import { connect } from "react-redux";
import { DrawerNavigator, NavigationActions } from "react-navigation";
import {} from 'react-native-elements';
import ls from 'react-native-local-storage';
import {
Container,
Header,
Title,
Content,
Text,
Button,
Footer,
FooterTab,
Left,
Body,
Right,
Input,
Item,
List,ListItem,Thumbnail
} from "native-base";
import axios from 'axios';
import Icon from 'react-native-vector-icons/FontAwesome';
export default class Search extends Component {
static navigationOptions = {
header: null
}
constructor(props) {
super(props);
this.state = {
getAllUsers:'',
checkResponce:false,
userID:'',
changeButtons:false,
};
}
componentDidMount(){
ls.get("savedata").then(data => {this.setState({ userID: data.user.id })});
axios.get( "http://172.104.217.178/api/get_users" )
.then(response => {
//alert(JSON.stringify(response));
this.setState({getAllUsers:response.data,})
// alert(JSON.stringify(this.state.getAllUsers));
})
.catch(error => alert(error.response.data));
}
Donefollow(getuserId){
axios.post( "http://172.104.217.178/api/follow_user/"+this.state.userID,{
user_id:getuserId
} )
.then(response => {
//alert(JSON.stringify(response));
if(response.data.status===1){
this.changebutton(getuserId)
}
})
.catch(error => alert(error.response.data));
}
async changebutton(followid){
this.setState({changeButtons:true})
await alert("here can i change ?")
}
render() {
let GetUersData=[];
let UsersState=this.state.getAllUsers;
for(let property in UsersState.result){
GetUersData.push( <ListItem avatar style={{height:71}}>
<Left>
<Thumbnail source={{uri:UsersState.result[property].profile_photo}} />
</Left>
<Body >
<Text style={{marginTop:15}}>{UsersState.result[property].name}</Text>
<Text note></Text>
</Body>
<Right >{this.state.changeButtons?
<Button rounded warning onPress={this.Donefollow.bind(this,UsersState.result[property].id)}>
<Text>Following</Text>
</Button>: <Button rounded warning onPress={this.Donefollow.bind(this,UsersState.result[property].id)}>
<Text>Follow</Text>
</Button>}
{/* <Button rounded warning onPress={this.Donefollow.bind(this,UsersState.result[property].id)}>
<Text>Follow</Text>
</Button> */}
</Right>
{/* <Right style={{paddingTop:10}}>
</Right> */}
</ListItem>)
}
return (
<Container style={styles.container}>
<Header>
{/* <Left>
<Text>Search</Text>
</Left> */}
<Body >
<Item rounded style={{width:"100%",height:35}}>
<Icon active color='#f39c12' size={24} style={{marginLeft:12}}name='search' />
<Input placeholder='Search'/>
</Item>
</Body>
{/* <Right>
<Button style={{backgroundColor:'transparent'}}>
<Icon style={{color:'#000'}} name="search" />
</Button>
</Right> */}
</Header>
{/*End Header*/}
<Content>
<List style={{marginTop:15}}>
{/* <ListItem avatar style={{height:71}}>
<Left>
<Thumbnail source={require('../../../images/profile_1x.png')} />
</Left>
<Body >
<Text style={{marginTop:15}}>Name</Text>
<Text note></Text>
</Body>
<Right >
<Button rounded dark>
<Text>Follow</Text>
</Button>
</Right>
<Right style={{paddingTop:10}}>
</Right>
</ListItem> */}
{GetUersData}
</List>
</Content>
<Footer>
<FooterTab>
<Button >
<Icon size={24}name="home" onPress={() =>this.props.navigation.navigate('Home') }/>
</Button>
<Button >
<Icon color='#f39c12' name="search" size={20}/>
</Button>
<Button onPress={() =>this.props.navigation.navigate('Gallery') }>
<Icon name="plus"size={20} />
</Button>
<Button onPress={() =>this.props.navigation.navigate('Following') }>
<Icon name="heart" size={20} />
</Button>
<Button onPress={() =>this.props.navigation.navigate('Profile') }>
<Icon name="user" size={20}/>
</Button>
</FooterTab>
</Footer>
</Container>
);
}
}
const styles = StyleSheet.create({
container:{
flex: 1,
},
topTabs:{
borderBottomWidth: 2,
width:180
},
borderLine:{
borderWidth: 1,
marginTop:10,
marginHorizontal: 40,
},
imageStyle:{
paddingTop: 10,
},
})
Here is my output before clicked
and after clicked output looks like that
I want when I clicked on whatever button just that button will change not all buttons help me please
add another state like buttonChangedUserID and set that in following method
async changebutton(followid){
this.setState({changeButtons:true, buttonChangedUserID:followid })
....
then use it to get selected user id to change button while rendering it after state change
I need to set a custom color for Radio button, here is what i tired :
<Radio
color={"#ff0000"}
selectedColor={"#ff0000"}
selected={true}
onPress={ ()=> this.props.somefunc() }
/>
I find it working. Try this code.
import React, { Component } from 'react';
import { Container, Header, Content, ListItem, Text, Radio, Right } from 'native-base';
export default class App extends Component {
state = {
radioBtnOne: false,
radioBtnTwo: false
}
render() {
return (
<Container>
<Header />
<Content>
<ListItem onPress={() => this.setState({ radioBtnOne: !this.state.radioBtnOne })}>
<Text>Daily Stand Up</Text>
<Right>
<Radio selected={this.state.radioBtnOne} color="red" selectedColor="green" onPress={() => this.setState({ radioBtnOne: !this.state.radioBtnOne })} />
</Right>
</ListItem>
<ListItem onPress={() => this.setState({ radioBtnTwo: !this.state.radioBtnTwo })}>
<Text>Discussion with Client</Text>
<Right>
<Radio selected={this.state.radioBtnTwo} color="red" selectedColor="green" onPress={() => this.setState({ radioBtnOne: !this.state.radioBtnOne })} />
</Right>
</ListItem>
</Content>
</Container>
);
}
}
Gif
The problem was solved in the new version of native base (2.7.2).
same problem that's why i used
library : react-native-flexi-radio-button
also you use one of following libraries
1: react-native-simple-radio-button
2: radio-button-react-native
When radio button not selected:
<Radio selected={false} color="gray" selectedColor="green" />
When radio button selected:
i got a little problem with Header component in NativeBase (UI Component for React Native). Its position should be on top. But, mine is below a white block. I don't know why its there.
Here my code
import React, { Component } from 'react';
import { Image } from 'react-native';
import {
Container,
Header,
Left,
Body,
Right,
Title,
Content,
Footer,
FooterTab,
Button,
Icon,
Text,
List,
ListItem,
Switch,
Item,
Input,
Form,
DeckSwiper,
Card,
CardItem,
Thumbnail,
View
} from 'native-base';
import { Col, Row, Grid } from "react-native-easy-grid";
import { StackNavigator } from 'react-navigation';
import Expo from "expo";
import { cards, groups_category } from '../data/dummies';
class HomeScreen extends Component {
constructor (props) {
super(props);
this.state = {
loading: true,
isUserLogin: false,
searchStatus: false
}
this.showSearch = this.showSearch.bind(this);
this.checkLoginStatus = this.checkLoginStatus.bind(this);
}
async componentWillMount() {
await Expo.Font.loadAsync({
'Roboto': require('native-base/Fonts/Roboto.ttf'),
'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
'Ionicons': require("#expo/vector-icons/fonts/Ionicons.ttf")
});
this.setState({ loading: false });
}
showSearch () {
this.setState({ searchStatus: !this.state.searchStatus });
}
checkLoginStatus () {
if (!this.state.isUserLogin) {
return this.props.navigation.navigate('Login');
} else {
return
}
}
render() {
if (this.state.loading) {
return <Expo.AppLoading />;
}
return (
<Container>
{ this.state.searchStatus &&
(<Header searchBar rounded>
<Item regular>
<Icon name='md-arrow-back' onPress={this.showSearch} />
<Input placeholder='Contoh: Jakarta Memancing'/>
<Icon name='search' />
</Item>
</Header>)
}
{ !this.state.searchStatus &&
(<Header>
<Left>
<Icon name='add' style={{color: '#FFFFFF'}} />
</Left>
<Body style={{ alignItems: 'center' }}>
<Title>Komunitas</Title>
</Body>
<Right>
<Icon name='search' style={{color: '#FFFFFF'}} onPress={this.showSearch} />
</Right>
</Header>)
}
{/* Content */}
<Content padder={true}>
<View style={{height: 470}}>
<DeckSwiper
dataSource={cards}
renderItem={item =>
<Card style={{ elevation: 3 }}>
<CardItem>
<Left>
<Thumbnail source={item.image} />
<Body>
<Text>{item.text}</Text>
<Text note>NativeBase</Text>
</Body>
</Left>
</CardItem>
<CardItem cardBody>
<Image style={{ height: 300, flex: 1 }} source={item.image} />
</CardItem>
<CardItem>
<Icon name="heart" style={{ color: '#ED4A6A' }} />
<Text>{item.name}</Text>
</CardItem>
</Card>
}
/>
</View>
<List>
<ListItem itemHeader first>
<Text>Kategori Grup</Text>
</ListItem>
{groups_category.map(group => {
return (<ListItem key={group.id}>
<Left>
<Icon name={group.icon}/>
</Left>
<Body>
<Text>{group.name}</Text>
</Body>
<Right />
</ListItem>)
}
)}
</List>
</Content>
{/* Content */}
<Footer>
<FooterTab>
<Button vertical active>
<Icon active name="home" />
<Text style={{fontSize: 9.5}}>Home</Text>
</Button>
<Button vertical>
<Icon name="megaphone" />
<Text style={{fontSize: 9.5}}>Baru</Text>
</Button>
<Button vertical>
<Icon name="notifications" />
<Text style={{fontSize: 9.5}}>Notifikasi</Text>
</Button>
<Button onPress={this.checkLoginStatus} vertical>
<Icon name="person" />
<Text style={{fontSize: 9.5}}>Profil</Text>
</Button>
</FooterTab>
</Footer>
</Container>
);
}
}
export default HomeScreen;
It results like this
As you can see the Header which has search icon is located below an empty space / white color. Why this happen ? Maybe there are a lot of friends here had experienced it before when using NativeBase UI Component.
It's because you are using StackNavigator as well. You can disable the header as below.
static navigationOptions = {
headerMode: 'none'
}
UPDATE for React Navigation 5.x
If you want to use Nativebase's header with react navigation 5, you can do it like this:
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import {
Header,
Left,
Body,
Title,
Button,
Icon,
View,
Text
} from 'native-base';
const Stack = createStackNavigator();
const Home = () => {
return (
<View>
<Text>Hello World</Text>
</View>
)
}
const CustomHeader = ({scene, previous, navigation}) => {
const {options} = scene.descriptor;
const title =
options.headerTitle !== undefined
? options.headerTitle
: options.title !== undefined
? options.title
: scene.route.name;
return (
<Header>
<Left>
{previous ? (
<Button transparent onPress={navigation.goBack}>
<Icon name="arrow-back" />
</Button>
) : (
undefined
)}
</Left>
<Body>
<Title>{title}</Title>
</Body>
</Header>
);
};
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={Home}
options={{
header: (props) => <CustomHeader {...props} />,
}}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
More of the options here https://reactnavigation.org/docs/en/stack-navigator.html
Set header null in navigation option to remove top blank space, like below
export default class Home extends React.Component {
static navigationOptions = {
title: 'Home',
header: null //used for removing blank space from top
};
}