after searching for hours I am finally completly lost. I tried to build a simple Dictionary app following an outdated tutorial (https://code.tutsplus.com/tutorials/creating-a-dictionary-app-using-react-native-for-android--cms-24969) for react native. The standard app after I run "react-native init" works fine on my phone. However my code just shows a blank screen without any errors. Below I posted the code, which I used to replace everthing in index.adroid.js. I would really appreciate it, if you could help me here. Thanks in advance!
import React, {Component} from 'react';
import {
AppRegistry,
Text,
View,
TextInput,
StyleSheet,
} from 'react-native';
var english_german = require('./english_german.json');
class Dictionary extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
output: ''
};
}
render() {
return(
<View style={styles.parent}>
<Text>
Type something in English:
</Text>
<TextInput
// style= {{height: 40}}
// placeholder="Type here to translate!"
onChangeText={(text) => this._onTextInputChangeText(text)}
value={this.state.input}
onSubmitEditing={ this.showTranslation().bind(this)} />
<Text style = {styles.germanLabel}>
German translation:
</Text>
<Text style = {styles.germanWord}>
{this.state.output}
</Text>
</View>
);
}
_onTextInputChangeText(text) {
//alert(text);
this.setState({
input : text
})
}
showTranslation() {
var translation = this.state.input in english_german ? english_german[this.state.input] : "Not found";
this.setState({
output: translation
});
}
}
const styles = StyleSheet.create({
// For the container View
parent: {
padding: 16
},
// For the Text label
germanLabel: {
marginTop: 20,
fontWeight: 'bold'
},
// For the Text translation
germanWord: {
marginTop: 15,
fontSize: 30,
fontStyle: 'italic'
}
});
AppRegistry.registerComponent('Dictionary', () => Dictionary);
Thank you guys!
I didn't get the error most of the time, but the syntax error at onSubmitEditing was the problem. For some reason it didn't work (show anything) when I uncommented the whole TextInput. Anyway the fix of Michael Cheng to onSubmitEditing={ this.showTranslation.bind(this)} worked.
Related
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const ComponentsScreen = () => {
return (
<View>
<Text style={styles.textStyle}> Hello World! </Text>
</View>
);
}
const styles = StyleSheet.Create({
textStyle: {
fontsize: 30
}
});
export default ComponentsScreen;
Here is the picture link
Don't know what is the error here, help me please.
Change StyleSheet.Create C to lower case like :
const styles = StyleSheet.create({
will be fine.
I created a component at react-native, but the text of the button is always at uppercase, someone knows why it doesn't take the text that pass, because I want to show 'Login', but it shows 'LOGIN'
import React, { Component } from 'react';
import { View, Button} from 'react-native';
import LabelApp from "../../config/labels.app";
const labelApp = LabelApp.loginView;
export default class Login extends Component {
constructor(props){
super(props);
this.handleClickBtnEnter = this.makeLogin.bind(this);
}
makeLogin() {
}
render() {
return (
<View>
<Button title= {labelApp.textButtonLogin} onPress={this.handleClickBtnEnter}/>
</View>
);
}
}
Label of component
const LabelApp = {
loginView: {
textButtonLogin: 'Ingresar',
},
}
export default LabelApp;
The visualization
For react Native Paper button use uppercase={false} prop:
<Button
mode="outlined"
uppercase={false}
accessibilityLabel="label for screen readers"
style={styles.yourButtonStyle}>Button label</Button>
So, the other two answers are correct that you should use TouchableOpacity, but as someone new to React Native, it took me awhile to understand what was going on here. Hopefully this explanation provides a little more context.
The built-in Button component seems to have some weird compatibility/visibility issues on occasion, one of which is rendering the title prop text all uppercase. When viewing the documentation for the Button component in Chrome, the preview shows all text being capitalized under the "Web" view but not Android or iOS (I was having this issue using Expo and Metro Bundler on an Android device, so not sure what to make of this). I couldn't find anything about capitalization/uppercase in the Button docs, so perhaps this is a bug.
The solution is to use a different component called TouchableOpacity. It also has an onPress event you can use and a built-in touch animation, but it has less out of the box styling than the Button component. Important to note from docs: "Opacity is controlled by wrapping the children in an Animated.View, which is added to the view hierarchy. Be aware that this can affect layout." It doesn't have a title prop, so you just put the button text in a Text component, like so:
<Button
title='text will be capitalized'
onPress={onPress}
/>
becomes
<TouchableOpacity onPress={onPress}>
<Text>text will stay lowercase</Text>
</TouchableOpacity>
I was having the same issue as OP, and this solved it for me.
From the official documentation
A basic button component that should render nicely on any platform. Supports a minimal level of customization.
The recommend use of touchable opacity or touchable native feedback
https://facebook.github.io/react-native/docs/touchableopacity
Below I've added textTransform: 'lowercase', as a style rule for the button to override any inherited text casing.
import React, { Component } from 'react'
import {
StyleSheet,
TouchableOpacity,
Text,
View,
} from 'react-native'
export default class App extends Component {
constructor(props) {
super(props)
this.state = { count: 0 }
}
onPress = () => {
this.setState({
count: this.state.count+1
})
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={styles.button}
onPress={this.onPress}
>
<Text> Touch Here </Text>
</TouchableOpacity>
<View style={[styles.countContainer]}>
<Text style={[styles.countText]}>
{ this.state.count !== 0 ? this.state.count: null}
</Text>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 10
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
textTransform: 'lowercase', // Notice this updates the default style
},
countContainer: {
alignItems: 'center',
padding: 10
},
countText: {
color: '#FF00FF'
}
})
https://snack.expo.io/Bko_W_gx8
This question is 3 years old and I'm not sure why no one has answered it correctly until now.
Native android buttons are all caps by default starting from android lollipop, which is what react native uses when you use the control Button from react-native in your app. To override the functionality, you just need to add this line in your styles.xml file inside your app theme (not the splash screen style)
<item name="android:textAllCaps">false</item>
You can get more details here: https://stackoverflow.com/a/30464346/11104068
The changes are not going to apply instantly obviously since the change is in the naive xml file and not in a JavaScript file. So you will need to do a npm/yarn run android
I've tried your code and it looks like it's the expected behaviour with Button component from react-native
You can see this at the official documentation
I believe that you need to change Button component, take it from another package to meet your needs.
As an alternative you can create your own button
import React, { Component } from 'react';
import { View, Button, TouchableHighlight, StyleSheet } from 'react-native';
import LabelApp from "../../config/labels.app";
const labelApp = LabelApp.loginView;
export default class Login extends Component {
constructor(props){
super(props);
this.handleClickBtnEnter = this.makeLogin.bind(this);
}
makeLogin() {
}
render() {
return (
<View>
<TouchableHighlight onPress={this.handleClickBtnEnter} underlayColor="white">
<View style={styles.button}>
<Text style={styles.buttonText}>{labelApp.textButtonLogin}</Text>
</View>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
marginBottom: 30,
width: 260,
alignItems: 'center',
backgroundColor: '#2196F3'
},
buttonText: {
textAlign: 'center',
padding: 20,
color: 'white'
}
});
<Button
style={{
borderRadius: 10,
backgroundColor: "#000",
width: 200,
height: 50,
}}
>
<Text
uppercase={false}
>
Login
</Text>
</Button>
Gonna try to make this as detailed as I can since I'm new to React Native and maybe this'll help someone else as well ✨.
I'm using the React Native Super Grid library, which internally uses FlatList and SectionList, to render a grid layout. The grid is populated with text via props from a separate const
What I'm trying to do is: When a user taps any item in the FlatList, the item that was tapped is copied to the clipboard and an alert is shown confirming it was copied.
What's happening right now: Each item is tappable & the correct alert is showing onPress confirming that you've copied to your clipboard, BUT nothing is actually being written to the clipboard. Just to make sure that writeToClipboard is working I have a static message in there that just says "WELL AT LEAST THE CLIPBOARD WORKS," so if you tap any item, that static message is successfully copied to the clipboard. I'm just not sure of how to copy the specific item that was tapped to the clipboard.
Here's the code for the grid component:
import React, { Component } from "react";
import {
StyleSheet,
Alert,
View,
Text,
TouchableOpacity,
Clipboard,
Button,
onPress
} from "react-native";
import { FlatGrid } from "react-native-super-grid";
class Emojigrid extends Component {
constructor(props) {
super(props);
this.state = {
text: "WELL AT LEAST THE CLIPBOARD WORKS",
clipboardContent: null
};
}
writeToClipboard = async () => {
await Clipboard.setString(this.state.text);
alert("Boom, Copied");
};
render() {
return (
<FlatGrid
itemDimension={130}
items={items}
style={styles.gridView}
// staticDimension={300}
// fixed
spacing={2}
renderItem={({ item, index }) => (
<View style={[styles.itemContainer, { backgroundColor: "#F7F7F7" }]}>
<TouchableOpacity onPress={this.writeToClipboard}>
<Text style={styles.itemName}>{item.name}</Text>
</TouchableOpacity>
</View>
)}
/>
);
}
}
export default Emojigrid;
const items = [
{ name: "¯_(ツ)_/¯" },
{ name: "ʕ·͡ᴥ·ʔ" },
{ name: "•`_´•" },
];
const styles = StyleSheet.create({
gridView: {
marginTop: 0,
marginBottom: 400,
flex: 1
},
itemContainer: {
justifyContent: "center",
alignItems: "center",
borderRadius: 0,
height: 125
},
itemName: {
fontSize: 18,
color: "black",
fontWeight: "400"
}
});
Thinking the answer is probably quite obvious, but any help is much appreciated!
Your writeToClipboard function needs to accept an argument.
writeToClipboard = async (text) => {
await Clipboard.setString(text);
alert("Boom, Copied");
};
And pass that argument where you call it.
<TouchableOpacity onPress={() => this.writeToClipboard(item.name)}>
I'm a newbie to React-Native, so I've been going through a tutorial to create a login screen. The code in the tutorial is out of date. I'm creating a login screen made up of a few components. However, a certain TextInput isn't showing up in the simulator. Here's the parent component "LoginForm" from LoginForm1.js:
export default class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {
text: ''
};
}
render() {
return (
<Card>
<CardSection>
<Input
placeholder="user#gmail.com"
label="Email"
value={this.state.email}
onChangeText={text => this.setState({ text })}
/>
</CardSection>
The child component "Input" is wrapped in components "CardSection" and "Card" (these pass their props with a View displaying {this.props.children}, but here's the "Input" component from Input.js:
export default class Input extends Component {
render() {
return (
<View style={styles.containerStyle}>
<Text style={styles.labelStyle}>{this.props.label}</Text>
<TextInput
placeholder={this.props.placeholder}
autoCorrect={false}
style={styles.inputStyle}
value={this.props.value}
onChangeText={this.props.onChangeText}
/>
</View>
);
}
}
const styles = StyleSheet.create({
inputStlye: {
color: '#000',
paddingRight: 5,
paddingLeft: 5,
fontSize: 18,
Height: 50,
Width: 50,
flex: 2,
},
This code doesn't throw any errors, but the TextInput from "Input" doesn't show up. I've given it some dimensions in the styling, so that can't be it. If I replace the TextInput with just normal Text, then the contents of that Text tag will appear in the simulator. Am I missing something to do with passing props? Any help would be much appreciated, thank you!
You have the value being passed down as value={this.state.email}, but you're onChangeText is updating this.state.text so just change it to value={this.state.text}.
I'm playing with react native and got a strange behaviour.
When I try to show a ActitvityIndicator for Android setting its animating property to true with a showProgress variable in the state it doesn't work if the variable is started as false.
In the sample below if the ActivityIndicator animating property start as true, then the buttons make the ActivityIndicator hide or appear correctly.
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
TextInput,
TouchableHighlight,
ActivityIndicator
} from 'react-native';
export class Login extends Component {
constructor(props) {
super(props);
this.state = {
showProgress: true
};
}
render() {
return (
<View>
<TouchableHighlight onPress={this.progressOff.bind(this)}>
<Text>progressOff</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.progressOn.bind(this)}>
<Text>progressOn</Text>
</TouchableHighlight>
<ActivityIndicator animating={this.state.showProgress} size="large"/>
</View>
);
}
progressOff() {
this.setState({showProgress: false});
}
progressOn() {
this.setState({showProgress: true});
}
}
But if i use the code below, with the animating property starting as false, then the button to make the ActivityIndicator appear doesn't work:
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
TextInput,
TouchableHighlight,
ActivityIndicator
} from 'react-native';
export class Login extends Component {
constructor(props) {
super(props);
this.state = {
showProgress: false
};
}
render() {
return (
<View>
<TouchableHighlight onPress={this.progressOff.bind(this)}>
<Text>progressOff</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.progressOn.bind(this)}>
<Text>progressOn</Text>
</TouchableHighlight>
<ActivityIndicator animating={this.state.showProgress} size="large"/>
</View>
);
}
progressOff() {
this.setState({showProgress: false});
}
progressOn() {
this.setState({showProgress: true});
}
}
What am I missing here?
This appears to be a bug in React Native. The code with initial state being showProgress: false works on iOS but not on Android.
I've opened an issue on github if you want to follow the progression:
https://github.com/facebook/react-native/issues/9023
Option 1
A workaround I've used is to use the showProgress variable to render a completely different view with the ActivityIndicator:
render() {
if (this.state.showProgress) {
return this.renderLoadingView();
} else {
return this.renderMainView();
}
}
Option 2
You can also set the opacity of the ActivityIndicator according to the state:
render() {
return (
<View>
<TouchableHighlight onPress={this.progressOff.bind(this)}>
<Text>progressOff</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.progressOn.bind(this)}>
<Text>progressOn</Text>
</TouchableHighlight>
<ActivityIndicator style={{opacity: this.state.showProgress ? 1.0 : 0.0}} animating={true} size="large"/>
</View>
);
}
However the spinner animation doesn't always start at the same position when using this method.
This is a bug of React-Native for component Activity Indicator.
I am not sure that fb has already solved it but you can try this
constructor(props) {
super(props);
this.state = {
opacity: 0
};
}
to show it use this.setState({opacity:1}) and to hide again this.setState({opacity:0}) in your called functions
and in the render where you are using activity indicator
<ActivityIndicator
animating={true}
color="#ffffff"
style={{height: 80, marginTop: 10, opacity: this.state.opacity }}
size="large"/>
If in your project you can use third party components, I recommend the use of react-native-loading-spinner-overlay
Solved easily our problems, beacause this component use a similar way to show or hide the Activity with the property visible.
Another way I found effective to work around that problem without much code is:
{ this.state.showProgress &&
<ActivityIndicator animating={true} size="large"/>
}
I tried a different approach which I think that it is a more "react way" to solve problems. So, the problems with the opacity solution is that If you just set it to 0, it still will be a animation, so it is not the best solution thinking in your app performance.
I created a separated component that I called <Loading/>, here is the code:
import { ActivityIndicator } from "react-native"
import React from "react"
import PropTypes from "prop-types"
const Loading = (props) =>
props.animating
? <ActivityIndicator style={props.style}
importantForAccessibility='auto' size={props.size}
color={props.size} /> : null
Loading.propTypes = {
animating: PropTypes.bool.isRequired,
style: PropTypes.oneOfType([PropTypes.style, PropTypes.object]),
}
export default Loading
Usage:
<Loading animating={true} importantForAccessibility='auto' size="large" color="#A02BFF" style={styles.loading} />
That way it will avoid to create a animation when it is not a necessity, you will create separated component that can be removed easily at the point that the ActivityIndicator issue becomes solved in the future by replacing it to the original ActivityIndicator native component.
The only problem I had with this, was that in Android it wasn't visible because of the background I had on my screen. I fixed by only changing the color prop to something I knew should stand out in the background:
<ActivityIndicator color={theme.secondary.color} />
i got this problem all by a mistake. i did not put ActivityIndeicator in the center of a view. so it positioned on top of a view, which is covered by a natigation bar. code below is correct. hope this can help u.
<View style={{alignItems: 'center', justifyContent: 'center', flex: 1, backgroundColor: 'white'}}>
<ActivityIndicator
animating={true}
style={
{
alignItems: 'center',
justifyContent: 'center',
opacity: this.state.loading ? 1 : 0
}}
size="large"
/>
</View>
A quick fix Use conditional rendering.. Keep animating : {true} and just Visible and invisible view.
Checkout :
https://kylewbanks.com/blog/how-to-conditionally-render-a-component-in-react-native
In my case, for react native version 0.59.10 , the size property type is different for Android and iOS, so for that I had to make a Platform check as following and it worked.
<ActivityIndicator
size={Platform.OS === "ios" ? 0 : "large"} //This platform check worked.
color={props.color}
animating={props.animating}
style={props.style}
/>
The transition of animating from false to true is too slow on Android. But you can force a re-render using the key prop:
<ActivityIndicator
key={`${props.animating}`}
animating={props.animating}
/>
When props.animating changes from false to true, they key also changes. This forces a re-render, meaning that a new component is rendered with animating = true, which will instantly start your spinner.
If you are testing it on Android one of the reason could be the color property.
Be sure to give the ActivityIndicator a color. For example:
<ActivityIndicator size="large" color="#0000ff" />
This solution work perfectly for me in Android.
Hope this will help you.
import {ActivityIndicator} from 'react-native';
const [opacity, setOpacity] = useState(0)
const onLoadStart = () => {
setOpacity(1);
};
const onLoad = () => {
setOpacity(0);
};
const onBuffer = ({isBuffering}) => {
setOpacity(isBuffering ? 1 : 0);
};
return(
<View>
<Video
video={{uri: props.videoSource}}
autoplay={false}
customStyles={{
seekBarProgress: {
backgroundColor: theme.color.primary,
},
seekBarKnob: {
backgroundColor: theme.color.primary,
},
}}
ref={ref => (player = ref)}
onBuffer={onBuffer}
onLoadStart={onLoadStart}
onLoad={onLoad}
/>
<ActivityIndicator
animating
size="large"
color={color.primarylight}
style={{
opacity: opacity,
position: 'absolute',
top: 70,
left: 70,
right: 70,
// height: 50,
}}
/>
</View>
)