Change footer style based on view height in react native - react-native

In react native, how would I go about applying a different footer style depending on the height of a particular ScrollView?
Basically, I want to create a sticky footer for a view that isn't the entire height of the phone and, if the ScrollView is larger, I want to add the footer onto the end of the ScrollView.
Hope that makes at least some sense!
Sample below for demonstration.
ThanksSimon
//If the view is larger than the phone height, have the footer at the bottom of the scroll view
<View style={{flex: 1}}>
<Header navigation={this.prop.navigation}
<Scrollview>
<View>
<Text>Content</Text>
</View>
<View>
<Image source={image} style={styles.footerImage} />
</View>
</ScrollView>
</View>
//If the content view is smaller than the phone size, the view needs to be outside the scrollview and use stick styles
<View style={{flex: 1}}>
<Header navigation={this.prop.navigation}
<Scrollview>
<View>
<Text>Content</Text>
</View>
</ScrollView>
<View>
<Image source={image} style={styles.stickyFooter} />
</View>
</View>
const styles = StyleSheet.create({
footerImage: {
width: Dimensions.get('window').width,
maxHeight: 235,
resizeMode: "contain"
},
stickyFooter: {
flex: 1,
position: 'absolute',
left: 0,
top: 0,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
});

Ciao, you could move the footer position using minHeight on Scrollview css. Something like:
<Scrollview style={styles.scrollview}>
<View>
<Text>Content</Text>
</View>
</ScrollView>
Then in your styles:
const styles = StyleSheet.create({
...
scrollview:{
minHeight: 300 // 300 for example
}
});
In this way, if Scrollview does not contains elements, footer appears after 300. Else, if Scrollview contains elements and his height is greater then 300, footer will be moved down according to Scrollview height.

import React from 'react';
import {
Text,
View,
StyleSheet,
ScrollView,
Dimensions,
Image,
} from 'react-native';
export default function App() {
return (
<View>
<ScrollView>
<View style={styles.body}>
<Text>Body</Text>
</View>
<View style={styles.footer}>
<Text>Footer</Text>
</View>
</ScrollView>
</View>
);
}
const { height } = Dimensions.get('window');
const styles = StyleSheet.create({
body: {
minHeight: height, // This is where the magic happens
backgroundColor: 'blue', // This is just for visual indication
},
footer: {
minHeight: 150,
backgroundColor: 'green' // This is just for visual indication
}
});
Should work for different screen heights.

Related

How to make curve design in react native?

I'm creating a react native app and I need to create a curved screen design. How to create a curve design like the below screen.
This is what I tried here,
My sample codes,
import React from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
} from 'react-native';
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
export default class Home extends React.Component {
render() {
return (
<View style={styles.container}>
<StatusBar hidden={true} />
<View style={styles.container1}>
<Text style={styles.name}>Container1</Text>
</View>
<View style={styles.container2}>
<Text style={styles.name}>Container1</Text>
</View>
<View style={styles.container3}>
<Text style={styles.name}>Container1</Text>
</View>
<View style={styles.container4}>
<Text style={styles.name}>Container1</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
container1: {
backgroundColor: '#3d06d6',
height: hp('25%'),
padding: 10,
borderBottomLeftRadius:100,
},
container2: {
backgroundColor: '#0cad95',
height: hp('25%'),
padding: 10,
borderBottomLeftRadius:100,
},
container3: {
backgroundColor: '#d6a606',
height: hp('25%'),
padding: 10,
borderBottomLeftRadius:100,
},
container4: {
backgroundColor: '#06bad6',
height: hp('25%'),
padding: 10,
borderBottomLeftRadius:100,
},
});
I want to curve my container edges like the first picture. I am able to make curves of the bottom edges. And How can I make curve designs like the first image? and also how can I add some animations into the container when I touch the container to open another screen? Is there any way to do this design using any style with "borderRadius" or any other way? And I don't want to use any library like react-native-svg.
If you need a Linear Gradient as the background. Just giving the color of the next box will not be the best option.
Assume "value" as the border-radius. ie the curve
Give a marginTop and paddingTop for each container.
marginTop : -value,
paddingTop : value,
Also assign zIndex in decending order for each container.
You can set zIndex with respect to the index, if you are looping through an array.
Result
Sample code
import React from 'react';
import {View, StyleSheet, Text} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
const data = ['', '', ''];
const App = () => {
return (
<View style={styles.container}>
{data.map((item, index) => (
<View style={[styles.item, {zIndex: data.length - index}]}> // setting zIndex here
<LinearGradient
style={StyleSheet.absoluteFill}
colors={['#4c669f', '#3b5998', '#192f6a']}
/>
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
zIndex: 1,
},
item: {
height: 250,
borderBottomLeftRadius: 100, // logic goes here
marginTop: -100, // move container
paddingTop: 100, // move inner item down
overflow: 'hidden',
},
});
export default App;
You can simply wrap your view inside a normal view and set the background colour of the next box which will give the output you need.
<View style={{ backgroundColor: '#0cad95' }}>
<View style={styles.container1}>
<Text style={styles.name}>Container1</Text>
</View>
</View>
<View style={{ backgroundColor: '#d6a606' }}>
<View style={styles.container2}>
<Text style={styles.name}>Container1</Text>
</View>
</View>

Disable TouchableOpacity for nested View

I've a touchable opacity, and I have a few views inside it. I have one specific view that I don't want for it to be clickable. How can I achieve this?
The specific view that you don't want for it to be clickable should be "TouchableOpacity" but have activeOpacity={1} . In this way parent TouchableOpacity will not work and activeOpacity={1} will make it like disable
Complete code
import React, { Component } from "react";
import { TouchableOpacity, View, Text } from "react-native";
export default class App extends Component {
render() {
return (
<View style={{ flex: 1, margin: 50 }}>
<TouchableOpacity
style={{ backgroundColor: "red", width: 250, height: 250 }}
>
<TouchableOpacity
style={{
backgroundColor: "green",
width: 100,
height: 100,
margin: 20,
alignItems: "center",
justifyContent: "center"
}}
activeOpacity={1}
>
<Text>No Click Area</Text>
</TouchableOpacity>
</TouchableOpacity>
</View>
);
}
}
App Preview
Go in that view and add a prop => pointerEvents:none
<View pointerEvents="none" />
Please refer here
I don't know what conditions you're talking about, but if you want to do what you want, you can use the status value. To deactivate a button when displaying a screen, change the status value when rendering the screen, or change it when you press a button. The examples are attached together.
Example
import * as React from 'react';
import { Text, View, StyleSheet,TouchableOpacity } from 'react-native';
import Constants from 'expo-constants';
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
disabled: false
}
}
componentDidMount(){
this.setState({ disabled: true})
}
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
Change code in the editor and watch it change on your phone! Save to get a shareable url.
</Text>
<TouchableOpacity style={{width:"100%",height:20,alignItems:"center",backgroundColor:"blue"}} onPress={() => alert("touch")} disabled={this.state.disabled}>
<Text>Touch </Text>
</TouchableOpacity>
<TouchableOpacity style={{width:"100%",height:20,alignItems:"center",backgroundColor:"red"}} onPress={() => this.setState({disabled:true})}>
<Text>disabled</Text>
</TouchableOpacity>
</View>
);
}
}
Another way you could do it is to wrap you View which you don't want to be clickable with TouchableWithoutFeedback.
export default class App extends React.Component {
render() {
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<TouchableOpacity style={{backgroundColor: "blue", width: 300, height: 300}}>
<TouchableWithoutFeedback>
<View style={{backgroundColor: "yellow", width: 100, height: 100}}>
<Text>Hello</Text>
</View>
</TouchableWithoutFeedback>
</TouchableOpacity>
</View>
);
}
}
As #AnaGard suggested, the key to having a press free view inside a pressable container is to make a pressable inner view without an onPress value.
Better than using TouchableOpacity is using the Pressable component, which the ReactNative's documentation suggests is more future-proof.
Therefore, an updated answer to this question might be as follows:
<View>
<Pressable
style={{ width: 500, height: 250 }}
onPress={() => onClose()}
>
<Pressable style={{ height: 100, width: 200 }}>
<View>
<Text>Your content here</Text>
</View>
</Pressable>
</Pressable>
</View>
Some references:
Pressable
TouchableOpacity

How can i create tab bar like this? is there any sample?

how can i create tab bar like this in react native?
google tasks tab bar
is there any sample like this?
Using an Image you can achieve it
Sample Snack : https://snack.expo.io/#msbot01/intelligent-croissant
import * as React from 'react';
import { Text, View, StyleSheet,Image } from 'react-native';
import Constants from 'expo-constants';
import Icon from 'react-native-vector-icons/FontAwesome';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={{backgroundColor:'white', height:'10%', bottom:0, position:'absolute', zIndex:1, width:'100%', justifyContent:'space-between',paddingLeft:15,paddingRight:15, flexDirection:'row', alignItems:'center', shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 5 }}>
<View>
<Icon name="bars" size={25} color="grey" />
</View>
<View style={{height:'100%',width:100, backgroundColor:'white'}}>
<Image style={{width:100,paddingBottom:'20%', position:'absolute', zIndex:3, bottom:'61%' }} source={require('./bottom round 2.png')} />
</View>
<View>
<Icon name="ellipsis-v" size={25} color="grey" />
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: 'white',
position:'relative',
}
});
I created one like this with an SVG in the middle. Left and right is an empty view with a width and a background color. In the middle the SVG component. The floating button is made with an absolute position. I don't know if there is a better way to do this, but that's my solution.
I have created one using SVG and path and I took help from following Code
https://itnext.io/reactnative-curved-tabbar-dc62e681c24d
also the github code : https://github.com/alex-melnyk/clipped-tabbar
Hope this is helpful. Thanks

How to make a view 100% window height?

I'm brand new to react native. I'm trying to figure out how to make a box full height.
I have tried to add flex property to both container and view, but the height is not 100%.
export default class LinksScreen extends React.Component {
render() {
return (
<ScrollView style={styles.container}>
<View style={{ flex: 1, backgroundColor: '#fff', flexGrow: 1 }}>
<Text>Hallo</Text>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
padding: 20,
backgroundColor: 'blue',
},
});
You need to wrap the ScrollView with a View that has height. ScrollViews must have a bounded height in order to work. You can read more details about that here: https://facebook.github.io/react-native/docs/scrollview
Do it something like below:
render() {
return (
<View style={styles.container}>
<View style={{height: 80}} >
<ScrollView
...
EDIT
Your code actually works. Maybe you just want to see if your scrollview works when the whole screen is occupied. Try this below and you will see, I simply multiplied the text contents 80 times:
render() {
return (
<ScrollView style={styles.container}>
<View style={{ flex: 1, backgroundColor: "#fff", flexGrow: 1 }}>
{Array(80)
.fill(1)
.map((item, index) => (
<Text>Hallo {index}</Text>
))}
</View>
</ScrollView>
);
}
Remove flex:1
Give height:"100%"
width: "100%"

NativeBase card fitting/scaling the image within the card

First: I have looked at this, but didn't find what I was looking for.
I wanna create something like this
But I have some problems with the resizing of an large image.. I found out that I can fix the pixels by doing inline style and using height and width. But I want it to look good on an iPad as well... What to do?
Here is my code
import React, { Component } from 'react';
import { Image } from 'react-native';
import { List, Card, CardItem, Thumbnail, Text, Button, Icon } from 'native-base';
class ListEquipment extends Component {
constructor() {
super();
}
render () {
return (
<List style={{padding: 5}}
dataArray={this.props.items}
renderRow={(item) =>
<Card >
<CardItem>
<Thumbnail source={require('../img/Robot-96.png')} />
<Text>Card</Text>
<Text note>Bonus Info</Text>
</CardItem>
<CardItem cardBody>
<Image source={require('../img/micscrope.jpg')} />
<Text>
Information goes here..
</Text>
<Button >
<Icon name="ios-beer" />
<Text>Cheers</Text>
</Button>
</CardItem>
</Card>
}
/>
)
}
};
export default ListEquipment;
Are you looking to size the images based on the size of the device?
If so, you can use:
import SCREEN_IMPORT from 'Dimensions'
const SCREEN_WIDTH = SCREEN_IMPORT.get('window').width,
const SCREEN_HEIGHT = SCREEN_IMPORT.get('window').height,
You will then be able to set the width/height inline as a percentage of SCREEN_HEIGHT and SCREEN_WIDTH.
Additionally you will want to consider the pixelRatio, it is recommended to store varying sizes of an image so that downsizing/upscaling will not effect image quality.
var image = getImage({
width: PixelRatio.getPixelSizeForLayoutSize(200),
height: PixelRatio.getPixelSizeForLayoutSize(100),
});
<Image source={image} style={{width: 200, height: 100}} />
Where getImage will return the nearest sized image for the device screen/pixel ratio.
First thing I would do is to wrap the Image on a View. Then, set a height that matches the aspect ratio of the image and then use resizeMode: 'contain'.
Anyway, this is the closest I could get:
<View style={{backgroundColor: 'green', margin: 10, borderColor: 'yellow', borderWidth: 2}}>
<View style={{backgroundColor: 'green', padding: 10, borderBottomColor: 'yellow', borderBottomWidth: 2}}>
<Text style={{fontSize: 20}}>Header</Text>
</View>
<View style={{backgroundColor: 'red'}}>
<View style={{alignItems: 'center', height: 150}}>
<Image source={require('./test.png')} style={{flex: 1, resizeMode: 'contain'}}/>
</View>
<View style={{backgroundColor: 'violet'}}>
<Text style={{color: 'blue'}}>Description</Text>
</View>
</View>
</View>
With a 500x300(px) image this generates:
By using an image with the correct aspect ratio it looks way better: