How can I scroll down to a focused text input? - javascript

I am trying to figure out how can I scroll up/down to the recently focused input.
I am using this text input -> https://facebook.github.io/react-native/docs/textinput
This is the text input:
<TextInput
autoFocus
style={PassengersStyles.SearchBox}
onChangeText={text => searchParamActionHandler(text)}
value={searchParam}
placeholder="Search..."
autoCapitalize="none"
ref={this.searchRef}
/>
It is a hidden text input, it has autoFocus so when the input is shown, it is focused right away but the phone-screen/UI stays in the same position. I need that once the input if focused the screen scrolls to the input so the user is able to see that there is a new element in the UI.
Any ideas?

You might be missing a <ScrollView> which is required if your content exceeds the screen height.
You might also need a KeyboardAvoidingView which ensures that the TextInput is not covered(or hidden) behind the keyboard.
Here I have added a few <View>'s to simulate some content.
import React from "react";
import {
StyleSheet,
View,
TextInput,
ScrollView,
KeyboardAvoidingView
} from "react-native";
export default class App extends React.Component {
render() {
return (
<KeyboardAvoidingView behavior="padding">
<ScrollView>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<TextInput
autoFocus
placeholder="Textinput far below..."
style={{ height: 20, backgroundColor: "red" }}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
<View
style={{
height: 100,
width: 100,
backgroundColor: "rgba(0, 0, 0, 0.3)"
}}
/>
</ScrollView>
</KeyboardAvoidingView>
);
}
}

Related

React Native (flexDirection: "row") not working

For some reason when I'm trying to align the contents of the Card which is the Image and Card.Title it will always align it like a column, the two won't go next to each other.
However, if I put the flexDirection: "row" in the modal container (which contains these two cards) it puts the cards side by side as it should. Why would it not work on the contents of the card itself?
Thanks
<Provider>
<Portal>
<Modal Modal visible={themeVisible} onDismiss={hideThemeModal} contentContainerStyle={modalStyle}>
<Card containerStyle={{ backgroundColor: '#3D3D3D', margin: 0, padding: 0, borderWidth: 0, elevation: 0, borderColor: '#212121' }}>
<Card.Title style={{ color: '#FFFFFF', marginBottom: 0, fontSize: 25, marginTop: 10 }} >Theme Selection</Card.Title>
<Text style={{ color: '#AAAAAA', textAlign: 'center', marginBottom: 10 }} >Thanks for supporting Fitness!</Text>
</Card>
<TouchableOpacity onPress={hideThemeModal}>
<Card containerStyle={{ flexDirection: "row", backgroundColor: '#3D3D3D', marginTop: 10, paddingBottom: 30, padding: 30, borderWidth: 0, borderTopWidth: 1, borderBottomWidth: 1, elevation: 0, borderColor: '#212121' }}>
<Image style={{ width: 25, height: 25 }} source={require('./assets/yellow-dark.png')} />
<Card.Title style={{ color: '#FFFFFF' }} >Yellow / Dark</Card.Title>
</Card>
</TouchableOpacity>
</Modal>
</Portal>
</Provider>
Tried float: left, flexdirection, inline-block, etc no change
Here is the styles for modalStyle and the safeareaview style
const modalStyle = {
backgroundColor: '#3D3D3D',
padding: 20,
margin: 35,
borderWidth: 1,
borderRadius: 7.5,
borderColor: '#F3AF21',
};
const styles = StyleSheet.create({
container: {
display: "flex",
flex: 1,
backgroundColor: '#181818',
},
});
Card component has 2 props for styling. containerStyle is used to style the outer container while wrapperStyle for inner container. In your code you should replace containerStyle with wrapperStyle
<Card wrapperStyle={{ flexDirection: "row", backgroundColor: '#3D3D3D', marginTop: 10, paddingBottom: 30, padding: 30, borderWidth: 0, borderTopWidth: 1, borderBottomWidth: 1, elevation: 0, borderColor: '#212121' }}>
<Image style={{ width: 25, height: 25 }} source={require('./assets/yellow-dark.png')} />
<Card.Title style={{ color: '#FFFFFF' }} >Yellow / Dark</Card.Title>
</Card>
Note: You can adjust the other attributes in both the styles as per your need.

Reac-Native: hexagon with border

in my react native app I want to have a bordered hexagon, I'm trying to achive this by having two hexagons one before the other, however for the bigger hexagon(2) I can't seem to get the proper dimensions, I got the first hexagon from a post in this blessed site, can anyone help me?
<View style={{width:125,height:125,position:'relative',alignItems:'center',justifyContent:'center'}}>
<View style={styles.hexagon2}>
<View style={styles.hexagonInner2}>
<View style={styles.hexagonBefore2}></View>
</View>
<View style={styles.hexagonAfter2}></View>
</View>
<View style={{width:125,height:125,position:'absolute',top:0,left:0,alignItems:'center',justifyContent:'center'}}>
<View style={styles.hexagon}>
<View style={styles.hexagonInner}>
<View style={styles.hexagonBefore}></View>
</View>
<View style={styles.hexagonAfter}></View>
</View>
</View>
</View>
Hexagon styles:
const styles = StyleSheet.create({
//this one is the small hexagon, no need to touch this one
hexagon: {
width: 100,
height: 55
},
hexagonInner: {
width: 100,
height: 55,
backgroundColor: 'rgb(1,121,111)'
},
hexagonAfter: {
position: 'absolute',
bottom: -25,
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: 50,
borderLeftColor: 'transparent',
borderRightWidth: 50,
borderRightColor: 'transparent',
borderTopWidth: 25,
borderTopColor: 'rgb(1,121,111)'
},
hexagonBefore: {
position: 'absolute',
top: -25,
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: 50,
borderLeftColor: 'transparent',
borderRightWidth: 50,
borderRightColor: 'transparent',
borderBottomWidth: 25,
borderBottomColor: 'rgb(1,121,111)'
},
//This ine is the bigger hexagon, the border
hexagon2: {
width: 100,
height: 55,
},
hexagonInner2: {
width: 100,
height: 55,
backgroundColor: 'rgb(1,121,111)',
},
hexagonAfter2: {
position: 'absolute',
bottom: -25,
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: 50,
borderLeftColor: 'transparent',
borderRightWidth: 50,
borderRightColor: 'transparent',
borderTopWidth: 25,
borderTopColor: 'red'
},
hexagonBefore2: {
position: 'absolute',
top: -25,
left: 0,
width: 0,
height: 0,
borderStyle: 'solid',
borderLeftWidth: 50,
borderLeftColor: 'transparent',
borderRightWidth: 50,
borderRightColor: 'transparent',
borderBottomWidth: 25,
borderBottomColor: 'red'
}
});
You can do this with the library react-native-svg which lets you make complicated shapes. Example I made here (https://snack.expo.dev/#heytony01/blissful-coffee)
and code below.
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import Svg, { Polygon } from 'react-native-svg';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
const Hexagon = () =>{
return (
<Svg height="300" width="300" >
<Polygon
points="00,150 225,280 75,280 0,150 75,20 225,20 300,150 225,280 75,280 0,150 75,20 225,20 300,150 225,280 75,280 0,150, 75 20 225,20"
fill="lime"
stroke="lime"
strokeWidth="1"
>
</Polygon>
</Svg>
)
}
export default function App() {
return (
<View style={{flex:1,justifyContent:"center",alignItems:"center"}}>
<Hexagon />
</View>
);
}

On react native when I put an if statment in the render section checking the value of a variable I get an error

I am trying to load the font by having so that when you press a button, your font will load. When I put the if statement in the render section, I get an error saying that:
RawText "if (fontLoaded=="true")" must be wrapped in an explicit text component. Please help me solve this, I am very confused.
I am very new to react native so this may be a very basic question, I am sorry.
My code is below:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, TextInput, ScrollView, TouchableHighlight, Button } from 'react-native';
import { Font } from 'expo';
var fontLoaded = false;
export default class App extends React.Component {
componentDidMount() {
Expo.Font.loadAsync({
'Cabin-Regular-TTF': require('./Cabin-Regular-TTF.ttf'),
});
}
constructor(props) {
super(props);
this.state = { postInput: ""}
}
render() {
return (
<View style={styles.container}>
<View style={{width: 1, height: 30, backgroundColor: '#e8e8e8'}} />
<Button
onPress={this.setState({ fontLoaded: true })}
title="Press Me To Load the App After 15 Seconds!"
color="#841584"
accessibilityLabel="Wait 15 seconds and then press me to load the font!"
/>
if (fontLoaded=="true") {
<View style={styles.container}>
<Text style={{ fontFamily: 'Cabin-Regular-TTF', fontSize: 16 }}>
Whats on your mind? Create a post!
</Text>
<TextInput>
tyle={{height:40, width: 320, borderColor: '#303030', borderWidth: 1}}
onChangeText={(postInput)=>this.setState({postInput})}
value={this.state.postInput}
</TextInput>
<ScrollView>
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
</ScrollView>
</View>
}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#e8e8e8',
alignItems: 'center',
justifyContent: 'center',
},
});
The problem is that you're trying to use raw javascript inside your html. You can't use the regular if statement inside the render() function but you can use the inline conditional statement like this:
{isTrue ? (<div>True</div>) : (<div>False</div>)}
Read more about it here
In your case it'll be something like this:
render() {
return (
{/*your code as usual*/}
{fontLoaded ? (
<View style={styles.container}>
{/*your code as usual*/}
</View>) :
null}
Use && to achieve the same result. You have to use JSX condition inside the render method. You can write your if condition like below.
{fontLoaded &&
<View style={styles.container}>
<Text style={{ fontFamily: 'Cabin-Regular-TTF', fontSize: 16 }}>
Whats on your mind? Create a post!
</Text>
<TextInput>
style={{height:40, width: 320, borderColor: '#303030', borderWidth: 1}}
onChangeText={(postInput)=>this.setState({postInput})}
value={this.state.postInput}
</TextInput>
<ScrollView>
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
</ScrollView>
</View>
}

If statement: SyntaxError Unexpected token, expected ,

In react native I am trying to put some code that will load the font after pressing a button. The if statement is getting an error (line 38:6) that says, Unexpected token, expected , (38:6). I have no idea why this is happening, and I don't know where to put the comma it wants, or if the problem is something else.
error message
Line 38
Updated code:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, TextInput, ScrollView, TouchableHighlight, Button } from 'react-native';
import { Font } from 'expo';
var fontLoaded = false;
export default class App extends React.Component {
componentDidMount() {
Expo.Font.loadAsync({
'Cabin-Regular-TTF': require('./Cabin-Regular-TTF.ttf'),
});
}
constructor(props) {
super(props);
this.state = { postInput: ""}
}
render() {
return (
<View style={styles.container}>
<View style={{width: 1, height: 30, backgroundColor: '#e8e8e8'}} />
<Button
onPress={() => this.setState({ fontLoaded: true })}
title="Press Me To Load the App After 15 Seconds!"
color="#841584"
accessibilityLabel="Wait 15 seconds and then press me to load the font!"
/>
</View>
{fontLoaded ? (
<View style={styles.container}>
<Text style={{ fontFamily: 'Cabin-Regular-TTF', fontSize: 16 }}>
Whats on your mind? Create a post!
</Text>
<TextInput>
style={{height:40, width: 320, borderColor: '#303030', borderWidth: 1}}
onChangeText={(postInput)=>this.setState({postInput})}
value={this.state.postInput}
</TextInput>
<ScrollView>
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
</ScrollView>
</View>) : (null) }
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#e8e8e8',
alignItems: 'center',
justifyContent: 'center'
},
});
The component's template must have exactly one top-level container. So I put your component between an enclosing tag and the error's gone:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, TextInput, ScrollView, TouchableHighlight, Button } from 'react-native';
import { Font } from 'expo';
var fontLoaded = false;
export default class App extends React.Component {
componentDidMount() {
Expo.Font.loadAsync({
'Cabin-Regular-TTF': require('./Cabin-Regular-TTF.ttf'),
});
}
constructor(props) {
super(props);
this.state = { postInput: ""}
}
render() {
return (
<View>
<View style={styles.container}>
<View style={{width: 1, height: 30, backgroundColor: '#e8e8e8'}} />
<Button
onPress={this.setState({ fontLoaded: true })}
title="Press Me To Load the App After 15 Seconds!"
color="#841584"
accessibilityLabel="Wait 15 seconds and then press me to load the font!"
/>
</View>
{fontLoaded ? (
<View style={styles.container}>
<Text style={{ fontFamily: 'Cabin-Regular-TTF', fontSize: 16 }}>
Whats on your mind? Create a post!
</Text>
<TextInput>
style={{height:40, width: 320, borderColor: '#303030', borderWidth: 1}}
onChangeText={(postInput)=>this.setState({postInput})}
value={this.state.postInput}
</TextInput>
<ScrollView>
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
</ScrollView>
</View>) : (null) }
</View>
);
}
} // missing one!
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#e8e8e8',
alignItems: 'center',
justifyContent: 'center'
},
});
Also, you have missed closing } at the end of class definition. I marked it with a comment.
try
{
fontLoaded && (
<View style={styles.container}>
....
</View>
)
}
I also see problem in your onPress - it should be
onPress={() => this.setState({ fontLoaded: true })}
Why don't you refactor your code and move all the scrollView code to new function,
e.g:
renderScrollWrapper() {
retun(
<View style={styles.container}>
<Text style={{ fontFamily: 'Cabin-Regular-TTF', fontSize: 16 }}>
Whats on your mind? Create a post!
</Text>
<TextInput>
style={{height:40, width: 320, borderColor: '#303030', borderWidth: 1}}
onChangeText={(postInput)=>this.setState({postInput})}
value={this.state.postInput}
</TextInput>
<ScrollView>
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
<View style={{width: 300, height: 250, backgroundColor: '#1daff1'}} />
<View style={{width: 300, height: 40, backgroundColor: '#147aa8'}} />
<View style={{width: 1, height: 6, backgroundColor: '#e8e8e8'}} />
</ScrollView>
</View>);
}
Then change your render method to,
render() {
return (
<View>
<View style={styles.container}>
<View style={{width: 1, height: 30, backgroundColor: '#e8e8e8'}} />
<Button
onPress={this.setState({ fontLoaded: true })}
title="Press Me To Load the App After 15 Seconds!"
color="#841584"
accessibilityLabel="Wait 15 seconds and then press me to load the font!"
/>
</View>
{fontLoaded ? {this.renderScrollWrapper()} : (null) }
</View>
);
}

React Native Map Renders On Top Of Everything

I am working on a little map application using react-native-maps. I am trying to render a floating action button on top of the map, but while I do see it flashing for a second, as soon as the map renders, it sits right on top of the button. I will paste my render code and styles below:
render() {
return (
<View style={{flex:1, backgroundColor: '#f3f3f3'}}>
<MapView ref="map" mapType="terrain" style={styles.map} region={this.state.region} onRegionChange={this.onRegionChange}>
<MapView.Marker coordinate={{latitude: this.state.region.latitude, longitude: this.state.region.longitude}}>
<View style={styles.radius}>
<View style={styles.marker} />
</View>
</MapView.Marker>
</MapView>
<ActionButton buttonColor="rgba(231,76,60,1)" style={styles.actionButton}>
<ActionButton.Item buttonColor='#9b59b6' title="New Task" onPress={() => console.log("notes tapped!")}>
<Icon name="rocket" style={styles.actionButtonIcon} />
</ActionButton.Item>
<ActionButton.Item buttonColor='#3498db' title="Notifications" onPress={() => {}}>
<Icon name="rocket" style={styles.actionButtonIcon} />
</ActionButton.Item>
<ActionButton.Item buttonColor='#1abc9c' title="All Tasks" onPress={() => {}}>
<Icon name="rocket" style={styles.actionButtonIcon} />
</ActionButton.Item>
</ActionButton>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
map: {
width: width,
height: height,
zIndex: 998
},
radius: {
height: 50,
width: 50,
borderRadius: 50 / 2,
overflow: 'hidden',
backgroundColor: 'rgba(0, 122, 255, 0.1)',
borderWidth: 1,
borderColor: 'rgba(0, 122, 255, 0.3)',
alignItems: 'center',
justifyContent: 'center'
},
marker: {
height: 20,
width: 20,
borderWidth: 3,
borderColor: 'white',
borderRadius: 20 / 2,
overflow: 'hidden',
backgroundColor: '#007AFF'
},
actionButton: {
position: 'absolute',
width: 20,
height: 20,
top: 10,
left: 10,
zIndex: 999
},
actionButtonIcon: {
fontSize: 20,
height: 22,
color: 'white'
}
});
I had the same problem. I solved it by giving the map a negative z-index. Also, I used flex: 1, instead of width and height, but that shouldn't make a difference.
Like:
map: {
width: width,
height: height,
zIndex: -1
},
actionButton: {
position: 'absolute',
width: 20,
height: 20,
top: 10,
left: 10,
zIndex: 10
},
<Pressable style={{
zIndex: 5
flex: 1,
flexDirection:'row',
padding: 10,
position:'absolute',
bottom:"25%",
alignSelf: "center",
justifyContent: "space-between",
backgroundColor: '#4DDB81',
borderWidth: 0.5,
borderRadius: 10,
}}>
<Text style={{
fontSize: 30,
color: "#383838"
}}>Pressable
it is a long shot but try to add position: 'absolute' to your map styles and set its coordinates and see what happens

Categories