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>
Related
I'm learning to programming in React-Native (and also in Javascript) and I have a question.
Basically, I have created a Login for 2 categories of users: "Regular" and "Plus".
After the login they are redirect to an HomeUser page.
My problem is that in this "HomeUser" page I should create dynamic Content depending on the type of user.
This is the HomeUser
class HomeUser extends Component {
constructor(props){
super(props);
}
render() {
const FirstName = global.utente.data.Person.FirstName;
const LastName = global.utente.data.Person.LastName;
const Username = global.utente.data.Person.FiscalCode;
const Roles = global.utente.data.Roles
console.log(Roles)
return (
<View style={style.container}>
<View style={style.page}>
<Icon name="user-circle" color="#64c7c0" size={70} onPress={() => Actions.viewprofile()} />
<Text style={{paddingBottom: 15, textAlign: 'center', fontSize: 15, color: '#64c7c0', fontWeight: 'bold'}}>View Profile</Text>
<Text style={{textAlign: 'center', fontSize: 20,}}>{"Welcome"}</Text>
<Text style={{textAlign: 'center', fontSize: 20, color: '#64c7c0', fontWeight: 'bold'}}>{FirstName} {LastName}</Text>
<Text>{Roles}</Text>
//Add here "EDIT PROFILE" button to link a the page to edit profile, only for Regular User.
</View>
</View>
)
}
}
export default HomeUser;
So I should insert content dynamically for the users. Can you explain how can I do for example to the edit profile? I should create a new page and link to this page with a If condition? ( I don't think so xD )
My thought is that if I have to do more checks on the role, the efficiency of the application slows down. Is it possible that this problem occurs?
If i understand your question correctly you want to render a component when the user role is a specific one.
In this case you can use conditional rendering using:
{condition && <Component>}
inside you render return function.
In your code something like:
{Roles==="SpecificRole"&&<Button></Button>}
should do the trick
First Edit profile when you login success you can save user fix information on local storage then you can open new page name UserEditProfile it's a good way for efficiency.
If wanna show 1 page 2 different role stuff component you must create 2 component like that
//it's different .jsx file
<RegularUserComponent /*you can add props here*/ />
<SpecificRoleUserComponent />
then you can call like that
import RegularUserComponent from './components/RegularUserComponent.js'
import SpecificRoleUserComponent from './components/RegularUserComponent.js';
and use like that
// in render
{Roles==="Reqular" ? <RegularUserComponent/> :<SpecificRoleUserComponent/> }
localstorage about the information you must check this link
and An Example for a compornt
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View,Button,Image} from 'react-native';
export default class NameOfYouComponent extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
const {RequestResponse} = this.state;
return (
<View style={styles.container}>
{/*Here is Component include*/}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
});
you can call like that
import NameOfYouComponent from './../afolder/Component/NameOfYouComponent'
App.js:
import React, { Component } from "react";
import { Text, View, StyleSheet } from "react-native";
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text>
<Text>First</Text>
<Text style={{ borderBottomWidth: 1 }}>Second</Text>
<Text>Third</Text>
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#ECF0F1"
}
});
As you can see, we have nested <Text> components. The problem is some style props such as borderBottomWidth - marginVertical - width is NOT working for the nested components!
Any idea for solving this issue?
Thanks in advance!
I'm not sure why the (width, marginVertical) are not working but I know that you should specify the (borderStyle=solid, borderColor) so that you can see it.I think that's the problem, hope it helped.
But I should say that it might not be it cause I came across your question by trying to ask one, and for me all the styles did not work, not only that but it's raising an error and it does not run at all, this strange behavior only happen to Text component whether nested or not.
Here is the sample code , i am trying react-native-navigation
i used react-native init navigate to start the project
and afterwards i installed
yarn add react-native-navigation#latest
the code run perfect for first screen , but as i am making a call to showNextScreen function it throws the error
undefined is not an object (evaluating 'this.props.navigator.push') react native
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import {Navigation} from 'react-native-navigation';
import firstPage from './app/components/firstPage';
export default class navigate extends Component {
//function to move to next screen
showNextScreen = () =>{
this.props.navigator.push({
screen: 'firstPage',
title: 'firstScreen'
})
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text onPress={this.showNextScreen.bind(this)}
style={styles.instructions}>
Double tap R on your keyboard to reload,{'\n'}
Shake or press menu button for dev menu
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('navigate', () => navigate);
Using React Native Navigation, you have to bootstrap your app differently than how it's done originally. Native Navigation doesn't use the registerComponent setup since it's a native navigator.
The steps to fully setting up are listed in their docs https://wix.github.io/react-native-navigation/#/usage
I'm building a React Native app for the first time using an iOS Simulator with XCode, and it seems that my elements on the bottom of the screen are being cut off, as if the screen can only scroll so far. I've tried changing the overall container View's height, but it doesn't change how far down I can scroll. I've also tried removing the styling, as well as changing View to ScrollView, but neither helped. Another strange thing is that I need to add paddingTop, otherwise, the first Text is displayed over the time in the simulator
Here's the code:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Fields from './components/Fields.js'
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Calculator</Text>
<Text>1099 Calculator</Text>
<Fields />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
paddingTop: 50
},
});
Here's the top of the screen without the padding
And here's how it looks cut off
This is an issue I also had. To fix it just wrap your container with another view without padding but with flex. So like this:
export default class App extends React.Component {
render() {
return (
<View style={styles.main}>
<View style={styles.container}>
<Text>Calculator</Text>
<Text>1099 Calculator</Text>
<Fields />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
paddingTop: 50
},
main: {
flex: 1
}
});
I was facing the same problem, it turned out to be the padding that I added to my ScrollView. Maybe it is not the solution, it is simply to discard ideas..
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>
)