React Native Animated component gets covered on panning - javascript

Works fine on iOS:
Gets covered outside of box on Android:
I read somewhere that zIndex only affects sibling components, though this works on iOS.
How should I go about fixing it on Android?
https://snack.expo.io/#riwu/animated-zindex
import React from 'react';
import { View, Animated, PanResponder } from 'react-native';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
pos: new Animated.ValueXY(),
};
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: Animated.event([
null,
{
dx: this.state.pos.x,
dy: this.state.pos.y,
},
]),
});
}
render() {
return (
<View
style={{
marginTop: 20,
borderWidth: 1,
padding: 5,
width: 50,
height: 50,
}}
>
<Animated.Image
{...this.panResponder.panHandlers}
style={[this.state.pos.getLayout(), { flex: 1, zIndex: 1 }]}
source={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png' }}
/>
</View>
);
}
}
export default App;

For the zIndex to take effect, you need to make the position of the elements as absolute, to overlap each other.
Therefore the resulting code will look like this
<View >
<View
style={{
marginTop: 20,
borderWidth: 1,
width: 50,
height: 50,
position: 'absolute',
zIndex: 1
}}
>
</View>
<Animated.Image
{...this.panResponder.panHandlers}
style={[this.state.pos.getLayout(), { marginTop: 25, marginLeft: 5, height: 40, width: 40, position: 'absolute', zIndex: 2}]} //...Adding appropriate margin, height and width as per parent element
source={{ uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png' }}
/>
</View>
Here's the sample snack demo

Related

flexDirection is causing images to disappear

so I have my images displaying one after another like I want them to. Instead of them being vertical though, I would like them to display horizontally. Originally, I was trying to use flexDirection: 'row' while then setting scrollview to horizontal to achieve this but flexDirection seems to make the images disappear all together.
I was putting flexDirection in the View at line 60. I also tried creating another parent view to hold flexDirection but that gave me the same result.
Please copy and paste this into snack.expo.io to see exactly what I am referring to!
Thank you for any insight at all!
import React, { useState } from 'react';
import {
Pressable,
StyleSheet,
Text,
View,
useWindowDimensions,
Dimensions,
Image,
Animated,
PanResponder,
TouchableOpacity,
ScrollView,
ImageBackground,
Platform,
} from 'react-native';
import { SearchBar } from 'react-native-elements';
import {
scale,
verticalScale,
moderateScale,
ScaledSheet,
} from 'react-native-size-matters';
import { MaterialCommunityIcons } from '#expo/vector-icons';
const screenResolutions = () => {
var SCREEN_HEIGHT = useWindowDimensions().width;
var SCREEN_WIDTH = useWindowDimensions().height;
};
const images = [
{ id: '1', uri: require('./assets/snack-icon.png'), text: 'Test' },
{ id: '2', uri: require('./assets/snack-icon.png') /*text: "Test"*/ },
{ id: '3', uri: require('./assets/snack-icon.png') /*text: "Test"*/ },
{ id: '4', uri: require('./assets/snack-icon.png') /*text: "Test"*/ },
];
const pressableTest = () => {
let textlog = '';
const [state, setState] = useState(0);
};
export default class Home extends React.Component {
renderImages = () => {
return images.map((item, i) => {
return (
<View
style={{
paddingLeft: scale(10),
paddingRight: scale(10),
paddingBottom: scale(15),
}}>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('VenueDetails')}>
<ImageBackground
source={item.uri}
style={{
width: '100%',
height: scale(225),
shadowColor: '#000',
shadowOffset: { width: 1, height: 4 },
shadowOpacity: 1,
}}
imageStyle={{ borderRadius: 10 }}>
<View
style={{
position: 'absolute',
bottom: 10,
left: 10,
justifyContent: 'flex-start',
alignItems: 'flex-start',
}}>
<Text style={styles.name}>Name</Text>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={styles.category}>Category</Text>
<Text style={styles.dot}>⬤</Text>
<Text style={styles.money}>$$</Text>
<Text style={styles.dot}>⬤</Text>
<Text style={styles.starRating}>★★★</Text>
</View>
</View>
</ImageBackground>
</TouchableOpacity>
</View>
);
});
};
state = {
search: '',
};
updateSearch = (search) => {
this.setState({ search });
};
render() {
const { search } = this.state;
return (
<ScrollView
style={{ flex: 1, backgroundColor: '#272933', horizontal: 'true' }}>
<View style={{ flex: 1, marginTop: 15 }}>{this.renderImages()}</View>
</ScrollView>
);
}
}
const styles = ScaledSheet.create({
starRating: {
color: 'white',
fontSize: '20#s',
textShadowOffset: { width: 2, height: 2 },
textShadowRadius: 2,
textShadowColor: '#000',
},
category: {
color: 'white',
fontSize: '20#s',
textShadowOffset: { width: 2, height: 2 },
textShadowRadius: 2,
textShadowColor: '#000',
},
name: {
fontWeight: 'bold',
color: 'white',
fontSize: '25#s',
textShadowOffset: { width: 2, height: 2 },
textShadowRadius: 2,
textShadowColor: '#000',
},
dot: {
color: 'white',
fontSize: '5#s',
paddingLeft: '5#s',
paddingRight: '5#s',
textShadowOffset: { width: 2, height: 2 },
textShadowRadius: 2,
textShadowColor: '#000',
},
money: {
color: 'white',
fontSize: '20#s',
},
});
i dont use react , but your image view ( the one you return from render images ) should have a width or a flex-basis prop , and you container (scrollview > view) should have display : flex and width of 100vw
i made it work : here
.flex-box {
width : 100vw ; // or %
display : flex ;
overflow-x : scroll ;
flex-wrap : no-wrap ;
}
.flex-item {
width : 200px ; // or % or flex-basis with no shrink or min-width
}
Edit : i changed to no-wrap and fixed width instead of basis to make it scrollable horizentally .
if a container is set to 100% flex no-wrap , and its children have a fixed width they will overflow horizontally in web we simply put overflow-x : scroll ; to make it scrollable and view all overflowed items .

Why is the screen not clickable when changing backgroundColor on react-native to transparent?

I have a code which will pop up and close the popup with a little animation in it. The problem arises when I add color to the background of the popup. Because when the popup is closed and the background color has changed, the screen can't be clicked.
I thought about removing the background, but I didn't know how. I think setting backgroundColor to transparent will solve my problem. But it only removes the previous color and makes the screen not clickable.
Previously I tried to use if else to close the background, but the animation on the application doesn't even work anymore.
Here is the code I attached:
import React, { useState, useRef } from 'react';
import { Text, View, TouchableHighlight, TouchableWithoutFeedback, Animated, KeyboardAvoidingView, Dimensions, ScrollView } from 'react-native';
const testScreen = () => {
const windowHeight = Dimensions.get('window').height;
const bounceValue = useRef(new Animated.Value(windowHeight)).current;
const [reportBackgroundColor, setReportBackgroundColor] = useState("");
const _toggleSubviewAppear = () => {
var toValue = 0;
Animated.spring(
bounceValue,
{
toValue: toValue,
velocity: 3,
tension: 2,
friction: 8,
}
).start();
setReportBackgroundColor("rgba(0, 0, 0, 0.2)");
};
const _toggleSubviewDisappear = () => {
var toValue = windowHeight;
Animated.spring(
bounceValue,
{
toValue: toValue,
velocity: 3,
tension: 2,
friction: 8,
}
).start();
};
console.log(JSON.stringify(reportBackgroundColor));
return (
<View style={{ flex: 1, backgroundColor: 'white', alignItems: 'center', justifyContent: 'center' }}>
<TouchableHighlight onPress={() => {
_toggleSubviewAppear();
}}>
<View style={{borderRadius: 100, height: 50, width: 50, backgroundColor: 'pink', justifyContent: 'center', alignItems: "center"}}>
<Text>
Click to show
</Text>
</View>
</TouchableHighlight>
<View style={{ backgroundColor: reportBackgroundColor, flex: 1, top: 0, bottom: 0, right: 0, left: 0, position: 'absolute' }}>
<Animated.View style={{ transform: [{ translateY: bounceValue }], flex: 1, zIndex: 1000, position: 'absolute', bottom: 0, left: 0, right: 0 }} >
<KeyboardAvoidingView style={{ flex: 1 }}>
<View style={{ borderColor: "#E0E0E0", borderWidth: 1, borderTopLeftRadius: 40, borderTopRightRadius: 40, backgroundColor: 'white' }}>
<ScrollView showsVerticalScrollIndicator={false}>
<TouchableWithoutFeedback onPress={() => {
_toggleSubviewDisappear();
setReportBackgroundColor("transparent");
}}>
<View style={{ position: 'absolute', right: 27, top: 27, justifyContent: 'center', alignItems: 'center', borderRadius: 100, backgroundColor: 'white', borderWidth: 1, borderColor: '#E0E0E0', height: 29, width: 29 }}>
<Text>
X
</Text>
</View>
</TouchableWithoutFeedback>
<Text style={{ marginTop: 27, alignSelf: "center", fontSize: 19, color: "#333333" }}>Laporkan Penjual</Text>
<View style={{ marginBottom: 25 }}></View>
</ScrollView>
</View>
</KeyboardAvoidingView>
</Animated.View>
</View>
</View>
)
}
You are changing Animated parent view's background color, although you change it to transparent, it still there so that couldn't click the bottom view, is there you wand to change backgroundcolor? It seems have to change this one? backgroundColor: 'white' And then confirm the animated view truly closed, and the button should be clickable.

React native Animated undefined is not an object (evaluating 'u.stopTracking')

I'm having the following problem: "undefined is not an object (evaluating 'u.stopTracking')".
It happens when on Expo I update a props, I tried to use on componentWillReceiveProps, stopAnimation() and stopTracking(), but I could not.
Link expo: Here
To make the error appear, just click on the image of the central player.
Can someone give me a hand?
App:
import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground } from 'react-native';
import { Constants } from 'expo';
import Album from './Album';
import Track from './Track';
const State = ['normal', 'transparent', 'big'];
export default class App extends React.Component {
constructor() {
super();
this.state = {
type: 0,
};
}
render() {
let { type } = this.state;
return (
<View style={styles.container}>
<ImageBackground
source={{
uri:
'https://i.pinimg.com/originals/62/6f/84/626f84c40696c1308a77fd8331e12b3e.jpg',
}}
imageStyle={{ borderRadius: 4 }}
style={{
alignItems: 'center',
justifyContent: 'center',
height: 400,
width: 400,
}}>
<Album
type={State[type]} //normal,transparent,big
title={Track.name}
artist={Track.artists[0].name}
cover={Track.album.images[0].url}
onPress={() => {
type = ++type % 3;
this.setState({ type });
}}
/>
</ImageBackground>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#fff',
},
});
Album:
import * as React from 'react';
import {
Text,
View,
StyleSheet,
ImageBackground,
Animated,
TouchableOpacity,
} from 'react-native';
const size = 40;
export default class Album extends React.Component {
constructor(props) {
super(props);
this.min = size / 4;
this.max = size / 2;
this.heightCenter = new Animated.Value(this.min);
this.heightLateral = new Animated.Value(size / 2);
/*this.state = {
heightCenter: new Animated.Value(this.min),
heightLateral: new Animated.Value(size / 2),
};*/
}
animateBar = (el, value) => {
var newValue = value == this.max ? this.min : this.max;
Animated.timing(el, {
toValue: value,
}).start(() => this.animateBar(el, newValue));
};
onPress = e => {
return this.props.onPress(e);
};
componentDidMount() {
console.log(this.heightCenter)
this.animateBar(this.heightCenter, this.min);
this.animateBar(this.heightLateral, this.max);
}
componentWillReceiveProps(nextProps) {
if (nextProps.type !== this.props.type) {
console.log('componentWillReceiveProps');
//this.state.heightCenter.stopAnimation();
//this.state.heightLateral.stopAnimation();
//Animated.stopTracking();
//Animated.timing(this.heightCenter).stopTracking();
//Animated.timing(this.heightLateral).stopTracking();
/*this.state.heightCenter.stopTracking();
this.state.heightLateral.stopTracking();
this.state.heightCenter.stopAnimation();
this.state.heightLateral.stopAnimation();*/
//this.heightCenter = {};
//this.heightLateral = null;
//this.heightCenter.stopTracking();
//this.heightLateral.stopTracking();
//this.state.heightCenter.stopAnimation();
//this.state.heightLateral.stopAnimation();
console.log(this.heightCenter)
}
}
componentDidUnmount() {
console.log('componentDidUnmount');
//Animated.timing(this.heightCenter).stop();
//Animated.timing(this.heightLateral).stop();
}
componentDidUpdate() {
this.animateBar();
}
render() {
let { type, title, artist, cover } = this.props;
let barWidthCenter = {
height: this.heightCenter,
};
let barWidthLateral = {
height: this.heightLateral,
};
if (type != 'normal' && type != 'transparent' && type != 'big')
type = 'transparent';
let backgroundColor =
type == 'normal' ? 'rgba(255,255,255,1)' : 'rgba(255,255,255,0.5)';
let color = type == 'normal' ? '#000' : '#fff';
if (type == 'big')
return (
<TouchableOpacity onPress={() => this.onPress()}>
<View
style={{
alignItems: 'center',
justifyContent: 'center',
}}>
<ImageBackground
source={{
uri: cover,
}}
imageStyle={{ borderRadius: 4 }}
style={{
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'flex-start',
height: 200,
width: 200,
}}>
<View
style={{
borderRadius: 4,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(0,0,0,0.3)',
padding: 5,
height: 40,
width: 40,
margin: 5,
}}>
<Animated.View
style={[
{
backgroundColor: 'rgba(255,255,255,1)',
width: 5,
borderRadius: 5 / 2,
margin: 2,
},
barWidthLateral,
]}
/>
<Animated.View
style={[
{
backgroundColor: 'rgba(255,255,255,1)',
width: 5,
borderRadius: 5 / 2,
margin: 2,
},
barWidthCenter,
]}
/>
<Animated.View
style={[
{
backgroundColor: 'rgba(255,255,255,1)',
width: 5,
borderRadius: 5 / 2,
margin: 2,
},
barWidthLateral,
]}
/>
</View>
</ImageBackground>
<View style={{ paddingLeft: 12, paddingRight: 12 }}>
<Text style={{ fontWeight: 'bold', color: '#fff' }}>{title}</Text>
<Text style={{ color: '#fff' }}>{artist}</Text>
</View>
</View>
</TouchableOpacity>
);
return (
<TouchableOpacity onPress={() => this.onPress()}>
<View
style={{
backgroundColor: backgroundColor,
flexDirection: 'row',
justifyContent: 'center',
borderRadius: 4,
padding: 4,
}}>
<ImageBackground
source={{
uri: cover,
}}
imageStyle={{ borderRadius: 4 }}
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
height: size,
width: size,
}}>
<Animated.View
style={[
{
backgroundColor: 'rgba(255,255,255,1)',
width: 5,
borderRadius: 5 / 2,
margin: 2,
},
barWidthLateral,
]}
/>
<Animated.View
style={[
{
backgroundColor: 'rgba(255,255,255,1)',
width: 5,
borderRadius: 5 / 2,
margin: 2,
},
barWidthCenter,
]}
/>
<Animated.View
style={[
{
backgroundColor: 'rgba(255,255,255,1)',
width: 5,
borderRadius: 5 / 2,
margin: 2,
},
barWidthLateral,
]}
/>
</ImageBackground>
<View style={{ paddingLeft: 12, paddingRight: 12 }}>
<Text style={{ fontWeight: 'bold', color }}>{title}</Text>
<Text style={{ color }}>{artist}</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
I see it's been a while you asked this question. I don't know how you solved this problem but I've had the same error:
"undefined is not an object (evaluating 'u.stopTracking')"
because of the code here:
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
elementPositionX: 0,
target: null,
marginLeft: new Animated.Value(0),
};
It was happening because I had put the Animated Value in the state. It should have defined out of the state, as a property of the component class, like this:
export default class App extends React.Component {
constructor(props) {
super(props);
this.marginLeft= new Animated.Value(0);
this.state = {
elementPositionX: 0,
target: null,
};
The documentation about Animated API is so poor, so I am not sure why but this solved my problem.
EDIT:
I have managed to place it in the state somehow, and it works without giving the former error. However, I need to use this code to change the animated value: this.state.marginLeft2.setValue(amount); and this is actually changing the state directly - without using .setState(). It doesn't seem good to me.

Prevent image from overflowing when scaling it's size inside circular view

I am trying to create a circular profile image with the following code. The challenge is that I need to scale up the image when it is inside a circular view. On IOS this works fine as the extra image is cut off by the containing view, but on Android it simply overflows.
import React, { Component } from 'react'
import { View, Image } from 'react-native'
class Example extends Component {
render () {
return (
<View
style={{
borderRadius: 150,
borderWidth: 10,
borderColor: 'red',
width: 300,
height: 300,
}}
>
<Image
style={{
borderRadius: 150,
width: 280,
height: 280,
transform: [{
scale: 1.3,
}],
}}
resizeMode='contain'
source={{ uri: 'http://blog.ramboll.com/fehmarnbelt/wp-content/themes/ramboll2/images/profile-img.jpg' }}
/>
</View>
)
}
}
How it looks with scale on Android:
How it looks like without scale:
How I would like it to look with scale:
Giving overflow: 'hidden' as style to the parent view will solve the issue.
<View
style={{
borderRadius: 150,
borderWidth: 10,
borderColor: 'red',
overflow: 'hidden',
width: 300,
height: 300,
}}
>

React Native Animations singleValue.stopTracking is not a function

I try to implement a sliding bar and bond the sliding animation to a TouchableOpacity.
I initialized the parameter as sliderPosition: new Animated.Value(0)
the onPress function is :
onPress: function(event){
Animated.timing(this.state.sliderPosition, {
toValue: 202.5,
duration: 100,
easing: Easing.linear,
}).start();
},
I kept getting this error
[tid:com.facebook.react.RCTExceptionsManagerQueue] Unhandled JS Exception: singleValue.stopTracking is not a function. (In 'singleValue.stopTracking()', 'singleValue.stopTracking' is undefined)
layout for the slider is:
<View style = {styles.sliderContainer}>
<Animated.View style = {[styles.slider, {marginLeft:this.state.sliderPosition}]}>
</Animated.View>
</View>
styles:
sliderContainer: {
position: 'absolute',
top: 138,
left: 0,
right: 0,
height: 5,
backgroundColor: '#E15668',
shadowRadius: 1,
shadowOpacity: 0.5,
shadowColor: 'gray',
shadowOffset: {width: 0, height: 2},
opacity: 0.9
},
slider: {
marginTop: 0,
backgroundColor: '#FCC31B',
width: 120,
height: 5,
},
did I do something wrong?
Are you sure that sliderPosition property on your state remains an instance of Animated.Value? That error you're getting speaks to that being the issue. Here is a complete example using your code snippets that works as you'd expect. Try this out and if the snippet doesn't help solve your issue, please post more of your surrounding code to lend more context:
import React from 'react';
import {
Animated,
AppRegistry,
Easing,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
class MyApp extends React.Component {
constructor(props) {
super(props);
this.onPress = this.onPress.bind(this);
this.state = {
sliderPosition: new Animated.Value(0)
}
}
onPress(event){
Animated.timing(this.state.sliderPosition, {
toValue: 202.5,
duration: 100,
easing: Easing.linear,
}).start();
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this.onPress}>
<Text>Animate It</Text>
</TouchableOpacity>
<View style = {styles.sliderContainer}>
<Animated.View style = {[styles.slider, {marginLeft:this.state.sliderPosition}]}>
</Animated.View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
sliderContainer: {
position: 'absolute',
top: 138,
left: 0,
right: 0,
height: 5,
backgroundColor: '#E15668',
shadowRadius: 1,
shadowOpacity: 0.5,
shadowColor: 'gray',
shadowOffset: {width: 0, height: 2},
opacity: 0.9
},
slider: {
marginTop: 0,
backgroundColor: '#FCC31B',
width: 120,
height: 5,
}
});
AppRegistry.registerComponent('MyApp', () => MyApp);

Categories

Resources