I am a beginner at React Native. As you can see from the image that I have a Scroll View and two buttons. I have successfully implemented the scroll View which works fine but I also want to them to auto scroll on the press of a button. I have tried searching a lot but not getting anything which is working. So any help is appreciated. Please find my code below.
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View, Dimensions, ScrollView, Button } from 'react-native';
var screenWidth = Dimensions.get('window').width;
export default class App extends React.Component {
render() {
return (
<View style={styles.MainContainer}>
<View style={styles.ButtonViewContainer}>
<View style={styles.ButtonContainer}>
<Button title="Screen 1" />
</View>
<View style={styles.ButtonContainer}>
<Button title="Screen 2" />
</View>
</View>
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
>
<View style={styles.ScrollContainer}>
<Text style={styles.ScrollTextContainer}>
Screen 1
</Text>
</View>
<View style={styles.ScrollContainer}>
<Text style={styles.ScrollTextContainer}>
Screen 2
</Text>
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer: {
backgroundColor: '#abe3a8',
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
ScrollContainer: {
backgroundColor: '#cdf1ec',
flexGrow: 1,
marginTop: 0,
width: screenWidth,
justifyContent: 'center',
alignItems: 'center'
},
ScrollTextContainer: {
fontSize: 20,
padding: 15,
color: '#000',
textAlign: 'center'
},
ButtonViewContainer: {
flexDirection: 'row',
paddingTop: 35,
},
ButtonContainer: {
padding: 30,
},
});
I cant gurantee this is the best approach as I havent worked alot with React Native.
Add this.scroll.scrollTo({ x: calculatedStartPositionOfTheScreen}) to your button Press handler
https://facebook.github.io/react-native/docs/scrollview#scrollto
e.g
<View>
...
<View style={styles.ButtonContainer}>
<Button title="Screen 1" onPress={() => { this.scroll.scrollTo({ x: 0 }) }} />
</View>
<View style={styles.ButtonContainer}>
<Button title="Screen 2" onPress={() => { this.scroll.scrollTo({ x: screenWidth }) }} />
</View>
<View style={styles.ButtonContainer}>
<Button title="Screen 3" onPress={() => { this.scroll.scrollTo({ x: screenWidth * 2 }) }} />
</View>
...
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
ref={(node) => this.scroll = node}
>
...
</ScrollView>
</View >
For this use case in bigger projects you can also consider
https://reactnavigation.org
Try this.
<View>
...
<View style={styles.ButtonContainer}>
<Button title="Screen 1" onPress={() => { this.refs.scroll.scrollTo({ x: 0 }) }} />
</View>
<View style={styles.ButtonContainer}>
<Button title="Screen 2" onPress={() => { this.refs.scroll.scrollTo({ x: screenWidth }) }} />
</View>
<View style={styles.ButtonContainer}>
<Button title="Screen 3" onPress={() => { this.refs.scroll.scrollTo({ x: screenWidth * 2 }) }} />
</View>
...
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
ref={'scroll'}
>
...
</ScrollView>
</View >
You can try:
onPress = (index) => {
this.scroll.scrollTo({x: index * screenWidth, y: 0, animated: true})
}
<Button title="Screen 1"
onPress = {() => this.onPress(0)}
/>
...
<Button title="Screen 2"
onPress = {() => this.onPress(1)}
/>
...
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
ref = {re => this.scroll = re}
>
</ScrollView>
Related
I have a FlatList nested in a SectionList as shown below.
There is always 3 sections (rows) and each section has a FlatList with a horizontal scroll.
Expected
On button click, invoking the scrollToEnd() function, to scroll all 3 flatlists from each section to end.
Problem
Only the bottom or last flatlist scrolls to the end.
I cannot figure out why this is - I thought the ref in the flatlist may only be referencing the last Flatlist rendered and not the other two, maybe? If so, any tips or suggestions are welcome. Thank you.
...
const flatlistRef = useRef();
const scrollToEnd = () => {
flatlistRef.current.scrollToEnd({ animating: true });
};
...
<SectionList
contentContainerStyle={styles.sectionListContainer}
stickySectionHeadersEnabled={false}
sections={myData}
renderSectionHeader={({ section }) => (
<>
<FlatList
horizontal
data={section.data}
contentContainerStyle={
styles.flatlistContainer
}
renderItem={({ item }) => (
<Button
onPress={() => updateData(item.id)}
>
<ListItem item={item} />
</Button>
)}
showsHorizontalScrollIndicator={false}
ref={flatlistRef}
/>
</>
)}
renderItem={({}) => {
return null;
}}
/>
I have also working on this but I found a solution where I can create a Section.List by using react-native-paper.
But you can also use the map function, Here is the code of that
import React from "react";
import {View,Text} from "react-native";
const App = () =>{
return(
<View style={{flex: 1}}>
{data.map((item, index) => (
<View key={index} style={{borderBottomColor: 'black', borderBottomWidth: 2}}>
<Text style={{fontSize: 30, fontWeight: 'bold'}}>{item.title}</Text>
{item.items && <>
{item.items.map((item, index) => (
<View key={index} style={{backgroundColor: '#7fc', borderBottomColor: 'blue', borderBottomWidth: 2}}>
<Text style={{fontSize: 20, marginLeft: 40, color: 'blue'}}>{item.title}</Text>
{item.items && <>
{item.items.map((item, index) => (
<View key={index} style={{backgroundColor: 'yellow', borderBottomColor: 'red', borderBottomWidth: 2}}>
<Text style={{fontSize: 16, marginLeft: 80,}}>{item.title}</Text>
</View>
))}
</>}
</View>
))}
</>}
</View>
))}
</View>
)
}
export default App;
I hope It will help.
Friends, I would like to overlay a button on a webview in react native to redirect routes manually.
The react native buttons should be invisible on top of the webview buttons
The following image shows the buttons on the web page and below the react native buttons.
1
another problem is that the keyboard does not open when clicking on an input within the webview
here's my code:
const App = () => {
const deviceHeight = Dimensions.get('window').height;
const deviceWidth = Dimensions.get('window').width
const [url, setUrl] = useState('https://rootroute.com.br/');
return (
<KeyboardAvoidingView
behavior={ Platform.OS === 'ios' ? 'padding' : undefined }
style={styles.keyboardAvoidingView}
>
<View style={{ flex: 1}}>
<WebView
source={{ uri: url }}
onError={syntheticEvent => {
const { nativeEvent } = syntheticEvent;
Alert.alert('WebView error: ', "" + nativeEvent);
}}
onHttpError={syntheticEvent => {
const { nativeEvent } = syntheticEvent;
console.warn(
'WebView received error status code: ',
nativeEvent.statusCode,
);
}}
mixedContentMode={'always'}
geolocationEnabled={true}
ignoreSslError={true}
javaScriptEnabled={true}
domStorageEnabled={true}
scalesPageToFit={true}
startInLoadingState={false}
style={{ flex: 1, width: deviceWidth, height: deviceHeight, marginTop: 15 }}
/>
<View style={styles.container}>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/1')}
title="Home"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/2')}
title="Alerta"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/3')}
title="Explore"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/4')}
title="Carrinho"
/>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={() => setUrl('https://rootroute.com.br/5')}
title="Conta"
/>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 50
},
buttonContainer: {
flex: 1,
},
keyboardAvoidingView: { flexGrow: 1, flexShrink: 1 },
});
export default App; ```
I think you don't need KeyboardAvoidingView in your case
Just use WebView and View
Because KeyboardAvoidingView use to handle TextInput keyboard on normal View
I use react-native-vector-icons.
Click the input
Keyboard goes up
When pressing the icon, icon doesn't trigger, the keyboard will go down first rather than the onpress method icon triggers while having the keyboard is on
Expected Result would like a live chat, while keyboard is up submit icon will always trigger.
I tried to enwrap it in scrollview with keyboardshouldpersisttaps and it doesn't work.
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : null}
style={{ flex: 1 }}
keyboardVerticalOffset={64}
>
<View style={styles.slide} key={i}>
<TouchableHighlight
style={styles.video}
onPress={this.handleDoubleTap}
onLongPress={this.handlePlayAndPause}
>
<ViewportAwareVideo
key={i}
source={{ uri: firstVideoUri }}
shouldPlay={this.state.shouldPlay}
isLooping
preTriggerRatio={-0.4} // default is 0
retainOnceInViewport={false} // default is false
style={styles.video}
onPlaybackStatusUpdate={this._onPlaybackStatusUpdate}
progressUpdateIntervalMillis={1000}
resizeMode='contain'
innerRef={ref => (this._videoRef = ref)}
onViewportEnter={() => {
this.setState({ shouldPlay: true });
}}
onViewportLeave={() => {
this.setState({ shouldPlay: false });
}}
/>
</TouchableHighlight>
{this.state.shouldPlay ? null : (
<TouchableHighlight
onPress={this.handlePlayAndPause}
style={styles.pauseBtn}
>
<IconComponent name='play-circle' size={50} color='black' />
</TouchableHighlight>
)}
<CopilotStep
name='swipeUp'
text='Swipe up to view next video'
order={5}
>
<WalkthroughableView style={styles.topSection}>
<Text style={styles.imageHeadingText}>{product.name}</Text>
{product.short_description === '' ? null : (
<HTML
html={product.short_description}
imagesMaxWidth={Dimensions.get('window').width}
containerStyle={styles.imageDescText}
baseFontStyle={styles.htmlStyle}
/>
)}
<CopilotStep
name='swipeRight'
text='Swipe right to view product details'
order={6}
>
<WalkthroughableView
style={{
flexDirection: 'row',
flexWrap: 'wrap',
paddingHorizontal: 20,
paddingVertical: 5
}}
>
{product.tags.map((value, index) => {
return (
<Text key={index} style={styles.tagText}>
{value.name.charAt(0) === '#'
? value.name
: '#' + value.name}
</Text>
);
})}
</WalkthroughableView>
</CopilotStep>
{product.total_sales > 0 ? (
<View
style={{
flexDirection: 'row',
flexWrap: 'wrap',
paddingHorizontal: 20,
paddingVertical: 5
}}
>
<Text style={styles.totalSales}>
{product.total_sales +
(product.total_sales > 100
? '+ bought'
: ' bought in the last 24 hours')}
</Text>
</View>
) : null}
</WalkthroughableView>
</CopilotStep>
<View style={styles.bottomSection}>
<View style={{ flex: 1, justifyContent: 'flex-end', height: 30 }}>
{this.state.messages.map((message, index) => (
<React.Fragment key={index}>
<View
key={index}
style={{
flexDirection: 'row',
alignItems: 'center',
marginHorizontal: 5,
marginVertical: 5,
paddingLeft: 10,
height: 20
}}
>
<Image
style={{ width: 20, height: 20, borderRadius: 20 / 2 }}
source={{ uri: 'https://picsum.photos/20/20' }}
/>
<Text
style={{
fontFamily: Constants.fontHeader,
marginHorizontal: 5,
color: '#007AFF'
}}
>
{message.user.name}
</Text>
<Text
style={{
fontFamily: Constants.fontHeader,
marginHorizontal: 5,
color: 'white'
}}
>
{message.text}
</Text>
</View>
</React.Fragment>
))}
</View>
<CopilotStep
name='chatOnFeed'
text='Click here to chat on video feed'
order={7}
>
<WalkthroughableTextInput
style={{
// position: 'absolute',
// bottom: 0,
// left: 0,
fontFamily: Constants.fontFamily,
marginBottom: 110,
marginHorizontal: 5,
marginVertical: 5,
paddingRight: 35,
paddingLeft: 20,
height: 35,
width: width - 60,
backgroundColor: 'white',
borderRadius: 25
}}
onChangeText={messageText => this.setState({ messageText })}
value={this.state.messageText}
placeholder='Share your thoughts'
placeholderTextColor='#9B9B9B'
/>
</CopilotStep>
<IconComponent
style={{ position: 'absolute', bottom: 115, right: 10 }}
name='arrow-right'
size={25}
color='black'
onPress={product => this.sendMessage(product)}
/>
</View>
<View style={styles.iconBar}>
<CopilotStep
name='productDetail'
text='Click here to got to product details'
order={8}
>
<WalkthroughableText>
<IconComponent
style={styles.iconBarIcon}
name='shopping-cart'
size={iconSize}
color='white'
onPress={() => {
this.props.onViewProductScreen({ product });
this.setState({ shouldPlay: false });
}}
/>
</WalkthroughableText>
</CopilotStep>
<Text style={styles.iconBarText}>Shop</Text>
<CopilotStep
name='like'
text='Click here to like this product'
order={9}
>
<WalkthroughableText>
<Entypo
style={styles.iconBarIcon}
name='heart'
size={30}
color={this.state.isInWishList ? 'red' : 'white'}
onPress={() => {
this.state.isInWishList
? this.props.removeWishListItem(product)
: this.props.addWishListItem(product);
this.setState(prevState => ({
isInWishList: !prevState.isInWishList
}));
}}
/>
</WalkthroughableText>
</CopilotStep>
<Text style={styles.iconBarText}>Like</Text>
<CopilotStep
name='share'
text='Click here to share this product'
order={10}
>
<WalkthroughableText>
<IconComponent
style={styles.iconBarIcon}
name='share'
size={iconSize}
color='white'
onPress={this.onShare}
/>
</WalkthroughableText>
</CopilotStep>
<Text style={styles.iconBarText}>Share</Text>
<CopilotStep
name='fullChat'
text='Click here to view full chat'
order={11}
>
<WalkthroughableText>
<IconComponent
style={[styles.iconBarIcon, { paddingTop: 4 }]}
name='message-circle'
size={iconSize}
color='white'
onPress={product => this.sendChat(product)}
/>
</WalkthroughableText>
</CopilotStep>
</View>
</View>
</KeyboardAvoidingView>
);
You can see my problem is on IconComponent after the WalkthroughableTextInput
If you are using NativeBase component use it like this
<Content keyboardShouldPersistTaps={'handled'}>
...
</Content>
For ReactNative <ScrollView/>
<ScrollView keyboardShouldPersistTaps={'handled'}>
...
</ScrollView>
I'm creating a login, and to solve the problem with the virtual keyboard covering my text inputs I'm using KeyboardAvoidingView. I thought that the logo would animate nicely since I define both the form and the logo as flex: 1 (shrink/grow as much as possible in the available space) Since opening a keyboard diminishes the available space on the screen, the logo does change, but shrinks too much and then an overlap occurs. What I am missing?
This is my LoginScreen:
import React, { Component } from 'react'
import { Image, StyleSheet, View, KeyboardAvoidingView, Button } from 'react-native'
import FormTextInput from '../components/FormTextInput'
class LoginScreen extends Component {
state = { email: '', password: '' }
handleEmailUpdate = email => {
this.setState({ email })
}
handlePasswordUpdate = password => {
this.setState({ password })
}
handleLoginPress = () => {
console.log('Login button pressed')
}
render() {
return (
<KeyboardAvoidingView style={styles.container} behavior="padding">
<Image style={styles.logo} source={require('../assets/images/test.png')} />
<View style={styles.form}>
<FormTextInput
value={this.state.email}
onChangeText={this.handleEmailChange}
placeholder="Email"
autoCorrect={false}
keyboardType="email-address"
returnKeyType="next"
/>
<FormTextInput
placeholder="Password"
value={this.state.password}
onChangeText={this.handlePasswordChange}
secureTextEntry
returnKeyType="done"
/>
<Button title="LOGIN" onPress={this.handleLoginPress} />
</View>
</KeyboardAvoidingView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'space-between',
},
logo: {
flex: 1,
width: '80%',
resizeMode: 'contain',
alignSelf: 'center',
},
form: {
flex: 1,
justifyContent: 'center',
width: '80%',
},
})
export default LoginScreen
*EDIT: after adding the line android:windowSoftInputMode="adjustPan", the keyboard overlaps the login button:
Use this is your android manifest
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustPan" //add this line
android:exported="true">
try this it will solve this problem
try this.
{Platform.OS === 'ios' ?
<KeyboardAvoidingView style={styles.container} behavior="padding">
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={{paddingVertical: 10}}
keyboardShouldPersistTaps='handled'>
<Image style={styles.logo} source={require('../assets/images/test.png')} />
<View style={styles.form}>
<FormTextInput
value={this.state.email}
onChangeText={this.handleEmailChange}
placeholder="Email"
autoCorrect={false}
keyboardType="email-address"
returnKeyType="next"
/>
<FormTextInput
placeholder="Password"
value={this.state.password}
onChangeText={this.handlePasswordChange}
secureTextEntry
returnKeyType="done"
/>
<Button title="LOGIN" onPress={this.handleLoginPress} />
</View>
</ScrollView>
</KeyboardAvoidingView>
: <ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={{paddingVertical: 10}}
keyboardShouldPersistTaps='handled'>
<Image style={styles.logo} source={require('../assets/images/test.png')} />
<View style={styles.form}>
<FormTextInput
value={this.state.email}
onChangeText={this.handleEmailChange}
placeholder="Email"
autoCorrect={false}
keyboardType="email-address"
returnKeyType="next"
/>
<FormTextInput
placeholder="Password"
value={this.state.password}
onChangeText={this.handlePasswordChange}
secureTextEntry
returnKeyType="done"
/>
<Button title="LOGIN" onPress={this.handleLoginPress} />
</View>
</ScrollView>
}
and style is
const styles = StyleSheet.create({
container: {
flex: 1, paddingVertical: 30,
alignItems: 'center', justifyContent: 'center',
backgroundColor: '#FFFFFF',
},
logo: {
flexGrow: 1,
width: '80%',
resizeMode: 'contain',
alignSelf: 'center',
},
form: {
flexGrow: 1,
justifyContent: 'center',
width: '80%',
},
});
Is there a way using "View" to make it loop?
I have already tried using:
function generateListViewPager (shapeStyle) {
return () => {
return (
<View style={styles.pageContainer} >
<ScrollView showsVerticalScrollIndicator={false}>
for(let i = 0; i < 40; i++){
<View style={[styles.shapeBase]}>
<Image
style={{width: windowWidth, height: 260, alignItems: 'center'}}
source={{uri: 'https://test.com/img/i.jpg'}}
/>
<View style={{
position: 'absolute',
width: windowWidth - 15,
height: 130,
bottom: 41,
backgroundColor: 'rgba(0, 0, 0, 0.1)'
}}>
<Text style={styles.TitleStyle}>Test i</Text>
</View>
<View style={styles.subButton}>
</View>
<View style={styles.hairline} />
<View style={styles.subContent}>
</View>
</View>
}
</ScrollView>
</View>
)
}
}
I need to show my view from 0 to 39, how would I do it using a loop? thanks
You are evaluating javascript with your for loop but you don't have the curly braces around it. I think you could wrap your repeating component into a dumb component:
const MyRepeatedView = ({ i }) => {
return (
<View style={[styles.shapeBase]}>
<Image
style={{width: windowWidth, height: 260, alignItems: 'center'}}
source={{uri: 'https://test.com/img/i.jpg'}}
/>
<View style={{
position: 'absolute',
width: windowWidth - 15,
height: 130,
bottom: 41,
backgroundColor: 'rgba(0, 0, 0, 0.1)'
}}>
<Text style={styles.TitleStyle}>Test {i}</Text>
</View>
<View style={styles.subButton}>
</View>
<View style={styles.hairline} />
<View style={styles.subContent}>
</View>
</View>
);
};
function generateListViewPager (shapeStyle) {
return () => {
return (
<View style={styles.pageContainer} >
<ScrollView showsVerticalScrollIndicator={false}>
{[...Array(40).keys()].map(i => <MyRepeatedView key={i} i={i} />)}
</ScrollView>
</View>
)
}
}
Perhaps you should try using a Flatlist component.
Check documentation here:
https://facebook.github.io/react-native/docs/flatlist.html