I try to create react native app that looks like existing web app. I have a fixed footer at bottom of window. Do anyone have idea how this can be achieved with react native?
in existing app it's simple:
.footer {
position: fixed;
bottom: 0;
}
Here's the actual code based on Colin's Ramsay answer:
<View style={{flex: 1}}>
<ScrollView>main</ScrollView>
<View><Text>footer</Text></View>
</View>
Off the top of my head you could do this with a ScrollView. Your top-level container could be a flex container, inside that have a ScrollView at the top and your footer at the bottom. Then inside the ScrollView just put the rest of your app as normal.
I'm using fixed footers for buttons in my app. The way I implement a fixed footer is like so:
<View style={{flex: 1}}>
<View><Text>my text</Text></View>
<View style={{position: 'absolute', left: 0, right: 0, bottom: 0}}><Text>My fixed footer</Text></View>
</View>
And if need the footer to move up when a keyboard appears for instance you can use:
const { DeviceEventEmitter } = React
class MyClass {
constructor() {
this.state = {
btnLocation: 0
}
}
componentWillMount() {
DeviceEventEmitter.addListener('keyboardWillShow', this.keyboardWillShow.bind(this))
DeviceEventEmitter.addListener('keyboardWillHide', this.keyboardWillHide.bind(this))
}
keyboardWillShow(e) {
this.setState({btnLocation: e.endCoordinates.height})
}
keyboardWillHide(e) {
this.setState({btnLocation: 0})
}
}
Then use {bottom: this.state.btnLocation} in your fixed footer class. I hope this helps!
You get the Dimension first and then manipulate it through flex style
var Dimensions = require('Dimensions')
var {width, height} = Dimensions.get('window')
In render
<View style={{flex: 1}}>
<View style={{width: width, height: height - 200}}>main</View>
<View style={{width: width, height: 200}}>footer</View>
</View>
The other method is to use flex
<View style={{flex: 1}}>
<View style={{flex: .8}}>main</View>
<View style={{flex: .2}}>footer</View>
</View>
#Alexander Thanks for solution
Below is code exactly what you looking for
import React, {PropTypes,} from 'react';
import {View, Text, StyleSheet,TouchableHighlight,ScrollView,Image, Component, AppRegistry} from "react-native";
class mainview extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<View style={styles.mainviewStyle}>
<ContainerView/>
<View style={styles.footer}>
<TouchableHighlight style={styles.bottomButtons}>
<Text style={styles.footerText}>A</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.bottomButtons}>
<Text style={styles.footerText}>B</Text>
</TouchableHighlight>
</View>
</View>
);
}
}
class ContainerView extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<ScrollView style = {styles.scrollViewStyle}>
<View>
<Text style={styles.textStyle}> Example for ScrollView and Fixed Footer</Text>
</View>
</ScrollView>
);
}
}
var styles = StyleSheet.create({
mainviewStyle: {
flex: 1,
flexDirection: 'column',
},
footer: {
position: 'absolute',
flex:0.1,
left: 0,
right: 0,
bottom: -10,
backgroundColor:'green',
flexDirection:'row',
height:80,
alignItems:'center',
},
bottomButtons: {
alignItems:'center',
justifyContent: 'center',
flex:1,
},
footerText: {
color:'white',
fontWeight:'bold',
alignItems:'center',
fontSize:18,
},
textStyle: {
alignSelf: 'center',
color: 'orange'
},
scrollViewStyle: {
borderWidth: 2,
borderColor: 'blue'
}
});
AppRegistry.registerComponent('TRYAPP', () => mainview) //Entry Point and Root Component of The App
Below is the Screenshot
Simple stuff here:
Incase you don't need a ScrollView for this approach you can go with the below code to achieve Something like this :
<View style={{flex: 1, backgroundColor:'grey'}}>
<View style={{flex: 1, backgroundColor: 'red'}} />
<View style={{height: 100, backgroundColor: 'green'}} />
</View>
You might also want to take a look at NativeBase (http://nativebase.io). This a library of components for React Native that include some nice layout structure (http://nativebase.io/docs/v2.0.0/components#anatomy) including Headers and Footers.
It's a bit like Bootstrap for Mobile.
The way I did this was to have a view (lets call it P) with flex 1, then inside that view have 2 more views (C1 and C2) with flex 0.9 and 0.1 respectively (you can change the flex heights to required values). Then, inside the C1 have a scrollview. This worked perfectly for me. Example below.
<View style={{flex: 1}}>
<View style={{flex: 0.9}}>
<ScrollView>
<Text style={{marginBottom: 500}}>scrollable section</Text>
</ScrollView>
</View>
<View style={{flex: 0.1}}>
<Text>fixed footer</Text>
</View>
</View>
Below is code to set footer and elements above.
import React, { Component } from 'react';
import { StyleSheet, View, Text, ScrollView } from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.containerMain}>
<ScrollView>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
<Text> Main Content Here</Text>
</ScrollView>
<View style={styles.bottomView}>
<Text style={styles.textStyle}>Bottom View</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
containerMain: {
flex: 1,
alignItems: 'center',
},
bottomView: {
width: '100%',
height: 50,
backgroundColor: '#EE5407',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
bottom: 0,
},
textStyle: {
color: '#fff',
fontSize: 18,
},
});
When flex is a positive number, it makes the component flexible and it will be sized proportional to its flex value. So a component with flex set to 2 will take twice the space as a component with flex set to 1.
<View style={{flex: 1}>
<ScrollView style={{flex: 1}>
//your scroll able content will be placed above your fixed footer content.
//when your content will grow bigger and bigger it will hide behind
//footer content.
</ScrollView>
<View style={styles.footerContainer}>
//your fixed footer content will sit fixed below your screen
</View>
</View>
One could achieve something similar in react native with position: absolute
let footerStyle = {
position: 'absolute',
bottom: 0,
}
There are a few things to keep in mind though.
absolute positions the element relative to its parent.
You might have to set the width and hight of the element manually.
Width and hight will change when orientation changes. This has to be managed manually
A practical style definition would look something like this:
import { Dimensions } from 'react-native';
var screenWidth = Dimensions.get('window').width; //full screen width
let footerStyle = {
position: 'absolute',
bottom: 0,
width: screenWidth,
height: 60
}
Suggestion 1
=> Body with fixed footer
<View style={{ flex: 1, backgroundColor: 'gray' }}>
<View style={{ flex: 9, backgroundColor: 'gray',alignItems: 'center', justifyContent: 'center', }}>
<Text style={{color:'white'}}>...Header or Body</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'yellow', alignItems: 'center', justifyContent: 'center', }}>
<Text>...Footer</Text>
</View>
</View>
Edit 2
=> Body & Fixed footer with tabs
<View style={{ flex: 1, backgroundColor: 'gray' }}>
<View style={{ flex: 9, backgroundColor: 'gray', alignItems: 'center', justifyContent: 'center', }}>
<Text style={{ color: 'white' }}>...Header or Body</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'yellow', alignItems: 'center', justifyContent: 'center', }}>
<View style={{ flex: 1, flexDirection: 'row' }}>
<TouchableOpacity style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white' }}>
<View>
<Text>
...Home
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'white' }}>
<View>
<Text>
...Settings
</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
Notes
import {TouchableOpacity} from 'react-native'
Advantages
We can use this simple footer without react bottom navigation
The best way is to use justifyContent property
<View style={{flexDirection:'column',justifyContent:'flex-end'}}>
<View>
<Text>fixed footer</Text>
</View>
</View>
if you have multiple view elements on screen, then you can use
<View style={{flexDirection:'column',justifyContent:'space-between'}}>
<View>
<Text>view 1</Text>
</View>
<View>
<Text>view 2</Text>
</View>
<View>
<Text>fixed footer</Text>
</View>
</View>
I found using flex to be the simplest solution.
<View style={{flex:1,
justifyContent: 'space-around',
alignItems: 'center',
flexDirection: 'row',}}>
<View style={{flex:8}}>
//Main Activity
</View>
<View style={{flex:1}}>
//Footer
</View>
</View>
import {Dimensions} from 'react-native'
const WIDTH = Dimensions.get('window').width;
const HEIGHT = Dimensions.get('window').height;
then on the write this styles
position: 'absolute',
top: HEIGHT-80,
left: 0,
right: 0,
worked like a charm
if you just use react native so you can use the following code
<View style={{flex:1}}>
{/* Your Main Content*/}
<View style={{flex:3}}>
<ScrollView>
{/* Your List View ,etc */}
</ScrollView>
</View>
{/* Your Footer */}
<View style={{flex:1}}>
{/*Elements*/}
</View>
</View>
also, you can use https://docs.nativebase.io/ in your react native project and then do something like the following
<Container>
{/*Your Main Content*/}
<Content>
<ScrollView>
{/* Your List View ,etc */}
</ScrollView>
</Content>
{/*Your Footer*/}
<Footer>
{/*Elements*/}
</Footer>
</Container>
React_Native
NativeBase.io
For Android problems with this:
in app/src/AndroidManifest.xml change windowSoftInputMode to the following.
<activity
android:windowSoftInputMode="stateAlwaysHidden|adjustPan">
I had absolutely no problems with this in ios using react-native and keyboardAwareScroll. I was about to implement a ton of code to figure this out until someone gave me this solution. Worked perfectly.
Set android:windowSoftInputMode="adjustPan" in your manifest file, and it will work as you expect.
I've used a combination of height: 100% and flex: 1.
<View style={{ height: "100%" }}>
<View
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
height: 50,
}}
>
{R.map(
tab => (
<TouchableOpacity
key={tab.id}
onPress={() => setCurrentTab(tab)}
>
<Text>{tab.name}</Text>
</TouchableOpacity>
),
tabs
)}
</View>
<View style={{ flex: 1 }}>
<View style={{ height: "100%" }}>
<View style={{ flex: 1 }}>
<ScrollView
style={{
width: "100%",
}}
>
... ScrollView content
</ScrollView>
</View>
<View
style={{
borderTopColor: "#dadada",
borderTopWidth: 1,
width: "100%",
alignItems: "center",
justifyContent: "center",
height: 60,
paddingBottom: 10,
}}
>
<TouchableOpacity
style={{
padding: 8,
borderRadius: 3,
}}
>
<Text>
Show Results
</Text>
</TouchableOpacity>
</View>
</View>
</View>
I think best and easy one would be as below, just place rest of ur view in a content and footer in a separate view.
`<Container>
<Content>
<View>
Ur contents
</View>
</Content>
<View>
Footer
</View>
</Container>`
or u can use footer from native-base
`<Container>
<Content>
<View>
Ur contents
</View>
</Content>
<Footer>
Footer
</Footer>
</Container>`
i created a package. it may meet your needs.
https://github.com/caoyongfeng0214/rn-overlaye
<View style={{paddingBottom:100}}>
<View> ...... </View>
<Overlay style={{left:0, right:0, bottom:0}}>
<View><Text>Footer</Text></View>
</Overlay>
</View>
Create a Style like this:
const styles = StyleSheet.create({
header:{ backgroundColor: "#00BFFF", height: "20%" },
footer:{ backgroundColor: "royalblue", height: "10%", flexDirection: "row", alignItems: "center" }
});
Then use the style in a tag :
<View style={styles.footer}>
<View style={{ flex: 1, alignItems: "center" }}>
<Pressable onPress={() => openCamera(true)}>
<View style={{ flexDirection: "column", alignItems: "center" }}>
<Icon name="camera" style={{ fontSize: 21, color: "white" }}/>
<Text style={{ color: "white" }}>Photo</Text>
</View>
</Pressable>
</View>
</View>