How to build a home screen using gridview in react native? - react-native

I need to build a home screen with grid view in react-native. And that grid view should contain four Image buttons. Each image button should redirect to different pages. I am using the react-native-super-grid package.

If you need only 4 image button than no need to make a complex grid . Use below code only and if you need a complex gird than use this YouTube video link for better understanding.
import React, { Component } from 'react';
import { AppRegistry, View,Image } from 'react-native';
export default class FlexDirectionBasics extends Component {
render() {
return (
// Try setting `flexDirection` to `column`.
<View style={{flex: 1, }}>
<View style={{flex: 1, flexDirection: 'row', }}>
<Image source={{uri: 'https://facebook.github.io/react/logo-og.png'}}
style={{flex:1}} />
<Image source={{uri: 'https://cdn-images-1.medium.com/max/512/1*qUlxDdY3T-rDtJ4LhLGkEg.png'}}
style={{flex:1}} />
</View>
<View style={{flex: 1, flexDirection: 'row', }}>
<Image source={{uri: 'https://rawgit.com/gorangajic/react-icons/master/react-icons.svg'}}
style={{flex:1}} />
<Image source={{uri: 'https://facebook.github.io/react/logo-og.png'}}
style={{flex:1}} />
</View>
</View>
);
}
};
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => FlexDirectionBasics);
Let me know if need more discussion

Here is the code according to user package.
RenderItem function is work such as loop.
when you put 4 objects in sections array RenderItem will make a loop for 4 time.
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Image style={styles.img} source={require('./assets/3.jpg')} />
<SuperGridSectionList
itemDimension={130}
sections={[
{
// all your style and data will be here according to your grid package
data: [
{ name: '1' }, { name: '2' },
{ name: '3' }, { name: '4' },
]
}
]}
style={styles.gridView}
renderItem={({ item }) => (
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.button} onPress={() => { alert("clicked me") }}>
<Image source={require("./assets/set2.png")} />
</TouchableOpacity>
</View>

You can install "npm install react-native-super-grid" and try this. You can change itemDimension then it will change number of icons should display on screen. This is only sample you can change what ever you needs.
import React, { Component } from "react";
import {
StyleSheet,
View,
Text,
TouchableOpacity,
PixelRatio,
Image
} from "react-native";
import { Container, Header, Content } from "native-base";
import GridView from "react-native-super-grid";
const buttons = [
{
name: "test1",
image: require("./src/icons/test1.png"),
key: 1
},
{
name: "test2",
image: require("./src/icons/test2.png"),
key: 2
},
{
name: "test3",
image: require("./src/icons/test3.png"),
key: 3
},
{
name: "test4",
image: require("./src/icons/test4.png"),
key: 4
},
];
class Home extends Component {
constructor(props) {
super(props);
}
onPress(){
}
render() {
return (
<Container style={styles.container}>
<Content contentContainerStyle={styles.contentContainerStyle}>
<GridView
itemDimension={180}
items={buttons}
renderItem={item => (
<View style={styles.gridCompenentContainer}>
<TouchableOpacity
onPress={this.onPress.bind(this)}
activeOpacity={0.8}
style={styles.touchView}
>
<Image
style={{ width: 60, height: 60 }}
source={item.image}
/>
</TouchableOpacity>
<View style={styles.textView}>
<Text style={styles.text}>{item.name} </Text>
</View>
</View>
)}
/>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff"
},
contentContainerStyle: {
backgroundColor: "#fff",
justifyContent: "center"
},
gridCompenentContainer: {
width: 160,
height: 140,
flexDirection: "column",
justifyContent: "center",
alignItems: "center"
},
touchView: {
width: 80,
justifyContent: "center",
alignItems: "center",
height: 80,
borderRadius: 40,
backgroundColor: "#0099cc"
},
textView: {
width: 140,
height: 50,
justifyContent: "center",
alignItems: "center"
},
text: {
width: 140,
fontSize: 12,
textAlign: "center",
color: "#0099cc"
}
});
export default Home;

thara### please refer this to get know how to implement react navigation or official documentation React Navigation.
You can add route for button press event. like
onPress={() =>
this.props.navigation.navigate('screen2');
}
https://facebook.github.io/react-native/docs/navigation#react-navigation

Related

Height of super view is not setting properly because of FlatList as its subview

I am trying to create a FlatList within a View, but when I set the view's position as Absolute, it takes the total content size of the FlatList. But I want to keep the height of the View as the remaining screen size between Navigation Bar & Bottom bar, but I don't know how to achieve that.
Here is my code:
import React from 'react';
import { View, StyleSheet, SafeAreaView, FlatList, Image, } from 'react-native';
import { DARK_GREY_COLOR_CODE, GREY_COLOR_CODE, MAGENTA_COLOR_CODE } from '../Constant/Constants';
export default class ExplorePage extends React.Component {
_renderTutorialList() {
}
render() {
const sampleNameArray = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'Kinky',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Waves/Loose Curls',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Curly',
image_name: './Images/hairtype_thum_image.png',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d79',
title: 'Coily',
},
];
return (
<SafeAreaView style={{flex:1, }}>
<View style={{ flex: 1, position: 'absolute', width: '100%', backgroundColor: GREY_COLOR_CODE }}>
<FlatList
data={sampleNameArray}
renderItem={({ item }) =>
<View style={{width: '89.3%', height: 302, marginLeft: '5.4%', marginRight: '5.4%', }}>
<Image source={require('../Images/user_icon.png')} style={{ position: 'absolute', width: '100%', height: '90%', borderRadius: 10, backgroundColor: MAGENTA_COLOR_CODE}} />
</View>
}
keyExtractor={item => item.id}
/>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
width: 300,
marginTop: 16,
},
});
Please help me out. I am unable to fix it as I am new to the React Native.
Here is the screenshot:
try this out
first render items from Flatlist and return view of Flatlist item
render() {
return (
<View style={{flex: 1}}>
<FlatList
extraData={this.state}
data={sampleNameArray}
keyExtractor={item => {
return item;
}}
renderItem={this.renderItem}
/>
</View>
);
this is your main render method and then render the items and adjust your list style in the next render and use style as described style={styles.stylename}
renderItem = ({item}) => {
return (
<View>
<View style={styles.body}>
<Text style={styles.text}> {item.data1}</Text>
<Text style={styles.text}> {item.data2}</Text>
<Text style={styles.text}> {item.data3}</Text>
</View>
</View>
);
and you can set how you want to render your item , like i do like this
then you can set CSS property to each and every element.
Hope it will gonna work for you 😃

Center Text in FlatList next to Icon - React Native

I am currently trying to center the text from the FlatList.
By centering I mean I want it to be in the middle, right of each Icon.
Currently this is how is displaying, it's on the bottom. I just want it to be a little bit higher:
Here is how my component looks like:
I have tried to implement few styles, but still no success.
The thing that crossed my mind but did not try was to hard code each line and drop the loop, but I am not sure if this is right to do.
import SocialIcon from 'react-native-vector-icons/AntDesign';
import BookingIcon from 'react-native-vector-icons/FontAwesome';
import FeatherIcons from 'react-native-vector-icons/Feather';
export const bookIcon = (<BookingIcon name="pencil-square-o" size={40} color="purple" />);
export const calendarIcon = (<SocialIcon name="calendar" size={40} color="purple" />);
export const questionIcon = (<SocialIcon name="questioncircleo" size={40} color="purple" />);
export const externalLinkIcon = (<FeatherIcons name="external-link" size={40} color="purple" />);
class AboutMe extends Component {
static navigationOptions = {
title: "About Me",
}
render() {
return (
<View style={styles.container}>
<View style={styles.topBox}>
<View style={styles.circleOuter} />
<View style={styles.circle} />
</View>
<View style={styles.middleBox}>
</View>
<View style={styles.bottomBox}>
<FlatList
contentContainerStyle={styles.listItem}
data={[
{key: 'Book a free appointment', page:'Book', icon: bookIcon},
{key: 'Availability', page:'Availability', icon:calendarIcon},
{key: 'FAQ', page:'Faq', icon: questionIcon},
{key: 'Useful Links', page: 'Links', icon: externalLinkIcon},
]}
onPress={() => this.props.navigation.navigate('Book')}
renderItem={({item}) => {
return (
<TouchableHighlight onPress={() => this.props.navigation.navigate(`${item.page}`)}>
<Text >{item.icon}{item.key}</Text>
</TouchableHighlight>
)
}}
/>
</View>
</View>
);
};
};
const styles = StyleSheet.create({
container: {
flex: 1
},
topBox: {
flex:3,
backgroundColor: 'red',
justifyContent:'center',
alignItems: 'center'
},
middleBox: {
flex:1,
backgroundColor: 'yellow'
},
bottomBox: {
flex:4,
backgroundColor: 'orange',
padding: 20
},
circle: {
width: 160,
height: 160,
borderRadius: 160/2,
backgroundColor: 'green',
position: 'absolute'
},
circleOuter: {
width: 180,
height: 180,
borderRadius: 180/2,
backgroundColor: 'black'
},
listItem: {
flex:1,
justifyContent: 'center'
},
text: {
fontSize: 20,
}
});
You need to wrap the Text tag in a View/TouchableHighlight tag and then center the text tag vertically. Try this and let me know. It could be necessary that you wrap the icons in a separated image tag. if the code avode dont work means that a separeted tag is necessary so let me know!
<TouchableHighlight
style={styles.buttonsStyle}
onPress={() => this.props.navigation.navigate(`${item.page}`)}
>
<Text>{item.icon}{item.key}</Text>
</TouchableHighlight>
...
...
...
//in the styles add
buttonsStyle:{
justifyContent: 'center',
}
EDIT1
In order to wrap the icons it should be like following.. Note that you cannot use TouchableHighlight in this case. it seems to be a bug with react-native. aslo i used TouchableOpacity
renderItem={({item}) => {
return (
<TouchableOpacity
style={styles.buttonsStyle}
onPress={() => this.props.navigation.navigate(`${item.page}`)}
>
<Image style={styles.imgStyles} source={item.icon} />
<Text style={styles.mappedTextStyle}>{item.key}</Text>
</TouchableOpacity>
)
}}
styles to change/add
buttonsStyle:{
alignItems: 'center',
flexDirection:'row',
marginTop: 5,
},
imgStyles:{
width: 40,
height: 40,
marginRight: 10
},
mappedTextStyle: {
fontSize: 18,
color: 'black'
},
EDIT 2
In order to cover vector-icons lib, i have created a Expo snack for producing the desired behavior. Expo snack has also the expected solution for the problem Expo Snack

React navigation status bar alert

I'm using react-native-status-bar-alert in combination with react-navigation.
In the latest version of react-navigation there's a problem with the height.
The height of the header is too big when the alert is active.
Anyone else experienced this issue and has a solution?
I think you should use a plugin: navigationbar-react-native
First, if you use react-navigation you should hide header-bar and use custom header-bar
export const RootStack = createStackNavigator(
{
Home: {
screen: HomeComponent,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'Home',
}
);
1, Install package
npm i navigationbar-react-native --save
2, Using
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,Image,
View,
TouchableOpacity,
} from 'react-native';
import NavigationBar from 'navigationbar-react-native';
const ComponentLeft = () => {
return(
<View style={{ flex: 1, alignItems: 'flex-start'}} >
<TouchableOpacity style={ {justifyContent:'center', flexDirection: 'row'}}>
<Image
source={require('./img/ic_back.png')}
style={{ resizeMode: 'contain', width: 20, height: 20, alignSelf: 'center' }}
/>
<Text style={{ color: 'white', }}>Back Home</Text>
</TouchableOpacity>
</View>
);
};
const ComponentCenter = () => {
return(
<View style={{ flex: 1, }}>
<Image
source={require('./img/ic_logo.png')}
style={{resizeMode: 'contain', width: 200, height: 35, alignSelf: 'center' }}
/>
</View>
);
};
const ComponentRight = () => {
return(
<View style={{ flex: 1, alignItems: 'flex-end', }}>
<TouchableOpacity>
<Text style={{ color: 'white', }}> Right </Text>
</TouchableOpacity>
</View>
);
};
class App extends Component {
render() {
return (
<View style={styles.container}>
<NavigationBar
componentLeft = { () => {<ComponentLeft /> }
componentCenter = { () => {<ComponentCenter /> }
componentRight = { () => {<ComponentRight /> }
navigationBarStyle= {{ backgroundColor: ''#215e79'' }}
statusBarStyle = {{ barStyle: 'light-content', backgroundColor: '#215e79' }}
/>
</View>
);
}
}
Easy create custom header bar in react native

React-native elements search bar ref to use focus() method for instance is undefined

I followed the doc of the react-native-elements library but I get this.search as an undefined object...
searchbar react-native-elements
class SearchBarTest extends Component {
componentDidMount()
{
this.search.focus()//search is undefined
}
render(){
<SearchBar
ref={search => this.search = search}
...
/>
}
}
Any idea how to make this working?
EDIT:
Adding full context of the code.
The idea is having a component with a header and body. The header has an optional search bar or a title and two buttons depending on the props search.
If search props is true, then I display the searchBar.
PARENT COMPONENT:
import React, {Component} from 'react';
import {StyleSheet, View, Text, TouchableWithoutFeedback, Keyboard} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import DismissableKeyboardContainer from '../../components/DismissableKeyboardContainer';
export default class Search extends Component {
static navigationOptions = () => {
return {
tabBarIcon: ({tintColor}) => (
<Icon name="ios-search-outline" size={25} color={tintColor}/>
)
}
};
render() {
someMethod = () => {
console.log('hello');
}
return (
<DismissableKeyboardContainer search={true}>
<View style={{flex: 1, alignItems: 'center'}}>
<Text>Hello world</Text>
</View>
</DismissableKeyboardContainer>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
}
});
COMPONENT where the actual searchBar component is used:
import React, { Component} from 'react';
import { Keyboard, TouchableWithoutFeedback, TouchableOpacity, View, Text, StyleSheet} from 'react-native';
import { SearchBar } from 'react-native-elements'
import Icon from 'react-native-vector-icons/Ionicons';
import PropTypes from 'prop-types';
class DismissableKeyboardContainer extends Component {
static defaultProps = {
title: '',
search: false,
buttonLeft: '',
buttonRight: '',
borderShadow: true,
headerStyle:{}
};
componentDidMount()
{
}
render() {
let { title, search, buttonLeft, buttonRight, headerStyle, borderShadow } = this.props;
return (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<View style={{ flex: 1 }}>
<View style={[styles.headerContainer, borderShadow ? styles.borderShadow : '', headerStyle]}>
{
!search && <View style={{position: 'absolute', padding: 10, bottom: 0, flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}}>
<TouchableOpacity style={{ flex: 0.2, alignItems: 'center'}}>
{
buttonLeft != "" && <Icon name={buttonLeft} size={25} color="grey" />
}
</TouchableOpacity>
<View style={{ flex: 1, alignItems: 'center' }}>
<Text style={styles.title}>{title}</Text>
</View>
<TouchableOpacity style={{ flex: 0.2, alignItems: 'center' }}>
{
buttonRight != "" && <Icon name={buttonRight} size={25} color="grey" />
}
</TouchableOpacity>
</View>
}
{
search && <SearchBar
ref={search => this.search = search}
containerStyle={{ backgroundColor: 'transparent', borderTopWidth: 0, borderBottomWidth: 0 }}
inputStyle={{ backgroundColor: 'white' }}
lightTheme
onChangeText={someMethod}
placeholder='Type Here...'
/>
}
</View>
<View style={{ flex: 1, backgroundColor: 'transparent'}}>
{this.props.children}
</View>
</View>
</TouchableWithoutFeedback>
);
}
}
const styles = StyleSheet.create({
headerContainer: {
flex: 0.12,
justifyContent: 'flex-end',
backgroundColor: 'white' ,
},
borderShadow: {
borderColor: '#ddd',
borderBottomWidth: 0,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 1,
elevation: 1,
},
title: {
fontSize: 18,
fontWeight: 'bold'
}
});
DismissableKeyboardContainer.propTypes = {
title: PropTypes.string.isRequired,
search: PropTypes.bool.isRequired,
buttonLeft: PropTypes.string.isRequired,
buttonRight: PropTypes.string.isRequired,
headerStyle: PropTypes.any,
};
export default DismissableKeyboardContainer;
I think I found the issue. As my SearchScreen is part of a TabBar from react-navigation, this.search.focus() error was appearing at the initial loading of the app. The Search screen being the second tab of the tabBar, I guess this is the reason why search couldn't be found as the screen was not active.
Found this answer: Trigger event on tabBar screen display
Which helped me to launch the this.search.focus() only when the screen Search is called under the componentDidUpdate() method
Please see code below:
1- First on my root navigator, I track react-navigation screen changes with onNavigationStateChange and screenProps
<Root
onNavigationStateChange={(prevState, currentState, action) => {
let currentScreen = action.routeName;
this.setState({ currentScreen })
}}
screenProps={{ currentScreen: this.state.currentScreen }}
/>
2- Then on my Parent component, I pass the currentScreen prop from I setup above in react-navigation
<DismissableKeyboardContainer search={true} currentScreen={this.props.screenProps.currentScreen}>
<View style={{flex: 1, alignItems: 'center'}}>
<Text>Hello world</Text>
</View>
</DismissableKeyboardContainer>
3- Now, I'm checking the screen being displayed and launch this.search.focus() only if the screen Search is displayed inside my DismissableKeyboardContainer child component.
componentDidUpdate() {
this.props.currentScreen === "Search" ? this.search.focus() : ''
}

How can I make a Text and a Button on the same level

I'm new to react-native and using flex box, I normally use Grid supplied by bootstrap or other css frameworks.
I'm trying to get the word Settings in the middle and my down arrow
on the right side to toggle away the modal but all I can get is this:
React code:
import React, { Component } from 'react'
import { Text, View } from 'react-native'
import { styles } from './styles'
import ViewContainer from 'Reddit/app/components/ViewContainer'
import StatusBarBg from 'Reddit/app/components/StatusBarBg'
import Icon from 'react-native-vector-icons/EvilIcons'
class SettingsIndexScreen extends Component {
render() {
return (
<ViewContainer>
<StatusBarBg />
<View style={styles.collapseIconContainer}>
<Text>Settings</Text>
<Icon name="arrow-down" size={40} />
</View>
</ViewContainer>
)
}
}
export default SettingsIndexScreen
css:
import { StyleSheet } from 'react-native'
export const styles = StyleSheet.create({
collapseIcon: {
},
toolbar: {
flexDirection: 'column'
},
toolbarTitle: {
textAlign: 'center',
flex: 1,
marginTop: 20
},
toolbarButton: {
textAlign: 'right',
marginRight: 8
}
});
Can't seem to figure out how to get them on the same level
This should give you some idea -
<View style={styles.container}>
<View style={styles.row}>
<View style={styles.col1}>
<Text style={styles.text}>Text1</Text>
</View>
<View style={styles.col2}>
<Text style={styles.text}>Text2</Text>
</View>
</View>
</View>
-
container: {
flex: 1,
},
row: {
flexDirection: 'row',
},
col1: {
flex: 0.6,
},
col2: {
flex: 0.4,
},
text: {
textAlign: 'right',
},
Try to set flexDirection: 'row' in their parent container -- collapseIconContainer, like so
collapseIconContainer: {
flexDirection: 'row';
}