Animation and flex space-between layout - react-native

I have 3 blocks disposed using justifyContent: 'space-between'.
The bottom block should be animated (bounce in loop) in height for 100 units in the grey area. The problem is I can't edit margins of the bottom block because justifyContent prop causes the middle block moves (first and middle block should be fixed).
import React, { Component } from 'react';
import { StyleSheet, Text, View, Easing, Animated, // Button,
ScrollView } from 'react-native';
import Button from 'react-native-button';
export default class App extends Component {
constructor () {
super()
this.animatedValue = new Animated.Value(0)
this.animate(Easing.bounce)
}
animate (easing) {
this.animatedValue.setValue(0)
Animated.timing(
this.animatedValue,
{
toValue: 1,
duration: 1000,
easing
}
).start( ()=> this.animate(Easing.bounce))
}
render () {
const marginBottom = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 100]
})
return (
<View style={{flex: 1,flexDirection: 'column',alignItems:"center",justifyContent: 'space-between' }}>
<View style={styles.block}><Text>top</Text></View>
<View style={styles.block}>><Text>second</Text></View>
<View style={{textAlign: "center",height:150,backgroundColor:"#555"}}>
<Animated.View style={[styles.block2, {marginBottom} ]}>
<Text style={{position:"absolute"}} >bottom</Text>
</Animated.View>
</View>
</View>
);
}
}
var styles = StyleSheet.create({
block: {
width: 50,
height: 50,
backgroundColor: 'red',
},
block2: {
width: 50,
height: 50,
backgroundColor: 'red',
}
});
https://snack.expo.io/#alfredopacino/animations-easing
To be more clear about what I'm trying to accomplish. It is just this plain and simple animation https://drive.google.com/open?id=1_nunJMjdsAkjvbE4_URc4GIsoDw8M7KN

Just change your marginBottom to marginTop
<View style={{ textAlign: "center", height: 150, backgroundColor: "#555" }}>
<Animated.View style={[styles.block2, { marginTop:marginBottom }]}>//<-changes--
<Text style={{ position: "absolute" }}>bottom</Text>
</Animated.View>
</View>

Related

How to scroll to image[x] in ScrollView at the first time open screen?

How to scroll to image[x] in ScrollView at the first time component load?
I want when we open this screen, ScrollView will scroll to the 4th image.
This is my demo
export default function App() {
const scrollX = useRef(new Animated.Value(0));
const imageRef = createRef(scrollX);
useEffect(() => {
imageRef.current?.scrollTo(new Animated.Value(3));
}, []);
return (
<SafeAreaView style={styles.container}>
<View style={styles.scrollContainer}>
<ScrollView
ref={imageRef}
horizontal={true}
pagingEnabled
showsHorizontalScrollIndicator={false}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: scrollX.current,
},
},
},
],
{ useNativeDriver: false }
)}
scrollEventThrottle={1}
>
{children}
</ScrollView>
</View>
</SafeAreaView>
);
}
scrollTo accept separate compoenents. You don't need to use animated component and the onScroll method for react scrollview. Just enter {x: value, animated: true} in scrollTo as it accepts object
Here is the code updated from snack:
import React, { useRef, useEffect, createRef } from "react";
import {
SafeAreaView,
ScrollView,
Text,
StyleSheet,
View,
ImageBackground,
Animated,
Dimensions,
} from "react-native";
const images = new Array(6).fill(
"https://images.unsplash.com/photo-1556740749-887f6717d7e4"
);
export const WIDTH = Dimensions.get("window").width;
export default function App() {
const imageRef = useRef();
useEffect(() => {
imageRef.current?.scrollTo({x: WIDTH * 3});
},[]);
return (
<SafeAreaView style={styles.container}>
<View style={styles.scrollContainer}>
<ScrollView
ref={imageRef}
horizontal={true}
pagingEnabled
showsHorizontalScrollIndicator={false}
>
{images.map((image, imageIndex) => {
return (
<View
style={{
width: WIDTH,
height: 250,
}}
key={imageIndex}
>
<ImageBackground source={{ uri: image }} style={styles.card}>
<View style={styles.textContainer}>
<Text style={styles.infoText}>
{"Image - " + imageIndex}
</Text>
</View>
</ImageBackground>
</View>
);
})}
</ScrollView>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
scrollContainer: {
height: 300,
alignItems: "center",
justifyContent: "center",
},
card: {
flex: 1,
marginVertical: 4,
marginHorizontal: 16,
borderRadius: 5,
overflow: "hidden",
alignItems: "center",
justifyContent: "center",
},
textContainer: {
backgroundColor: "rgba(0,0,0, 0.7)",
paddingHorizontal: 24,
paddingVertical: 8,
borderRadius: 5,
},
infoText: {
color: "white",
fontSize: 16,
fontWeight: "bold",
},
});

Animation in header in react-native

Hi I have an image in my HeaderRight and I want to animate it with an effect of zoom-in/zoom-out. How can I use the Animated library in order to work it out ?
Thanks !
let headerRight = (
<TouchableOpacity onPress = {() => {this.openDialog(true)} }>
<View style={{ flexDirection:'row', justifyContent: 'space-around'}}>
<View style={{borderRadius: 30, padding:4, overflow: 'hidden', alignItems: 'center',backgroundColor:'white', justifyContent: 'center', marginRight:20 }}>
<Image
style={{ width:28, height: 28}}
source={require("../Images/icone-sonnerie.png")}/>
</View>
</View>
</TouchableOpacity>
);
You can implement animated touchableOpacity like this
create class
import React from 'react'
import {
Animated,
TouchableOpacity
} from 'react-native'
const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity)
class AnimatedTouchableOpacity extends React.Component {
state = {
scale: new Animated.Value(1)
}
ScaleTheTouchable(toValue, withDuration) { //Call this function in this class in onPress or another event call you want with your scale (1 is the normal size) and duration in miliseconds
Animated.timing(
this.state.scale,
{
toValue: toValue,
duration: withDuration
},
).start()
}
render() {
return (
<AnimatedTouchable
style = {[
{
transform: [{
scale: this.state.scale
}]
},
this.props.style
]}
>
{this.props.children}//Your image or another view inside button goes here...
</AnimatedTouchable>
)
}
}
then you can call it like this
let headerRight = (
<AnimatedTouchableOpacity style = {{}} >
<View style={{ flexDirection:'row', justifyContent: 'space-around'}}>
<View style={{borderRadius: 30, padding:4, overflow: 'hidden', alignItems: 'center',backgroundColor:'white', justifyContent: 'center', marginRight:20 }}>
<Image
style={{ width:28, height: 28}}
source={require("../Images/icone-sonnerie.png")}/>
</View>
</View>
</AnimatedTouchableOpacity>
)

How do I make TouchableOpacity only clickable within its shape on mobile?

On web, shaping a TouchableOpacity makes it so only the shape is clickable, however on mobile the entire "box" surrounding the shape is clickable. Is there any way at all to make it so just the shape is clickable?
I have tried shaping the view and setting the style on both View and TouchableOpacity to overflow: 'hidden' but this also fails to contain the area which is touchable.
import React, { Component } from 'react';
import { StyleSheet, TouchableOpacity, Text, View } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
onPress = () => {
this.setState({
count: this.state.count + 1,
});
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={this.onPress}>
<Text> Touch Here </Text>
</TouchableOpacity>
<View style={[styles.countContainer]}>
<Text style={[styles.countText]}>
{this.state.count !== 0 ? this.state.count : null}
</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 10,
overflow: 'hidden',
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
borderRadius: 640,
height: 320,
width: 320,
overflow: 'hidden',
},
countContainer: {
alignItems: 'center',
padding: 10,
},
countText: {
color: '#FF00FF',
},
});
Here's a snack example of my problem

Hide TabNavigators and Header on Scroll

I want to hide the Header and the TabNavigator tabs onScroll. How do I do that? I want to hide them onScroll and show them on ScrollUp. My code:
import React, { Component } from 'react';
import { View, Text, ScrollView, StyleSheet, TouchableOpacity} from 'react-native';
class ScrollTest extends Component {
render(){
const { params } = this.props.navigation.state;
return(
<View style={styles.container}>
<ScrollView>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
container:{
flex:1, padding:5
},
newView:{
height: 200, backgroundColor:'green', margin:10
}
})
export default ScrollTest;
I checked this link for Animated API but not able to figureout how to implement it in onScoll?
So the header HomeScreen and the tabs Tab1 and Tab2 should hide on scroll and show when scrolled up. How do I do that?
Please help getting started on this.
Many thanks.
I was also stuck with the same animation thing, I tried this code for maximizing and minimizing the header using the Animated API of react-native.
You can also do the same for showing and hiding it.
import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, Image,Animated } from 'react-native';
const HEADER_MAX_HEIGHT = 200;// set the initial height
const HEADER_MIN_HEIGHT = 60;// set the height on scroll
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
};
}
render() {
const headerHeight = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [HEADER_MAX_HEIGHT,HEADER_MIN_HEIGHT],
extrapolate: 'clamp',
});
return(
<View style={{flex: 1}}>
<ScrollView
scrollEventThrottle={1}
onScroll={Animated.event(
[{nativeEvent:
{contentOffset: {y: this.state.scrollY}}}]
)}>
<View style={styles.container}>
<Text style={styles.paragraph}>hello</Text>
<Image source={{uri: "https://static.pexels.com/photos/67843/splashing-splash-aqua-water-67843.jpeg"}} style={styles.imageStyle}/>
<Image source={{uri: "https://www.elastic.co/assets/bltada7771f270d08f6/enhanced-buzz-1492-1379411828-15.jpg" }}
style={styles.imageStyle}/>
</View>
</ScrollView>
<Animated.View style={[styles.footer, {height: headerHeight}]}>
<View style={styles.bar}>
<Text>text here</Text>
</View>
</Animated.View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 24,
backgroundColor: '#ecf0f1',
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
imageStyle: {
height: 360,
width: '100%',
},
footer: {
position:'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: 'red',
},
bar: {
alignItems: 'center',
justifyContent: 'center',
},
});
Hope this helps someone.
I resolved for my case, hope this will be helpful
import React from 'react';
import {
Animated,
Text,
View,
StyleSheet,
ScrollView,
Dimensions,
RefreshControl,
} from 'react-native';
import Constants from 'expo-constants';
import randomColor from 'randomcolor';
const HEADER_HEIGHT = 44 + Constants.statusBarHeight;
const BOX_SIZE = Dimensions.get('window').width / 2 - 12;
const wait = (timeout: number) => {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
};
function App() {
const [refreshing, setRefreshing] = React.useState(false);
const scrollAnim = new Animated.Value(0);
const minScroll = 100;
const clampedScrollY = scrollAnim.interpolate({
inputRange: [minScroll, minScroll + 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
});
const minusScrollY = Animated.multiply(clampedScrollY, -1);
const translateY = Animated.diffClamp(minusScrollY, -HEADER_HEIGHT, 0);
const onRefresh = React.useCallback(() => {
setRefreshing(true);
wait(2000).then(() => {
setRefreshing(false);
});
}, []);
return (
<View style={styles.container}>
<Animated.ScrollView
contentContainerStyle={styles.gallery}
scrollEventThrottle={1}
bounces={true}
showsVerticalScrollIndicator={false}
style={{
zIndex: 0,
height: '100%',
elevation: -1,
}}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollAnim } } }],
{ useNativeDriver: true }
)}
overScrollMode="never"
contentInset={{ top: HEADER_HEIGHT }}
contentOffset={{ y: -HEADER_HEIGHT }}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}>
{Array.from({ length: 20 }, (_, i) => i).map((uri) => (
<View style={[styles.box, { backgroundColor: 'grey' }]} />
))}
</Animated.ScrollView>
<Animated.View style={[styles.header, { transform: [{ translateY }] }]}>
<Text style={styles.title}>Header</Text>
</Animated.View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
gallery: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 4,
},
box: {
height: BOX_SIZE,
width: BOX_SIZE,
margin: 4,
},
header: {
flex: 1,
height: HEADER_HEIGHT,
paddingTop: Constants.statusBarHeight,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: randomColor(),
},
title: {
fontSize: 16,
},
});
export default App;
checkout on Expo https://snack.expo.io/#raksa/auto-hiding-header

How to place buttons on what i want to place in react native?

before , I had problem with full size of width(100%)
In react native, width : 100% is not supported..
so I use var width = Dimensions.get('window').width; //full width this code.
But in this case, I want to place buttons on what I want to place like
in this photo
I want to place the hand!! buttons on the hand of body.
like width, in react native don't support % ..
so I want to place the buttons whatever the size of phone changes
this is my all codes
const MK = require('react-native-material-kit');
import React, { Component} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
Dimensions,
ScrollView
} from 'react-native';
const {
MKButton,
MKColor,
} = MK;
const ColoredButton = MKButton.button()
.withBackgroundColor(MKColor.Amber)
.build();
const Fab = MKButton.coloredFab()
.withBackgroundColor(MKColor.Teal)
.build();
class Test extends Component {
render() {
return (
<ScrollView style={styles.scrollView}>
<Image
style={styles.Bodystyle}
resizeMode='contain'
source={require('./img/body.png')}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text style={styles.instructions}>
Shake or press menu button for dev menu
</Text>
<View style={styles.row}>
<ColoredButton
onPress={() => {
console.warn('hi, raised button!');
}}
>
<Text pointerEvents="none"
style={styles.Buttontext}>
Hand!!
</Text>
</ColoredButton>
<Fab>
<Text style={styles.Buttontext}>
Hand!!
</Text>
</Fab>
</View>
</Image>
</ScrollView>
);
}
}
var width = Dimensions.get('window').width; //full width
var height = Dimensions.get('window').height; //full height
const styles = StyleSheet.create({
scrollView:{
flex:1,
},
row :{
flexDirection:'row',
},
container: {
flexDirection: 'column',
alignItems: 'center',
backgroundColor: '#F5FCFF',
flex:1
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
Buttonstyle:{
justifyContent: 'center',
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
Bodystyle:{
flexDirection:'column',
top: 0,
left: 0,
bottom: 0,
right: 0,
width: width,
height: height,
},
Buttontext:{
textAlign: 'center',
color: '#000000',
fontSize: 10,
}
});
AppRegistry.registerComponent('Test', () => Test);
I can be as simple as
const getPosition = (left, top, width, height) => ({
left: width * left,
top: height * top
})
For example
button: {
...(getPosition(0.7, 0.8, imageWidth, imageHeight))
}