Passing an image to webview in react-native - react-native

I'm making a simple app that requires the user to select an image, and that image needs to be passed on to a Webview window.
Now I have multiple problems:
1.The image needs to be passed on to a css "background-image" element
I can't seem to rename the file of the image that the user inputs
I can't relocate the image to the app's resources folder.
So here is the code for the image input:
state = {
ImageSource: null,
};
selectPhotoTapped() {
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
title: 'Image Picker',
storageOptions: {
skipBackup: true,
path:'data/data/fiftyoff/pictures',
}
};
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled photo picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
var ImagePicked= {path:response.path}
let source = { uri: response.uri };
// You can also display the image using data:
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
module.exports=ImagePicked
this.setState({
ImageSource: source
});
}
});
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
<View style={styles.ImageContainer}>
{ this.state.ImageSource === null ? <Text>Select a Photo</Text> :
<Image style={styles.ImageContainer} source={this.state.ImageSource} />
}
</View>
</TouchableOpacity>
</View>
And here's the CSS where the image needs to be passed to (where image1 is):
.app-picture {
border: 2px solid #893579;
background-position: center;
background-size: cover;
border-radius: 80px;
width: 80px;
height: 80px;
margin: 0 0 1em 0;
top: 68.4714px;
display: block;
position: absolute;
right: 5%;
display: none;
background-image: url("image1.jpg")

Related

How can i control Offset in Reactnative Animation?

I made some code based on your lecture.
When onPanResponderRelease is executed, if dx<-50, goLeft.start() is used to move toValue: -200.
I also refreshed the position using position.flattenOffset(); In onPanResponderGrant, I saved the position value using setOffset.
However, when goLeft.start() is executed and the tovalue has shifted by -200 and the card is touched again, onPanResponderGrant starts at -200 but ,the position is set to -400 and the card starts at an entirely different position.
How can I fix the code so that after goLeft.start() is executed, the touch will start at -200?
this is my code
import React, { useRef, useState } from "react";
import { Animated, PanResponder, Text, View } from "react-native";
import styled from "styled-components/native";
import { Ionicons } from "#expo/vector-icons";
import icons from "./icons";
const Container = styled.View`
flex: 1;
justify-content: center;
align-items: center;
background-color: #00a8ff;
`;
const Card = styled(Animated.createAnimatedComponent(View))`
background-color: white;
width: 100px;
height: 100px;
justify-content: center;
align-items: center;
border-radius: 12px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
position: absolute;
`;
const Btn = styled.TouchableOpacity`
margin: 0px 10px;
`;
const BtnContainer = styled.View`
flex-direction: row;
flex: 1;
`;
const CardContainer = styled.View`
flex: 3;
justify-content: center;
align-items: center;
`;
export default function App() {
const [left, setLeft] = useState(false);
// Values
const position = useRef(new Animated.Value(0)).current;
// Animations
const goCenter = Animated.spring(position, {
toValue: 0,
useNativeDriver: true,
});
const goLeft = Animated.spring(position, {
toValue: -200,
tension: 5,
useNativeDriver: true,
restDisplacementThreshold: 100,
restSpeedThreshold: 100,
});
const goRight = Animated.spring(position, {
toValue: 500,
tension: 5,
useNativeDriver: true,
});
// Pan Responders
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderGrant: () => {
console.log("Grant", position._value);
position.setOffset(position._value);
position.flattenOffset();
// position.addListener(() => {});
},
onPanResponderMove: (_, { dx }) => {
console.log("Move:", dx);
position.addListener(() => {});
position.setValue(dx);
// position.addListener(() => {});
},
onPanResponderRelease: (_, { dx }) => {
console.log("Release:", dx);
if (dx < -30) {
console.log("!!!");
goLeft.start();
position.flattenOffset();
} else {
position.flattenOffset();
}
},
})
).current;
position.addListener(() => console.log("p:", position));
// State
const [index, setIndex] = useState(0);
const onDismiss = () => {
// position.setValue(-100);
// Animated.timing(position, { toValue: -60, useNativeDriver: true }).start();
};
const closePress = () => {
console.log("222");
goLeft.start(onDismiss);
};
const checkPress = () => {
console.log("111");
goRight.start(onDismiss);
};
return (
<Container>
<CardContainer>
<Card
{...panResponder.panHandlers}
style={{
transform: [{ translateX: position }],
}}
>
<Ionicons color="#192a56" size={98} />
</Card>
</CardContainer>
<BtnContainer>
<Btn onPress={closePress}>
<Ionicons name="close-circle" color="white" size={58} />
</Btn>
<Btn onPress={checkPress}>
<Ionicons name="checkmark-circle" color="white" size={58} />
</Btn>
</BtnContainer>
</Container>
);
}

Image is not shown after image is selected from react-native image-picker

I am developing an application in which i need to upload an image from phone camera and also from gallery . camera & gallery is not showing image inside image tag.
here is my code
function profile({ route,navigation }) {
const [imageUri, setimageUri] = useState('');
const openCamera = () => {
let options={
storageOptions: {
path: 'images',
mediaType: 'photo',
},
};
launchCamera(options, response => {
console.log("response =", response);
if(response.didCancel){
console.log('user cancelled image picker');
}else if(response.error){
console.log('Image picker Error:', response.error);
}else if(response.customButton){
console.log('User taped cutom button:', response.customButton);
}else{
const source = {uri: 'data: image/jpeg;base64,'+ response.base64 };
setimageUri(source);
}
});
}
and this is image view code
<Image
source={imageUri}
style={{
height: 100,
width: 100,
borderRadius: 100,
borderWidth: 2,
borderColor: 'black',
alignSelf: 'center',
}}
/>
Try this,It will help you
function profile({ route,navigation }) {
const [imageUri, setimageUri] = useState('');
const openCamera = () => {
let options={
storageOptions: {
path: 'images',
mediaType: 'photo',
},
};
launchCamera(options, response => {
console.log("response =", response);
if(response.didCancel){
console.log('user cancelled image picker');
}else if(response.error){
console.log('Image picker Error:', response.error);
}else if(response.customButton){
console.log('User taped cutom button:', response.customButton);
}else{
setimageUri(response.assets[0].uri);
}
});
}
<Image
source={{ uri: imageUri }}
style={{
height: 100,
width: 100,
borderRadius: 100,
borderWidth: 2,
borderColor: 'black',
alignSelf: 'center',
}}
/>
response will give you assets array you can access image uri as response.assets[0].uri.

React native Reanimated Conditional Animated View Movement

I am really new to React-native-reanimated. I am trying to create one custom bottom-sheet like this app. I am using PanGestureHandler from react-native-gesture-handler for move the Animated View to go up and down. For gestureHandler I am using useAnimatedGestureHandler props from react-native-reanimated. I want to move the Animated View from start point to middle screen and bottom of screen. This is My Bottom sheet start point image, when scroll the card down it should come middle of the screen like this image, again scroll down the card it will come bottom like this image.
I am having difficulties with the conditional useAnimatedGestureHandler onEnd movement. Currently I am tracking onEnd's event.translationY and make a condition out of it.
This is how it works currently:
When the App start, the Animated View is top of the screen, if I move the card scroll to bottom it goes middle of the screen and it does not go down from middle of the screen, I can move it to up from middle of the screen or if I scroll hard to bottom it goes all the way to bottom and if I try scroll the View up it does not go middle, it just goes up to start View.
I am trying to make the condition based screen size but I don't know how to make it.
I shared my code in expo-snacks
This is my all code
import React, { useState, useEffect } from "react";
import { StyleSheet, useWindowDimensions, RefreshControl } from "react-native";
import MapView from "react-native-maps";
import styled from "styled-components";
import {
PanGestureHandler,
PanGestureHandlerGestureEvent,
FlatList,
} from "react-native-gesture-handler";
import Animated, {
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
withTiming,
Easing,
withSpring,
} from "react-native-reanimated";
const initialRegion = {
latitudeDelta: 15,
longitudeDelta: 15,
latitude: 60.1098678,
longitude: 24.7385084,
};
const api =
"http://open-api.myhelsinki.fi/v1/events/?distance_filter=60.1699%2C24.9384%2C10&language_filter=en&limit=50";
export default function App() {
const { height } = useWindowDimensions();
const top = useSharedValue(height);
const [event, setEvent] = useState([]);
const [loading, setLoading] = useState(false);
const prevTop = useSharedValue(height * 0.5);
// This is Fetch Data
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(api);
const data = await response.json();
setEvent(data.data);
setLoading(false);
} catch (error) {
console.log("erro", error);
}
};
useEffect(() => {
fetchData();
}, []);
const animatedStyle = useAnimatedStyle(() => {
return {
top: top.value * 0.2,
bottom: 0,
};
});
const gestureHandler = useAnimatedGestureHandler(
{
onStart(_, context) {
context.translateY = top.value;
},
onActive(event, context) {
top.value = context.translateY + event.translationY;
},
onEnd(event, _) {
// THIS IS MY CONDITION OF ANIMATED VIEW
if (event.translationY > 0 && event.translationY < 400) {
console.log("middle-top", top.value);
console.log("middle-height", height);
top.value = withSpring(height * 2.5, {
duration: 500,
easing: Easing.inOut(Easing.ease),
});
} else if (event.translationY > 450 && event.translationY < 800) {
console.log("bottom-top", top.value);
console.log("bottom-height", height);
top.value = withSpring(height * 4, {
duration: 500,
easing: Easing.inOut(Easing.ease),
});
} else if (event.translationY < 0) {
console.log("start-top", top.value);
console.log("start-height", height);
top.value = withSpring(height, {
duration: 500,
easing: Easing.inOut(Easing.ease),
});
}
},
},
[top]
);
return (
<>
<MapView style={styles.mapStyle} initialRegion={initialRegion} />
<PanGestureHandler onGestureEvent={gestureHandler}>
<Animated.View style={[styles.container, animatedStyle]}>
<Title>I am scroll sheet</Title>
<HeroFlatList
data={event}
refreshControl={
<RefreshControl
enabled={true}
refreshing={loading}
onRefresh={fetchData}
/>
}
keyExtractor={(_, index) => index.toString()}
renderItem={({ item, index }) => {
const image = item?.description.images.map((img) => img.url);
const startDate = item?.event_dates?.starting_day;
return (
<EventContainer key={index}>
<EventImage
source={{
uri:
image[0] ||
"https://res.cloudinary.com/drewzxzgc/image/upload/v1631085536/zma1beozwbdc8zqwfhdu.jpg",
}}
/>
<DescriptionContainer>
<Title ellipsizeMode="tail" numberOfLines={1}>
{item?.name?.en}
</Title>
<DescriptionText>
{item?.description?.intro || "No description available"}
</DescriptionText>
<DateText>{startDate}</DateText>
</DescriptionContainer>
</EventContainer>
);
}}
/>
</Animated.View>
</PanGestureHandler>
</>
);
}
const styles = StyleSheet.create({
container: {
position: "absolute",
left: 0,
right: 0,
top: 0,
backgroundColor: "white",
shadowOffset: {
height: -6,
width: 0,
},
shadowOpacity: 0.1,
shadowRadius: 5,
borderTopEndRadius: 15,
borderTopLeftRadius: 15,
},
mapStyle: {
flex: 1,
},
});
const HeroFlatList = styled(FlatList).attrs({
contentContainerStyle: {
flexGrow: 1,
},
})`
padding: 12px;
`;
const Title = styled.Text`
font-size: 16px;
font-weight: 700;
margin-bottom: 10px;
align-self: center;
padding: 10px;
`;
const DescriptionText = styled.Text`
font-size: 14px;
opacity: 0.7;
`;
const DateText = styled.Text`
font-size: 14px;
opacity: 0.8;
color: #0099cc;
`;
const EventImage = styled.Image`
width: 70px;
height: 70px;
border-radius: 70px;
margin-right: 20px;
`;
const DescriptionContainer = styled.View`
width: 200px;
`;
const EventContainer = styled(Animated.View)`
flex-direction: row;
padding: 20px;
margin-bottom: 10px;
border-radius: 20px;
background-color: #fff;
shadow-color: #000;
shadow-opacity: 0.3;
shadow-radius: 20px;
shadow-offset: 0 10px;
`;
Tech information
Tech
Version
react-native-gesture-handler
^1.10.3
react-native-reanimated
^2.2.0
Not the perfect solution...
added a new sharedValue to track if its moving up or down.
const prevTop = useSharedValue(height * 0.5);
and respective code on gesture end.
onEnd() {
if (top.value > prevTop.value) {
top.value = withTiming(height * 0.98);
} else {
top.value = withTiming(Math.min(200, top.value));
}
prevTop.value = top.value;
},
Still there is a scope of improvement.

Maximum update Depth Exceeded - wrapping animated component in a modal?

Having a problem here. Essentially trying to create an animation for a modal pop up when a button is tapped.
Because I have a tab bar in the application, To let the modal pop up over the tab bar, I need to wrap the Animated Component in a Modal (or maybe I don't? Would be good to know other solutions). This means that when I toggle the animation, I also want to toggle local state for the modal's visibility.
However, when I hit the button, the component updates through redux and calls the toggleModal function - the inclusion of this.setState(prevState => ({ modalVisible: !prevState.modalVisible })) is somehow causing a repetitive call of setState.
I have the animation working in a throwaway expo app without useNativeDriver and without a tab bar (thus not needing a modal component to wrap the animation).
How can I begin to fix this?
AddCircleModal:
const screenHeight = Dimensions.get("window").height
class AddCircleModal extends React.Component {
state = {
top: new Animated.Value(screenHeight),
modalVisible: false
}
componentDidUpdate() {
('modalDidUpdate')
this.toggleModal()
}
toggleModal = () => {
console.log('toggled')
this.setState(prevState => ({ modalVisible: !prevState.modalVisible })) //if I have this line I'm getting 'maximum update depth exceeded' error
if (this.props.action === 'openModal') {
Animated.spring(this.state.top, {
toValue: 174,
useNativeDriver: true
}).start()
}
if (this.props.action === 'closeModal') {
Animated.spring(this.state.top, {
toValue: screenHeight,
useNativeDriver: true
}).start()
}
}
render() {
return (
<Modal
transparent={true}
visible={this.state.modalVisible}
>
<AnimatedContainer style={{scaleY: this.state.top}}>
<TouchableOpacity
onPress={this.props.closeModal}
style={{ position: "absolute", top: 120, left: "50%", marginLeft: -22, zIndex: 1 }}
>
<Text>GO</Text>
</TouchableOpacity>
</AnimatedContainer>
</Modal>
)
}
}
const Container = styled.View`
position: absolute;
background: white;
width: 100%;
height: 100%;
z-index: 100;
border-radius: 22px;
`
const AnimatedContainer = Animated.createAnimatedComponent(Container)
function mapStateToProps(state) {
return { action: state.action }
}
function mapDispatchToProps(dispatch) {
return {
closeModal: () =>
dispatch({
type: "CLOSE_MODAL"
})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(AddCircleModal)

How to implement a navigation drawer based on react router 4 in react native

I want to create a navigation drawer like in uber . So Is there are any libraries or packages that i can used to develop the navigation drawer of my app based on react router 4.
Use this
https://github.com/Tinysymphony/react-native-drawer-menu
https://github.com/root-two/react-native-drawer
and you can creat a view by yourself, it't easy, like this:
import React, { PureComponent } from 'react';
import {
View,
Animated,
Easing,
Dimensions,
TouchableOpacity,
TouchableWithoutFeedback
} from 'react-native';
import mitt from 'mitt';
import styled from 'styled-components';
import { t } from '../i18n';
import { TOOLBAR_HEIGHT } from './Toolbar';
import Avatar from '../components/Avatar';
import Icon from '../components/Icon';
import Text from './Text';
const { width } = Dimensions.get('window');
//-----------------------------------------------
class MenuDrawer extends PureComponent {
static defaultProps = {
width: (width * 75) / 100
};
constructor(props) {
super(props);
this.state = { show: false };
this.emitter = mitt();
this.animateValue = {
opacity: new Animated.Value(0),
marginLeft: new Animated.Value(-props.width)
};
}
animation({ opacity, mgleft }) {
this.animateValue.opacity.setValue(opacity.start);
this.animateValue.marginLeft.setValue(mgleft.start);
return Animated.parallel([
Animated.timing(this.animateValue.opacity, {
toValue: opacity.end,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
}),
Animated.timing(this.animateValue.marginLeft, {
toValue: mgleft.end,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
})
]);
}
subscribe = cb => {
this.emitter.on('state-change', status => {
cb(status);
});
};
show = () => {
this.emitter.emit('state-change', true);
this.setState({ ...this.state, show: true }, () => {
const opacity = { start: 0, end: 0.6 };
const mgleft = { start: this.props.width, end: 0 };
this.animation({ opacity, mgleft }).start();
});
};
hide = () => {
this.emitter.emit('state-change', false);
const opacity = { start: 0.6, end: 0 };
const mgleft = { start: 0, end: this.props.width };
this.animation({ opacity, mgleft }).start(({ finished }) => {
if (finished) {
this.setState({ ...this.state, show: false });
}
});
};
handlePressOnBackground = () => {
this.hide();
};
renderContent() {
const { me } = this.props;
const name = me.fullname;
const avatar_url = me.avatar_url;
return (
<StyledView>
<StyledMyInfo>
<Avatar size={96} uri={avatar_url} name={name} isAgent={true} />
<StyledName text={name} />
</StyledMyInfo>
<StyledMenu>
<TouchableOpacity onPress={this.props.handlePressSettings}>
<StyledMenuItem>
<StyledIcon>
<Icon size={20} source={require('../assets/setting.png')} />
</StyledIcon>
<StyledLabel text={t('general_settings')} />
</StyledMenuItem>
</TouchableOpacity>
<TouchableOpacity onPress={this.props.handlePressChangePassword}>
<StyledMenuItem>
<StyledIcon>
<Icon
size={20}
ml={2}
source={require('../assets/password.png')}
/>
</StyledIcon>
<StyledLabel text={t('profile_language_change_password_link')} />
</StyledMenuItem>
</TouchableOpacity>
<TouchableOpacity onPress={this.props.handlePressLogout}>
<StyledMenuItem>
<StyledIcon>
<Icon
size={20}
ml={-1}
source={require('../assets/logout.png')}
/>
</StyledIcon>
<StyledLabel text={t('agent_profile_logout')} />
</StyledMenuItem>
</TouchableOpacity>
</StyledMenu>
</StyledView>
);
}
render() {
const { id } = this.props.me;
if (!this.state.show || !id) return null;
return (
<StyledViewContainer>
<TouchableWithoutFeedback
style={{ flex: 1 }}
onPress={this.handlePressOnBackground}
>
<Animated.View
style={[
{
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
backgroundColor: 'black'
},
{ opacity: this.animateValue.opacity }
]}
/>
</TouchableWithoutFeedback>
<Animated.View
style={[
{
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
width: '75%'
},
{ marginLeft: -this.animateValue.marginLeft }
]}
>
{this.renderContent()}
</Animated.View>
</StyledViewContainer>
);
}
}
//-----------------------------------------------
const StyledViewContainer = styled(View)`
position: absolute;
top: ${TOOLBAR_HEIGHT};
right: 0;
bottom: 0;
left: 0;
`;
const StyledView = styled(View)`
flex: 1;
background-color: #f9f9f9;
`;
const StyledMyInfo = styled(View)`
justify-content: center;
align-items: center;
height: 240;
background-color: white;
`;
const StyledName = styled(Text)`
margin-top: 10px;
font-size: ${props => props.theme.fontSizeLarge};
font-family: ${props => props.theme.fontSemiBold};
`;
const StyledMenu = styled(View)`
padding: 12px 15px;
`;
const StyledMenuItem = styled(View)`
margin-bottom: 5px;
flex-direction: row;
align-items: center;
`;
const StyledIcon = styled(View)`
width: 40;
height: 40;
justify-content: center;
align-items: center;
`;
const StyledLabel = styled(Text)``;
export default MenuDrawer;