I've found this weird behavior in IOS (both on the simulator and on a real device, but I only have screenshots from the simulator) where on input to the TextInput component, it puts a weird highlight behind the text you input. I've referenced this (since closed) issue: https://github.com/facebook/react-native/issues/7070
And I've scoured the docs (https://facebook.github.io/react-native/docs/textinput) for an answer to this, but can't quite seem to come up with any answers. I thought I was close with the selectTextOnFocus prop, but I set that to false and nothing changed (the behavior remained).
I have also tried setting textDecorationColor and textShadowColor to transparent, to no avail. I am really at a loss of what to do right now.
Here is the code I have for the input:
import React from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export class GeneralInput extends React.Component {
constructor(props) {
super(props);
this.state = {
placeholder: this.props.placeholder,
inputValue: "",
inputting: false,
};
}
whenInputIsFocused() {
this.setState({placeholder: ""});
}
whenInputIsBlurred() {
if (this.state.inputValue === "") {
this.setState({placeholder: this.props.placeholder});
}
}
focusNextField(nextField) { this.refs[nextField].focus(); }
render() {
const autoFocus = this.props.autoFocus == 'true';
const multiline = this.props.multiline == 'true';
return(
<View style={styles.outerContainer}>
<Text style={styles.labelText}>{this.props.labelText}</Text>
<TextInput
autoCapitalize='none'
autoFocus={autoFocus}
onChangeText={(inputValue) => this.setState({inputValue})}
value={this.state.inputValue}
secureTextEntry={this.props.secureTextEntry}
onBlur={this.whenInputIsBlurred.bind(this)}
onFocus={this.whenInputIsFocused.bind(this)}
underlineColorAndroid="transparent"
keyboardType={this.props.type}
returnKeyType={this.props.returnKeyType}
placeholder={this.state.placeholder}
placeholderTextColor='rgba(255, 255, 255, 0.3)'
multiline={multiline}
selectTextOnFocus={false}
onSubmitEditing={() => {this.focusNextField(this.props.ref)}}
blurOnSubmit={(this.props.moveAlongType === 'next') ? false : true}
style={styles.inputStyles} />
</View>
);
}
}
const styles = StyleSheet.create({
outerContainer: {
justifyContent: 'center',
alignItems: 'flex-start',
width: '90%',
marginBottom: 20,
},
labelText: {
fontFamily: 'rubik-bold',
fontSize: 14,
fontWeight: 'bold',
color: '#fff',
marginBottom: 5,
},
inputStyles: {
height: 40,
borderRadius: 2,
backgroundColor: 'rgba(255, 255, 255, 0.3);',
shadowColor: 'rgba(0, 0, 0, 0.15)',
shadowOffset: {width: 0,height: 2},
shadowOpacity: 0,
shadowRadius: 0,
width: '100%',
textDecorationColor: 'transparent',
fontSize: 14,
color: '#fff',
paddingLeft: 15,
fontFamily: 'rubik-bold',
},
});
And here are the screenshots of what is actually happening (the first screenshot is with the highlight, the second is just the input with the placeholder text for reference):
So the question is...how do I make that weird highlight go away on ios?
Text is not getting selected, it is just the background color you have given in the style.
Just remove the background color from the style of the <TextInput />
So, as per #Siraj the reason this odd behavior was happening was because the background color I had applied to the <TextInput /> component was also being applied to the text being inputed. So, I wrapped the <TextInput /> in a <View />, applied the height, width, backgroundColor, shadow, and borderRadius props to the surrounding <View />, and it has the desired effect! See the code below:
import React from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';
export class GeneralInput extends React.Component {
constructor(props) {
super(props);
this.state = {
placeholder: this.props.placeholder,
inputValue: "",
inputting: false,
};
}
whenInputIsFocused() {
this.setState({placeholder: ""});
}
whenInputIsBlurred() {
if (this.state.inputValue === "") {
this.setState({placeholder: this.props.placeholder});
}
}
focusNextField(nextField) { this.refs[nextField].focus(); }
render() {
const autoFocus = this.props.autoFocus == 'true';
const multiline = this.props.multiline == 'true';
return(
<View style={styles.outerContainer}>
<Text style={styles.labelText}>{this.props.labelText}</Text>
<View style={styles.inputContainer}> // added View
<TextInput
autoCapitalize='none'
autoFocus={autoFocus}
onChangeText={(inputValue) => this.setState({inputValue})}
value={this.state.inputValue}
secureTextEntry={this.props.secureTextEntry}
onBlur={this.whenInputIsBlurred.bind(this)}
onFocus={this.whenInputIsFocused.bind(this)}
underlineColorAndroid="transparent"
keyboardType={this.props.type}
returnKeyType={this.props.returnKeyType}
placeholder={this.state.placeholder}
placeholderTextColor='rgba(255, 255, 255, 0.3)'
multiline={multiline}
selectTextOnFocus={false}
onSubmitEditing={() => {this.focusNextField(this.props.ref)}}
blurOnSubmit={(this.props.moveAlongType === 'next') ? false : true}
style={styles.inputStyles} />
</View> // Closing the added View
</View>
);
}
}
const styles = StyleSheet.create({
outerContainer: {
justifyContent: 'center',
alignItems: 'flex-start',
width: '90%',
marginBottom: 20,
},
labelText: {
fontFamily: 'rubik-bold',
fontSize: 14,
fontWeight: 'bold',
color: '#fff',
marginBottom: 5,
},
inputContainer: { // added styles
height: 40,
width: '100%',
backgroundColor: 'rgba(255, 255, 255, 0.3);',
shadowColor: 'rgba(0, 0, 0, 0.15)',
shadowOffset: {width: 0,height: 2},
shadowOpacity: 0,
shadowRadius: 0,
borderRadius: 2,
},
inputStyles: {
height: '100%',
width: '100%',
fontSize: 14,
color: '#fff',
paddingLeft: 15,
fontFamily: 'rubik-bold',
},
});
Related
i am facing a problem regarding async storage in react native .
when i setItem in async storage and then retrieve it if there are 3 tasks- which i have added,
only two of them is retrieved
i will share a photo of before and after
this is output before refreshing
this is the output after refreshing the app
This is my app.js code
import { StatusBar } from 'expo-status-bar';
import {
StyleSheet,
Text,
View,
KeyboardAvoidingView,
FlatList,
TextInput,
TouchableOpacity,
Keyboard,
} from 'react-native';
import React, { Component } from 'react';
import * as Font from 'expo-font';
import Task from './components/Task';
import AppLoading from 'expo-app-loading';
import AsyncStorage from '#react-native-async-storage/async-storage';
let customFonts = {
Poppins_SemiBold: require('./assets/Poppins-SemiBold.ttf'),
Poppins_Regular: require('./assets/Poppins-Regular.ttf'),
};
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
task: '',
taskItems: [],
fontsLoaded: false,
};
}
async _loadFontsAsync() {
await Font.loadAsync(customFonts);
this.setState({ fontsLoaded: true });
}
componentDidMount() {
this._loadFontsAsync();
this._retrieveData()
}
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('data');
if (value.length !== 2) {
// We have data!!
this.setState({taskItems:[...JSON.parse(value)]})
console.log(value);
}
} catch (error) {
// Error retrieving data
console.log(error)
}
};
handleAddTask=()=>{
Keyboard.dismiss()
this.setState({taskItems:[...this.state.taskItems,this.state.task]})
this.setState({task:''})
AsyncStorage.setItem('data',JSON.stringify(this.state.taskItems))
}
deleteItem=(index)=>{
try {
let arr = [...this.state.taskItems];
arr.splice(index, 1);
this.setState({taskItems:arr})
AsyncStorage.setItem('data',JSON.stringify(arr))
} catch (err) {
console.log(err);
}
}
render() {
if (!this.state.fontsLoaded) {
return <AppLoading />;
}
return (
<View style={styles.container}>
{/* Todays Tasks */}
<View style={styles.taskWrapper}>
<Text style={styles.sectionTitle}>Today's Tasks</Text>
<View style={styles.items}>
{/* This is where the tasks will go! */}
<FlatList
data={this.state.taskItems}
keyExtractor={(item) => item}
renderItem={({ item, index }) => (
<Task text={item} handleDelete={() => this.deleteItem(index)} />
)}
/>
</View>
</View>
{/* Write a Task */}
<KeyboardAvoidingView style={styles.writeTaskWrapper}>
<TextInput
style={styles.input}
placeholder={'Write A Task!'}
onChangeText={(text) => {
this.setState({ task: text });
}}
value={this.state.task}
/>
<TouchableOpacity
onPress={() => {
this.handleAddTask();
}}>
<View style={styles.addWrapper}>
<Text style={styles.addText}>+</Text>
</View>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#E8EAED',
},
taskWrapper: {
paddingTop: 80,
paddingHorizontal: 20,
},
sectionTitle: {
fontSize: 24,
backgroundColor: '#fff',
fontFamily: 'Poppins_SemiBold',
borderRadius: 10,
margin: 'auto',
width: 250,
height: 60,
textAlign: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.2,
shadowRadius: 2,
elevation: 5,
paddingTop: 10,
},
items: {
marginTop: 30,
},
writeTaskWrapper: {
position: 'absolute',
bottom: 60,
width: '100%',
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
},
input: {
paddingVertical: 15,
paddingHorizontal: 15,
backgroundColor: '#fff',
borderRadius: 60,
width: 250,
fontFamily: 'Poppins_Regular',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 3,
},
addWrapper: {
width: 60,
height: 60,
backgroundColor: '#fff',
borderRadius: 60,
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 3,
},
addText: {},
});
and this is my task.js code which is a component:
import React from 'react';
import {
View,
Text,
StyleSheet,
Dimensions,
Animated,
TouchableOpacity,
} from 'react-native';
import AppLoading from 'expo-app-loading';
import {
Poppins_100Thin,
Poppins_100Thin_Italic,
Poppins_200ExtraLight,
Poppins_200ExtraLight_Italic,
Poppins_300Light,
Poppins_300Light_Italic,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_500Medium_Italic,
Poppins_600SemiBold,
Poppins_600SemiBold_Italic,
Poppins_700Bold,
Poppins_700Bold_Italic,
Poppins_800ExtraBold,
Poppins_800ExtraBold_Italic,
Poppins_900Black,
Poppins_900Black_Italic,
} from '#expo-google-fonts/poppins';
import { useFonts } from 'expo-font';
import Swipeable from 'react-native-gesture-handler/Swipeable';
const SCREEN_WIDTH = Dimensions.get('window').width;
const Task = (props) => {
let [fontsLoaded, error] = useFonts({
Poppins_100Thin,
Poppins_100Thin_Italic,
Poppins_200ExtraLight,
Poppins_200ExtraLight_Italic,
Poppins_300Light,
Poppins_300Light_Italic,
Poppins_400Regular,
Poppins_400Regular_Italic,
Poppins_500Medium,
Poppins_500Medium_Italic,
Poppins_600SemiBold,
Poppins_600SemiBold_Italic,
Poppins_700Bold,
Poppins_700Bold_Italic,
Poppins_800ExtraBold,
Poppins_800ExtraBold_Italic,
Poppins_900Black,
Poppins_900Black_Italic,
});
if (!fontsLoaded) {
return <AppLoading />;
}
const leftSwipe = (progress, dragX) => {
const scale = dragX.interpolate({
inputRange: [0, 100],
outputRange: [0, 1],
extrapolate: 'clamp',
});
return (
<TouchableOpacity onPress={props.handleDelete} activeOpacity={0.6}>
<View style={styles.deleteBox}>
<Animated.Text
style={{
transform: [{ scale: scale }],
color: '#fff',
fontFamily: 'Poppins_400Regular',
fontSize: 18,
}}>
Delete
</Animated.Text>
</View>
</TouchableOpacity>
);
};
return (
<Swipeable renderLeftActions={leftSwipe}>
<View style={styles.item}>
<View style={styles.itemLeft}>
<View style={styles.square}></View>
<Text style={styles.itemText}>{props.text}</Text>
</View>
<View style={styles.circular}></View>
</View>
</Swipeable>
);
};
const styles = StyleSheet.create({
item: {
backgroundColor: 'white',
padding: 15,
borderRadius: 10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 3,
},
itemLeft: {
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap',
},
square: {
width: 24,
height: 24,
backgroundColor: '#55BCF6',
opacity: 0.5,
borderRadius: 5,
marginRight: 15,
},
itemText: {
maxWidth: '80%',
fontFamily: 'Poppins_400Regular',
},
circular: {
width: 12,
height: 12,
borderColor: '#55BCF6',
borderWidth: 2,
borderRadius: 5,
},
deleteBox: {
backgroundColor: 'red',
justifyContent: 'center',
alignItems: 'center',
width: 100,
height: 55,
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.5,
shadowRadius: 2,
elevation: 5,
},
});
export default Task;
Due to React internal state update implementation, update Async storage run before new state updated. It's recommended to run asynchronous code before updating the state.
To solve the issue, refactor your code as below:
handleAddTask= async ()=>{
Keyboard.dismiss()
const updatedTaskItems = [...this.state.taskItems,this.state.task]
await AsyncStorage.setItem('data',JSON.stringify(updatedTaskItem))
this.setState({taskItems:updatedTaskUtems,task:''})
}
I am having trouble getting these two forms to just show the number input from my Virtualized Keyboard. Essentially what is going on here is that I have a numeric keypad passing in the numbers from the virtualized keyboard and a currency component to be able to have the currency format (thousand commas, and decimals).
Here is the UI for better idea of what I'm trying to explain.
When I press the keypad it says this:
This is the error I get
Here is my code:
import React, { useState, useEffect, useCallback } from "react";
import {
ScrollView,
StyleSheet,
Image,
TouchableWithoutFeedback,
ImageBackground,
Dimensions,
View,
StatusBar,
SafeAreaView,
TextInput,
Keyboard
} from "react-native";
import { Block, Text, theme } from "galio-framework";
import VirtualKeyboard from 'react-native-virtual-keyboard';
import CurrencyInput from '../components/CurrencyInput';
import Button from '../components/Button'
import { HeaderHeight } from "../constants/utils";
const { height, width } = Dimensions.get("screen");
const Give = () => {
const [value, setValue] = useState(0);
const handleValueChange = useCallback(val => {
// eslint-disable-next-line
console.log(val);
setValue(val);
}, []);
return (
<View style={style.container}>
<SafeAreaView>
<Block style={style.allContainer}>
<Block style={style.numberContainer}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss()} accessible={false} >
<CurrencyInput
max={100000000}
onValueChange={handleValueChange}
style={style.inputNumber}
value={value}
/>
</TouchableWithoutFeedback>
</Block>
<VirtualKeyboard color='#000' pressMode='string' onPress={(val) => setValue(val)} />
<Button style={style.button}><Text style={style.buttonText}>Ofrendar</Text></Button>
</Block>
</SafeAreaView>
</View>
)
}
const style = StyleSheet.create({
container: {
marginTop: Platform.OS === 'android' ? -HeaderHeight : 0,
height: height,
flex: 1,
flexDirection: 'row',
backgroundColor: "#fff",
width: width
},
backgroundImage: {
width: width,
flex: 1,
resizeMode: "cover",
},
animationContainer: {
},
animationImage: {
height: 250,
aspectRatio: 1,
alignSelf: "center",
},
ofrenda: {
fontSize: 55,
textAlign: "center",
fontWeight: "bold",
marginBottom: 70
},
buttonText: {
color: "#FFF",
fontSize: 30,
fontWeight: "bold",
letterSpacing: 2
},
button: {
height: 60,
width: width - theme.SIZES.BASE * 6,
marginBottom: 30,
marginTop: 30,
backgroundColor: "#00a8ff",
borderWidth: 3,
borderRadius: 10,
borderColor: "#00a8ff",
shadowColor: "transparent"
},
bottomButton: {
position: 'absolute',
bottom: 30
},
numberContainer: {
},
inputNumber: {
fontSize: 50,
fontWeight: "bold"
},
allContainer: {
justifyContent: "center",
alignItems: "center",
height: height,
width: width,
alignSelf: "center"
}
});
export default Give;
I am new to react native and firebase. I want to make a search bar that can search all data from firebase according to Barcode value, but I'm facing some errors while doing it. I think that my code is wrong somewhere but don't know where. I have transferred the firebase credentials to dbConfig.js . Here is my firebase data firebase data and my code:
import React,{Component} from 'react';
import { View, Text,TextInput,StyleSheet,Image, Button} from 'react-native';
import firebase from './dbConfig';
export default class ListItem extends Component {
render() {
return (
<>
<View style={styles.BackGround}>
<View style={styles.SectionStyle}>
<Image
source={require('./mic.png')} //mic image here
style={styles.ImageStyle}
/>
<TextInput
style={{ flex: 1, justifyContent: 'center', textAlign: 'center', fontSize: 12}}
placeholder="Search for Product"
underlineColorAndroid="transparent"
//onChangeText={(text) => this.setState({data: text})}
onSubmitEditing = {(text)=> this.setState({data: text})}
value = {this.state.data}
// onSubmitEditing={()=>this._search}
//onSubmitEditing={()=>this.componentWillMount}
/>
<Image
source={require('./usr.png')} //icon image here
style={styles.ImageStyle2}
/>
</View>
<View>
<Text>{this.state.items}</Text>
</View>
</View>
</>
);
}
constructor(props){
super(props);
this.state= {
items: '',
data: '',
};
}
componentWillMount(){
var ref = firebase.database().ref('/');
ref.child(this.state.data).on("value", snapshot =>{
console.log(snapshot.val().info.Price);
//if(snapshot.val().Price == this.state.data){
//this.setState({items: Object.values(snapshot.val())});
//}
//else{
//alert('there is problem');
//}
});
}
}
const styles = StyleSheet.create({
BackGround: {
backgroundColor: '#22abb6',
height: '100%'
},
SectionStyle: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
// borderWidth: 0.8,
// borderColor: '#000',
shadowColor:'#176f75',
marginTop: 50,
height: 40,
borderRadius: 10,
margin: 10,
},
ImageStyle: {
padding: 10,
marginLeft: 10,
margin: 5,
height: 25,
width: 25,
resizeMode: 'stretch',
alignItems: 'center',
},
ImageStyle2: {
padding: 10,
marginLeft: 10,
marginRight: 10,
margin: 5,
height: 25,
width: 25,
resizeMode: 'stretch',
alignItems: 'center',
},
});
I did it by changing the follows:
//adding this in TextInput
onSubmitEditing = {this.componentWillMount}
//on changing the function compoundWillMount to async()
componentWillMount= async()=>{
I am using react-native-simple-picker in my app which works fine in my project if I use the default show button but I would like to show the picker when I use a different button in my project. It looks like this.refs.picker.show() in ProposalPicker.js is the function that needs to be called, but I am not sure how to access this from another component file. Currently my code results in the following error - `Cannot read property 'show' of undefined. Appreciate any help.
ProposalPicker.js
import React, { Component } from 'react';
import { Picker, View, Text } from 'react-native';
import Button from './Button';
import SimplePicker from 'react-native-simple-picker';
const options = ['Option1', 'Option2', 'Option3'];
// Labels is optional
const labels = ['Banana', 'Apple', 'Pear'];
class ProposalPicker extends Component {
constructor(props) {
super(props);
this.state = {
selectedOption: '',
};
}
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>Current Option: {this.state.selectedOption}</Text>
<Text
style={{ color: '#006381', marginTop: 20 }}
onPress={() => {
this.refs.picker.show();
}}
>
Click here to select your option
</Text>
<Text
style={{ color: '#006381', marginTop: 20 }}
onPress={() => {
this.refs.picker2.show();
}}
>
Click here to select your option with labels
</Text>
<SimplePicker
ref={'picker'}
options={options}
onSubmit={(option) => {
this.setState({
selectedOption: option,
});
}}
/>
<SimplePicker
ref={'picker2'}
options={options}
labels={labels}
itemStyle={{
fontSize: 25,
color: 'red',
textAlign: 'left',
fontWeight: 'bold',
}}
onSubmit={(option) => {
this.setState({
selectedOption: option,
});
}}
/>
</View>
);
}
}
// class ProposalPicker extends Component {
// state={proposal: ''}
// selectedValue = '';
// updateProposal = (proposal) => {
// this.setState({ proposal: this.selectedValue });
// }
// handleConfirmClick = () => {
// this.setState({ proposal: this.selectedValue });
// }
// render() {
// return (
// <View>
// <Picker selectedValue = {this.selectedValue}
// onValueChange = {this.updateProposal}
// itemStyle={{ backgroundColor: 'grey' }}
// >
// <Picker.Item label = "Test" value = "TestValue1" />
// <Picker.Item label = "Test 1" value = "TestValue2" />
// <Picker.Item label = "Test" value = "TestValue3" />
// <Picker.Item label = "Test" value = "TestValue4" />
// <Picker.Item label = "Test" value = "TestValue5" />
// <Picker.Item label = "Test" value = "TestValue6" />
// <Picker.Item label = "Test" value = "TestValue7" />
// <Picker.Item label = "Test" value = "TestValue8" />
// <Picker.Item label = "Test nothing" value = "TestValue9" />
// </Picker>
// <Text style = {styles.textStyle}>CONFIRM</Text>
// </View>
// )
// }
// }
const styles = {
proposalPickerStyle: {
backgroundColor: 'lightgrey'
},
textStyle: {
flex: 1
}
}
export default ProposalPicker;
ProposalPickerButton.js
import React from 'react';
import { View, Text, Image, TouchableOpacity } from 'react-native';
const PickerButton = ({ onPress, text }) => {
const { textStyle, iconStyle, iconContainerStyle, textContainerStyle, buttonStyle } = styles;
return (
<TouchableOpacity onPress={onPress} style={buttonStyle}>
<View style={styles.containerStyle}>
<View style={iconContainerStyle}>
<Image
style={iconStyle}
source={require('./images/201.png')}
/>
</View>
<View style={textContainerStyle}>
<Text style={textStyle}>{text}</Text>
</View>
<View style={iconContainerStyle}>
<Image
style={iconStyle}
source={require('./images/201.png')}
/>
</View>
</View>
</TouchableOpacity>
);
}
const styles = {
containerStyle: {
flex: 1,
//backgroundColor: 'red',
borderWidth: 2,
borderRadius: 0,
borderColor: '#FFFFFF',
//shadowColor: '#000',
//shadowOffset: { width: 0, height: 2 },
//shadowOpacity: 0.1,
//shadowRadius: 2,
//elevation: 1,
marginLeft: 40,
marginRight: 40,
marginTop: 10,
marginBottom: 10,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row'
},
iconContainerStyle: {
flex: 2,
//backgroundColor: 'blue',
justifyContent: 'center',
//alignItems: 'center',
//width: '20%',
//height: '20%'
},
iconStyle: {
flex: 1,
width: null,
height: null,
resizeMode: 'contain',
marginLeft: 10,
marginRight: 10,
marginTop: 10,
marginBottom: 10
},
textContainerStyle: {
flex: 8,
//backgroundColor: 'orange',
alignItems: 'flex-start',
justifyContent: 'center',
},
textStyle: {
fontSize: 20,
fontWeight: 'bold',
color: '#FFFFFF',
//marginLeft: 10
//padding: 18
},
buttonStyle: {
width: '100%',
height: '100%'
}
};
export default PickerButton;
App.js
import React, { Component } from 'react';
import { View, Text, ImageBackground } from 'react-native';
import Logo from './Logo';
import ProposalPickerButton from './ProposalPickerButton';
import Button from './Button';
import ProposalPicker from './ProposalPicker';
import SimplePicker from 'react-native-simple-picker';
class App extends Component {
render() {
return (
<ImageBackground
source={require('./images/city.png')}
style={styles.backgroundStyle}
>
<View style={styles.backgroundOverlayStyle} />
<View style={styles.container}>
<View style={styles.logoContainer}>
<Logo />
</View>
<View style={styles.proposalPickerButtonStyle}>
<ProposalPickerButton
onPress={() => new ProposalPicker().refs.picker.show()}
// onPress={() => console.log('Proposal picker button pressed')}
//onPress={() => Linking.openURL(url)}
text="Select a service line"
/>
</View>
<View style={styles.startProposalButtonStyle}>
<Button text="Start proposal"/>
</View>
<View style={styles.proposalPickerStyle}>
{/* <ProposalPicker /> */}
</View>
</View>
</ImageBackground>
);
}
}
const styles = {
backgroundStyle: {
flex: 1,
backgroundColor: '#000000',
width: '100%',
height: '100%',
position: 'absolute'
},
backgroundOverlayStyle: {
flex: 1,
position: 'absolute',
backgroundColor: '#003284',
opacity: 0.5,
width: '100%',
height: '100%'
},
container: {
//backgroundColor: 'red',
flex: 1,
//opacity: 0.5,
alignItems: 'center',
width: '100%',
height: '65%',
},
logoContainer: {
//backgroundColor: 'blue',
flex: 3,
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '65%',
},
proposalPickerButtonStyle: {
flex: 1,
//backgroundColor: 'yellow',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
marginLeft: 100,
marginRight: 100
},
startProposalButtonStyle: {
flex: 1,
//backgroundColor: 'purple',
width: '100%',
height: '100%',
marginTop: 10,
marginRight: 80
},
proposalPickerStyle: {
opacity: 1,
flex: 2,
backgroundColor: 'green',
width: '100%',
height: '100%'
},
};
export default App;
To call methods via refs you need to have a ref assigned to an already mounted component. Therefore you can't say new ProposalPicker().refs.picker.show() because refs.picker does not exist until the component is mounted. You Should have your button and picker components in the same parent, that way you can easily create a ref in that parent, assign it, and call methods from it:
Also you should use callback refs instead of string refs because string refs are deprecated. In that case it would look like:
constructor(props){
super(props)
this.state = ...
this.picker = React.createRef() // make the ref
}
Then assign the ref:
<SimplePicker
ref={this.picker}
And then you can make an function to call when your button is pressed:
showPicker = () => {
if (this.picker.current) {
this.picker.current.show()
}
}
I am trying to place an Avatar element over my TextInput so that it will look like a conventional search bar, but it doesn't go over the TextInput Please isn't it working, or can another better method of putting the search icon over the TextInput be suggested, Thank you
import { Avatar } from 'react-native-elements';
import FontAwesome
from './node_modules/#expo/vector-icons/fonts/FontAwesome.ttf';
import MaterialIcons
from './node_modules/#expo/vector-icons/fonts/MaterialIcons.ttf';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {timePassed: false};
}
state = {
fontLoaded: false
};
async componentWillMount() {
try {
await Font.loadAsync({
FontAwesome,
MaterialIcons
});
this.setState({ fontLoaded: true });
} catch (error) {
console.log('error loading icon fonts', error);
}
}
render() {
setTimeout(() => {
this.setState({timePassed: true})
}, 4000);
if (!this.state.timePassed) {
return <Splash/>;
} else {
return (
<View style={BackStyles.container}>
<Avatar style={BackStyles.searchIcon} icon={{ name: 'search', size: 25, }}/>
<TextInput placeholder="Search for your herbs.."
underlineColorAndroid={'transparent'} style={BackStyles.textBox}
/></View>
);
}
}
}
const BackStyles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'flex-start',
alignSelf: 'stretch',
flex: 1,
backgroundColor: '#E2E2E2',
marginTop: 20,
// width: '100%'
},
textBox: {
flex: 1,
height: 45,
padding: 4,
// textAlignVertical: 'top',
paddingLeft: 20,
// marginRight: 5,
flexGrow: 1,
// fontSize: 18,
color: '#000',
backgroundColor: '#fff',
// textAlign: 'center'
},
searchIcon:{
position: 'absolute',
alignSelf: 'stretch',
height: 45,
flex: 1,
top: 50,
flexGrow: 1,
padding: 4
}
});
You can use Flexbox's justifyContent feature to force the TextInput to the left and the search icon to the right. If you put a border on the container and not the TextInput, the entire thing will appear as there is a search icon fixed onto the right of the TextInput, when, in reality, they are two separate components.
// styles
const styles = StyleSheet.create({
searchBox: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
borderWidth: 1,
borderColor: 'black',
},
});
// the component
<View style={styles.searchBox}>
<TextInput ...yourprops />
<Avatar ...yourprops />
</View>
If you want to read more about justifyContent and how godly Flexbox is, you should check out Chris Coyier's Flexbox guide.