i'm trying to set the scrollView's value to be 0 and it's crashing
below is my code
const scrollY = useRef(new Animated.Value(0)).current;
return (
<View style={{flex: 1}}>
<Animated.ScrollView
style={{flex: 1}}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: scrollY}}}],
{useNativeDriver: true},
)}
scrollEventThrottle={16}>
<Animated.View style={{top: scrollY}}>
<ProductDetail route={route} navigation={navigation} />
</Animated.View>
<ProductDetailInfo route={route} />
<Topping route={route} />
</Animated.ScrollView>
<ButtonProductDetail />
</View>
);
};
If you are trying to scroll to the top of the list, the ScrollView has a method for this, scrollTo(). Following is an example of how to use it:
import { useRef } from 'react'
import {
Text,
View,
ScrollView,
TouchableOpacity,
} from 'react-native';
export default function ScrollToTopExample() {
const listRef = useRef()
const handleScrollToTop = () => {
listRef.current.scrollTo({
x: 0,
y: 0,
animated: true,
})
}
const Button = () => (
<TouchableOpacity onPress={handleScrollToTop} >
<Text>Go to top</Text>
</TouchableOpacity>
)
return (
<View>
<ScrollView ref={listRef} >
// Some content here
</ScrollView>
<Button />
</View>
);
}
I created a snack on Expo for you to see the complete example on the computer with the source code. But the animation of the scroll works only on a mobile. You can scan the QR Code from your smartphone using the Expo Go app to see it in action.
Related
I created a FlatList of selectable countries like this
export default function Body() {
const data = useData();
const [selected, setSelected] = useState(1);
const renderItem = ({ item }) => {
return item.empty ? (
<View style={styles.blank} />
) : (
<Country
text={item.name}
onPress={() => setSelected(item.id)}
selected={item.id === selected}
>
<item.Flag />
</Country>
);
};
return (
<View style={styles.container}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id.toString()}
extraData={selected}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.flatlist}
numColumns={3}
/>
</View>
);
}
And I defined a Country component like this
import React from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { styles } from "./Style";
export default function Country({ children, text, onPress, selected }) {
return (
<View style={styles.container}>
<View style={[styles.view, selected && styles.selected]}>
<TouchableOpacity onPress={onPress}>{children}</TouchableOpacity>
</View>
<TouchableOpacity onPress={onPress}>
<Text style={styles.text}>{text}</Text>
</TouchableOpacity>
</View>
);
}
Everything was working perfectly fine and I was able to select a country but somehow now the touchableOpacity onPress event seems broken and the elements are no longer pressable. for things to work I need to edit and undo edit on the data array or the Country component. Is this a RN bug causing things to fail?
I found the root problem. Turns out that the problem lays on the stylesheet of the Country component wrapper. I gave it an alignSelf: "baseline" don't know why but removing it solved the hassle
I made a customized list component (in React Native) which shows touchable images with some description texts.
I need each images open a specific Modal; but I don't know how!! where & how I should code the Modal??
... here is my photo list component:
export class CustomGallery extends Component {
render() {
let {list} = this.props;
return (
<View style={styles.container}>
<FlatList
numColumns={4}
data={list}
renderItem={({ item}) => (
<View style={styles.views}>
<TouchableOpacity style={styles.touch} >
<ImageBackground
style={styles.img}
source={{ uri: item.photo }}
>
<Text style={styles.txt}>{item.name}</Text>
<Text style={styles.txt}>{item.key}</Text>
<Text style={styles.txt}>{item.describtion}</Text>
</ImageBackground>
</TouchableOpacity>
</View>
)}
/>
</View>
);
}
}
For Modal you can use modal from material-ui - https://material-ui.com/components/modal/
The Modal component renders its children node infront of a backdrop component. Simple and basic example would be like a confirmation message that pops up asking whether you surely want to delete particular information or not.
From your code I am guessing you want to display information regarding the image using modal when you click on the image.
Here I have added Modal component:
import React from 'react';
import Modal from '#material-ui/core/Modal';
export class CustomGallery extends Component {
constructor() {
super();
this.state = {
modalOpen: false,
snackOpen: false,
modalDeleteOpen: false,
};
}
handleModalOpen = () => {
this.setState({ modalOpen: true });
}
handleModalClose = () => {
this.setState({ modalOpen: false });
}
render() {
let {list} = this.props;
return (
<View style={styles.container}>
<FlatList
numColumns={4}
data={list}
renderItem={({ item}) => (
<View style={styles.views}>
<TouchableOpacity style={styles.touch} >
<ImageBackground
style={styles.img}
onClick={() => this.handleModalOpen()}
>
{ item.photo }
</ImageBackground>
<Modal
open={this.state.modalOpen}
onClose={this.handleModalClose}
closeAfterTransition
>
<Text style={styles.txt}>{item.name}</Text>
<Text style={styles.txt}>{item.key}</Text>
<Text style={styles.txt}>{item.describtion}</Text>
</Modal>
</TouchableOpacity>
</View>
)}
/>
</View>
);
}
}
I am not sure about how you set the image. But anyways below method is an example of opening modal with dynamic data.
import React, {useState} from "react";
import { Button, TouchableOpacity, FlatList, Modal, Text } from "react-native";
function App() {
const [value, setValue] = useState("");
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
return (
<>
<FlatList
data={DATA}
renderItem={({item}) => (
<TouchableOpacity onPress={() => setValue(item.title)}>
<Text>{item.title}</Text>
</TouchableOpacity>
)}
/>
<Modal visible={value}>
<Text>{value}</Text>
<Button title="close" onPress={() => setValue("")} />
</Modal>
</>
)
}
export default App;
I'm new to react-native. This component below should render comments posted by users, I would like to add an inputText component from react-native to allow users to post a comment, but don't know where I should place it within the code below.
import React, { useState, useEffect } from 'react';
import { useNavigation } from "#react-navigation/native";
import Icon from 'react-native-vector-icons/AntDesign';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
ScrollView,
FlatList,
Button,
TextInput
} from 'react-native';
import parseDate from "../utils/parseDate";
import * as API from "../api/api"
export default function CommentList({ ride }) {
const [text, setText] = React.useState("");
const [commentsData, setComments] = useState([]);
const navigation = useNavigation();
useEffect(() => {
API.getCommentsByRideId(ride.ride_id).then((comments) => {
setComments(comments)
})
}, [ride.ride_id])
deleteComment = (comment_id) => {
// useEffect(() => {
API.deleteCommentsByCommentId(comment_id).then(() => {
const updatedComments = list.filter((item) => item.comment_id !== comment_id);
setComments(updatedComments)
})
// }, [comment_id])
}
//deletes on refresh only
addComment = (newComment, ride_id) => {
API.postCommentByRideId(newComment, ride_id).then(() => {
setComments(newComment)
})
}
return (
<FlatList
style={styles.root}
data={commentsData}
ItemSeparatorComponent={() => {
return (
<View style={styles.separator} />
)
}}
keyExtractor={(item) => {
return item.author;
}}
renderItem={(item) => {
const comment = item.item;
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => navigation.navigate("UserProfile", { username: item.author })}>
{/* <Image style={styles.image} source={{ uri: comment.avatar_url }} /> */}
</TouchableOpacity>
<View style={styles.content}>
<View style={styles.contentHeader}>
<Text style={styles.name}>{comment.author}</Text>
<Text style={styles.time}>
{parseDate(comment.created_at)}
{comment.votes}
</Text>
</View>
<Text rkType='primary3 mediumLine'>{comment.body}</Text>
{/* <Text style={styles.time}> Likes: {comment.votes}</Text> */}
<TouchableOpacity onPress={() => deleteComment(comment.comment_id)}>
<Icon name="delete" size={20} color="#e33057" />
</TouchableOpacity>
</View>
</View>
);
}} />
);
}
This is the inputText I would like to add to allow users to post a comment.
<TextInput
value={text}
placeholder="write..."
onChangeText={text => setText(text)}
onSubmitEditing={() => addcomment(text, ride.ride_id)}
/>
if you want to add it at fixed position in bottom of screen you may do this
<View style={{flex : 1}}>
<Flatlist
contentContainerStyle={{paddingBottom: 50}}
.../>
<View style={{position : 'absolute', bottom : 0, width : '100%', height : 50}}>
//you input here
</View>
</View>
or if you want to add it last item of flatlist you may use ListFooterComponent
<FlatList
ListFooterComponent={<Input/>}
.../>
</FlatList>
I work actually on a picker component which needs to be at center on the middle value by default.
I have created a modal with a ScrollView with ref and use the scrollTo function view on this exemple: https://snack.expo.io/SkileGr9X
Tried all but got this error :
Cannot read property 'scrollTo' of undefined
Does someone have any tip?
import React from 'react';
import { Modal,TouchableHighlight,View, StyleSheet,ScrollView,TextInput} from 'react-native';
import { Container, Header, Content, Icon,Picker, Form, Text,Left, Body, Right, Title,Button,List, ListItem} from "native-base";
const Mystyles = StyleSheet.create({
container:{
},
btnSelect:{
borderColor:'#a1a1a1',
borderWidth:1,
padding:5,
margin:10,
height:33
},
placeholderSelect:{
color:'#a1a1a1',
},
valueSelect:{
color:'black',
}
});
let scrollYPos = 0;
var itemsArray = [];
for(let i=0; i < 90;i++){
itemsArray.push(i);
}
export default class Selects extends React.Component {
constructor(props){
super(props);
this.state = {
items:itemsArray,
modalVisible: false,
isLoading:false,
selectValue:'',
placeholder:'placeholder',
type:'int'
}
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
scrollYPos = this.state.screenHeight * 1;
this.scroller.scrollTo({x: 0, y: scrollYPos});
}
selectItem = (item) =>{
this.setState({
selectValue:item,
modalVisible:false
});
this.props.returnSelect(item);
}
render(){
const { selectValue,items,placeholder } = this.state;
return (
<View style={Mystyles.container}>
<Modal
animationType="slide"
presentationStyle='formSheet'
visible={this.state.modalVisible}>
<Header>
<Left>
<Button transparent onPress={() => {this.setModalVisible(false);}}>
<Icon name='arrow-back' />
</Button>
</Left>
<Body>
<Title>Header</Title>
</Body>
<Right />
</Header>
<ScrollView ref={(scroller) => {this.scroller = scroller}}>
<List dataArray={items}
renderRow={(item) =>
<ListItem onPress={() => {this.selectItem(item);}} selected={selectValue == item}>
<Left>
<Text>{item}</Text>
</Left>
<Right>
<Icon name="arrow-forward" />
</Right>
</ListItem>
}>
</List>
</ScrollView>
</Modal>
<TouchableHighlight
style={Mystyles.btnSelect}
underlayColor="rgba(0, 0, 0, 0.1)"
onPress={() => {
this.setModalVisible(true);
}}>
<Text style={selectValue ? Mystyles.valueSelect : Mystyles.placeholderSelect}>{selectValue ? selectValue : placeholder}</Text>
</TouchableHighlight>
</View>
);
}
}
<Button transparent onPress={() => {this.setModalVisible(false);}}>
When you press this button, Modal gone so you can scroll when view gone. You have to check:
if(this.state.modalVisible){
scrollYPos = this.state.screenHeight * 1;
this.scroller.scrollTo({x: 0, y: scrollYPos});
}
BTW screenHeight is a const, don't use state.
I am developing an application where I have a button (TouchableHighlight) when pressing this button it is necessary to capture a screeshot of the current screen and save the file in the device.
My code does not show error, but when I press the button (TouchableHighlight) I get the message:
Image saved to file: ///data/user/0/com.appcamerav4/cache/ReactNative-snapshot-image8525057299267209213.jpg through Remote JS Debugging .
I can not open this directory and need to save the image to the device.
I'm new to react-native.
Follow my code below:
import React, { Component } from 'react';
import { Text, View, Image, StyleSheet, TouchableHighlight, WebView, StatusBar, Button } from 'react-native';
import { captureScreen } from "react-native-view-shot";
const zooMais = require('../imgs/zooMais.png');
const zooMenos = require('../imgs/zooMenos.png');
const imgScreeshot = require('../imgs/screeshot.png');
const btnZooMais = ()=>{
alert("Zoo Mais");
console.log("Zoom +");
}
const btnZooMenos = ()=>{
alert("Zoo Menos");
console.log("Zoom +");
}
const capitureScreen = ()=>{
captureScreen({
format: "jpg",
quality: 0.8,
}).then(
uri => console.log("Image saved to", uri),
error => console.error("Oops, snapshot failed", error)
);
}
export default class Monitor extends Component {
render() {
return (
<View style={ style.viewPrincipal }>
<StatusBar hidden />
<View style={ style.viewImagem } >
<WebView
style={style.video}
automaticallyAdjustContentInsets={true}
scalesPageToFit={true}
startInLoadingState={false}
contentInset={{top: 0, right: 0, left: 0, bottom: 0}}
scrollEnabled={true}
source={{uri: 'https://facebook.github.io/react/logo-og.png'}}
onNavigationStateChange = {this.handleNavigationStateChange}
/>
</View>
<View style={ style.viewRodape }>
<View style={style.viewMenu}>
<View >
<TouchableHighlight onPress={ btnZooMais } >
<Image style={style.imgMenu} source={zooMais } />
</TouchableHighlight>
</View>
<View>
<TouchableHighlight onPress={ capitureScreen }>
<Image style={style.imgMenu} source={ imgScreeshot } />
</TouchableHighlight >
</View>
<View>
<TouchableHighlight onPress={ btnZooMenos } >
<Image style={style.imgMenu} source={ zooMenos } />
</TouchableHighlight>
</View>
</View>
</View>
</View>
);
}
}
const style = StyleSheet.create({
viewPrincipal:{
flex: 1
},
viewImagem:{
flex:10,
justifyContent:'center',
alignItems:'stretch'
},
viewRodape:{
flex:1.3
},
viewMenu:{
flexDirection:'row',
justifyContent: 'space-between'
},
imgMenu:{
margin: 0,
marginBottom:0
},
video:{
flex:1
}
});
Make sure react-native-view-shot is correctly linked in XCode (might require a manual installation,
refer to React Native doc).
import React, { useRef } from "react"; // import useRef hook on top
const cardRef = useRef(); // Use this hook inside your func. component *important
// Define a function like this
const saveAsImage = async () => {
try {
const result = await captureRef(cardRef, {
result: "tmpfile",
quality: 1,
format: "png",
});
MediaLibrary.saveToLibraryAsync(result);
} catch (e) {
console.log(e);
}
};
Apply a prop eg. parentRef={cardRef} to your component, make sure the ref name matches which in this case is "cardRef".
Give any Button/TouchableOpacity
onPress={() => {saveAsImage();}}
To solve this problem you have to go on your App permission on your real mobile and allow for camera storage then you can easily save your ViewShot on Your Mobile.
go to App Permisssion in your App.info
allow Camera accesss storage
To save the screenshot to the camera roll, use this one: https://facebook.github.io/react-native/docs/cameraroll.html#savetocameraroll
More info: https://github.com/gre/react-native-view-shot Check the FAQ section