How to customize button of react native - android

I am trying to make my application button in react-native like below
I am using inbuilt Button view of react native where I see that it does not allow to change the height also. I want to change the height as well rounded like expected image.
This is how my button is looking :
<Button
title="CONTINUE"
color="#FE434C"
onPress={() => navigate("EnableNotification")}
/>

So this is what I usually do:
<TouchableOpacity onPress={() => {/* do this */}}>
<View style={{
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 15
}}
>
<Text style={{ color: 'white' }}>Button</Text>
</View>
</TouchableOpacity>
I find using this method makes buttons much more customisable, but if you do some digging there could be a library which implements something similar (I never really found the need to search for it).
NOTE: Obviously you will have to adjust the height/width of the button to your flavor.
EDIT: My mistake... I had put the onPress prop in the view, woops.

Here is my solution to easily style buttons using TouchableOpacity, Text and StyleSheet:
import React, { Component } from 'react';
import { View, StyleSheet, TouchableOpacity, Text } from "react-native";
export default class CustomButton extends Component {
render(){
return (
<View style={styles.container}>
/* Custom Button */
<TouchableOpacity
style={styles.customBtnBG}
onPress={() => {}} >
<Text style={styles.customBtnText}>Button</Text>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center"
},
/* Here, style the text of your button */
customBtnText: {
fontSize: 40,
fontWeight: '400',
color: "#fff",
},
/* Here, style the background of your button */
customBtnBG: {
backgroundColor: "#007aff",
paddingHorizontal: 30,
paddingVertical: 5,
borderRadius: 30
}
});

#Ryan Turnbull, Well, i think a little padding and fontSize will do.
<TouchableOpacity onPress={() => this.onLogin()}>
<View
style={{
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 15,
padding: 15,
}}>
<Text style={{color: 'white', fontSize: 20, fontWeight: '800'}}>
Button
</Text>
</View>
</TouchableOpacity>

<TouchableOpacity onPress = {() => {/* do this */}}>
<View style = {{backgroundColor: 'red', alignItems: 'center',
justifyContent: 'center', borderRadius: 15}}
>
<Text style = {{color: 'white'}}>Button</Text>
</View>

You can use Touchable Opacity and it's prop border radius to adjust it's curve.
https://facebook.github.io/react-native/docs/touchableopacity

In React-native, we can customise user defined button component and call it from anywhere. So that we can have structured approach throughout the program or application.
import React from "react";
import { StyleSheet, TouchableOpacity, Text, View } from "react-native";
const MyButton = props => {
return (
<TouchableOpacity
onPress={props.onPress}
>
<View style={{...styles.buttonStyle, ...props.style,
backgroundColor:props.buttonColor,
borderColor:props.buttonColor}}>
<Text style={{...styles.TextStyle, ...props.style,
color:props.fontColor}}>
{props.children}
</Text>
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
buttonStyle: {
paddingVertical: 10,
paddingHorizontal: 10,
borderRadius: 10,
borderWidth: 2,
},
TextStyle: {
textAlign: "center",
},
});
export default MyButton;
In style ... spread operator is used to integrate all the styles from same components and incoming styles from parent component through props.
props.children is used here to pass button title, so that title text is displayed on the button.
When button is pressed then instead of handling this press event inside of the button but inside of the component where we use this button. So we pass a fitting function reference on the button.
This MyButton button component can be called anywhere inside the program like:
<MyButton onPress={() => onPressFunction()}
buttonColor="red" fontColor="white">Button Title</MyButton>

You can use this library https://github.com/APSL/react-native-button to create a customizable button in react native.
<View>
<Button
style={{
backgroundColor: "#FE434C",
borderColor: "transparent",
borderRadius: 20,
width: 250,
height: 50,
}}
textStyle={{ color: "#FFFFFF" }}
onPress={() => { }}
>
CONTINUE
</Button>
</View>

Related

Problem with TouchableOpacity, negative margin and Android - React Native

I'm with a problem with TouchableOpacity and Negative Margins inside a FlatList. On iOS works well, but on Android, when I click at the TouchableOpacity in the front of other TochableOpacity, the TouchableOpacity from behind fires. I don't know how to solve this.
iOS Image
I clicked at "Proposta 70" but fires "Proposta 78" from behind.
Android Image
The FlatList code
<View style={styles.containerList}>
<FlatList
data={proposalsList}
keyExtractor={item => item.proposta_id}
renderItem={({ item, index }) => (
<RenderItem
item={item}
index={index}
isLoweredCard={
openedCardIndex !== null && index === openedCardIndex + 1
}
changeOpenedCardIndex={changeOpenedCardIndex}
/>
)}
refreshing={loading}
onRefresh={() => getProposalsAndNotifications()}
/>
</View>
The RenderItem code
<TouchableOpacity
style={styles.container(index, isLoweredCard)}
onPress={() => changeOpenedCardIndex(index)}
>
<>
<View
style={[
styles.lineContainer,
{ marginBottom: metrics.padding * 1.5 },
]}
>
<View
style={{
width: '50%',
}}
>
<Text style={styles.proposalId}>
{`Proposta ${item.proposta_id}`}
</Text>
<Text style={styles.proposalDate}>
{dayjs(item?.proposta_data_criacao).format('DD.MM.YYYY')}
</Text>
</View>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'flex-end',
}}
>
<View style={styles.statusContainer}>
<Text style={{ fontSize: wp(4), fontWeight: 'bold' }}>
<TypeStatus status={item?.proposta_status} />
</Text>
</View>
</View>
</View>
<View style={styles.lineContainer}>
<Text style={styles.proposalDetailLabel}>Valor solicitado</Text>
<Text style={styles.proposalDetailValue}>
{formatCurrency(item?.proposta_valor_financiado)}
</Text>
</View>
<View style={styles.lineContainer}>
<Text style={styles.proposalDetailLabel}>Valor liberado</Text>
<Text style={styles.proposalDetailValue}>
{formatCurrency(item?.proposta_valor_financiado)}
</Text>
</View>
<View style={styles.lineContainer}>
<Text style={styles.proposalDetailLabel}>Parcelas</Text>
<Text style={styles.proposalDetailValue}>
{`${item?.proposta_valor_prazo}x`}
</Text>
</View>
<View style={styles.lineContainer}>
<Text style={styles.proposalDetailLabel}>Valor da parcela</Text>
<Text style={styles.proposalDetailValue}>
{formatCurrency(item?.proposta_valor_parcela)}
</Text>
</View>
<View style={styles.buttonContainer}>
<Button
onPress={goToDetails}
title="Ver detalhes"
titleStyle={styles.proposalButtonText}
style={styles.button}
/>
</View>
</>
</TouchableOpacity>
And the style of items
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
} from 'react-native-responsive-screen';
import { metrics, colors } from '../../../../constants';
const styles = StyleSheet.create({
container: (index, isLoweredCard) => ({
backgroundColor: `#00${index}F${index}C`,
marginTop: !isLoweredCard && index !== 0 ? -wp(53) : metrics.padding,
marginHorizontal: metrics.padding,
alignContent: 'center',
padding: metrics.padding,
borderRadius: metrics.radius,
zIndex: -(index + 999),
}),
lineContainer: {
width: '100%',
justifyContent: 'space-between',
flexDirection: 'row',
marginBottom: metrics.padding / 2,
},
statusContainer: {
backgroundColor: colors.white,
borderRadius: 20,
width: '70%',
paddingVertical: 3,
alignItems: 'center',
justifyContent: 'center',
},
proposalId: {
color: colors.white,
fontWeight: 'bold',
fontSize: wp(4.5),
},
proposalDate: {
color: 'rgba(0, 0, 0, 0.5)',
fontWeight: 'bold',
fontSize: wp(3.5),
},
proposalDetailLabel: {
fontSize: wp(4),
color: 'rgba(0, 0, 0, 0.9)',
},
proposalDetailValue: {
fontSize: wp(4.5),
color: colors.white,
fontWeight: 'bold',
},
proposalButtonText: {
color: colors.white,
fontWeight: 'bold',
fontSize: wp(4),
},
button: {
borderRadius: metrics.radius,
backgroundColor: '#002F6C',
paddingHorizontal: metrics.padding * 3,
},
buttonContainer: {
width: '100%',
marginTop: metrics.padding,
alignItems: 'center',
},
});
export default styles;
I encountered exactly the same problem on Android. My FlatList rendered items with negative margin to superimpose them on each other. The touchable on iOS is perfect but on Android it press the lowest item behind.
Finally I solved this by replacing
import { TouchableOpacity } from 'react-native';
with
import { TouchableOpacity } from 'react-native-gesture-handler';
Using react-native 0.63.4 and react-native-gesture-handler 1.9.0 in my case.
The only solution for my case was inverting the negative margin (top / bottom).
In my case the View component was with negative marginBottom and the touchable part that I wanted was on the bottom as well, so I inverted it and put the View inside the next component and gave a negative marginTop. So the part that I wanted to be touchable worked fine.
A little strange but for me it worked out well...

React Native - Change text color according to background color

I want to do something like as shown in the image below but I don't have any idea how to achieve that (I googled it, but I found only result for native code Swift, Obj C, ...).
Do I have to play with some layers or something like that?
Thanks for your answers!
Viktor
Hey thank you so much for your answers,
I had to handle the text overflow with ellipsis and it was really complicated with what you proposed, so I used the maskView to do that.
I did like that:
// container
<View style={{flex:1, borderRadius: 200, height: 25, overflow:hidden}}>
// Progress bar support
<View style={{flex:1, backgroundColor: 'gray'}} />
// Progress bar, I play with "width" to indicate percentage
<View style={[StyleSheet.absoluteFill, {width: "50%", backgroundColor: 'green'}]} />
<MaskedView
style={[StyleSheet.absoluteFill, {justifyContent: 'center'}]}
maskElement={
// I define text which will be masked
<View style={[StyleSheet.absoluteFill, {justifyContent: 'center'}]}>
<Text
style={{marginHorizontal: 15, fontSize: 13}}
numberOfLines={1}>
Text color change
</Text>
</View>
}>
// I define a default mask that I apply to the text so that it is 'black' when it is not ON the progress bar.
<View style={[StyleSheet.absoluteFill,{backgroundColor: 'black'}]} />
// I define the mask that takes the size of the progress bar and that I apply over the default mask (to overwrite it) so that the text under the mask becomes white.
<View style={[StyleSheet.absoluteFill,{width:"50%", backgroundColor: '#fff'}]} />
</MaskedView>
</View>
So I have my default bar indicating the "maximum progress" and I define my progress bar (which grows or shrinks according to the percentage).
Then I define a MaskedView with my text as MaskedElement.
By default, I apply a black mask on the text so that it is always black no matter what happens.
And then, I overwrite this mask with the white mask which has exactly the same size as my progress bar.
So everything under the mask of the progress bar becomes white to go on my "dark" progress bar and the rest is black!
This way, I can easily manage the text overflow with an ellpsizeMode="tail".
And this is the result:
Same styles from the previous answer but changed the implementation by adding another View that contains same text with different background color and text color inside the gray one with a position of 'absolute'!
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class Example extends React.Component {
state = {
text: 'Text color changes',
};
render() {
console.log(this.state.textArray);
return (
<View style={styles.container}>
<View
style={{
flex: 1,
backgroundColor: '#d0d3d6',
borderTopRightRadius: 20,
borderBottomRightRadius: 20,
borderTopLeftRadius: 20,
borderBottomLeftRadius: 20,
overflow: 'hidden',
}}>
<Text style={styles.leftLabelStyle}>{this.state.text}</Text>
<View
style={{
width: '30%',
height: '100%',
position: 'absolute',
backgroundColor: '#5483b3',
}}>
<Text numberOfLines={1} ellipsizeMode='clip'
{styles.RightLabelStyle}>
{this.state.text}
</Text>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginHorizontal: 20,
},
leftLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: '#000',
},
RightLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: '#fff',
},
});
example at snack:https://snack.expo.io/#hassan190011/loading
Edit : add ellipsizeMode='clip' after numberOfLines to remove dots
This implementation is a little bit different, Mainly I have 2 different views with separate styles & Finally, wrap those 2 views using the main view.
import * as React from "react";
import { Text, View, StyleSheet } from "react-native";
export default class Example extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.leftViewStyle}>
<Text style={styles.leftLabelStyle}>Text color ch</Text>
</View>
<View style={styles.rightViewStyle}>
<Text style={styles.rigthLabelStyle}>ange</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
marginHorizontal: 20
},
leftViewStyle: {
flex: 1,
backgroundColor: "#5483b3",
alignItems: "flex-end",
borderTopLeftRadius: 20,
borderBottomLeftRadius: 20
},
rightViewStyle: {
flex: 1,
backgroundColor: "#d0d3d6",
borderTopRightRadius: 20,
borderBottomRightRadius: 20
},
leftLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: "#fff"
},
rigthLabelStyle: {
fontSize: 16,
paddingVertical: 5,
color: "#000"
}
});
This might not be the optimal solution. If you have any doubts feel free to ask.
Hope this will helps you.

Creating Navigation Drawer with Image in header in React Native

import React, { Component } from 'react';
import { Alert, Button, TextInput, View, StyleSheet, Text, AsyncStorage } from 'react-native';
import { DrawerItems, DrawerNavigation } from 'react-navigation';
export default class Home extends Component {
const DrawerContent = (props) => (
<View>
<View
style={{
backgroundColor: '#f50057',
height: 140,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text style={{ color: 'white', fontSize: 30 }}>
Header
</Text>
</View>
<DrawerItems {...props} />
</View>
)
const Navigation = DrawerNavigator({
// ... your screens
Home:{
screen: HomeScreen,
},
Settings: {
screen: SettingsScreen,
},
}, {
// define customComponent here
contentComponent: DrawerContent,
})
render() {
return (
<View>
<Text>Welcome To Home</Text>
</View>
);
}
}
I am designing a screen which will be a home screen for my app. This screen will have navigation drawer like in Android and the drawer header will contain an image and a text label inside it and below that there will be drawer items from which i will navigate to a different screen. I have tried to achieve this using the above code but it doesn't work. Can you tell me where i am wrong? How can i achieve my target? I am a newbie to react native so i please make my concepts clear
Please replace your DrawerContent with the following code and check if it works.
const DrawerContent = (props) => {
return (
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<View style={{ flexDirection: 'row', paddingBottom: 20 }}>
<View style={{ flex: 80, backgroundColor: '#f50057'}}>
<Image style={{ width: 181, height: 132}} source={images.logo} />
</View>
<Text style={{ color: '#000', fontSize: 30 }}>Header</Text>
</View>
<DrawerItems {...props}/>
</SafeAreaView>
)};
First create Drawer Component
export default class DrawerComponent extends React.Component {
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView>
<View style={{ backgroundColor: "white" }}>
<Image
style={{ margin: 15 }}
source={{uri: 'https://facebook.github.io/react-native/docs/assets/favicon.png'}}
/>
</View>
<DrawerItems {...this.props} />
</ScrollView>
</SafeAreaView>
);
}
}
and import the component in your Home.js
import DrawerComponent from "./path/to/drawerComponent";
Please note : ScrollView is necessary for the case when you have more items to show ex: 7+ items (with margins in style prop) and also when screen height is small

How to create style globally in react native

I have multiple forms which have same kinda views for instance Text and Button. I do not want to declare same styles in different files wherever these are being used.
Is there any way to declare styles globally and use it in each screens of react native.
I have same style on each Text view, right now I am doing this in each files which is not good approach.
<Text style={{styles.textStyle}}>
Never forget to stay in touch with the people that matter to you.
</Text>
const styles = StyleSheet.create({
container: {
backgroundColor: "#FFFFFF",
alignItems: "center",
justifyContent: "center",
padding: 16,
flex: 1,
flexDirection: "column"
},
textStyle: {
fontSize: 22,
textAlign: "center"
}
});
import {
StyleSheet
} from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 80,
color: 'black'
}
});
module.exports = styles
Import The Following Style Where You Wants To Use That Style like
import styles from './Styles'
And use that styles like
<View
style={styles.container} >
<Text style={styles.welcome}>Welcome</Text>
</View>
Edit
import styles1 from './Styles'
than you can use
Global And Local Styles Togather With same name like:-
<View
style={styles1.container} >
</View>
<View>
style={styles.container}>
</View>

How to set the height of button in React Native Android

I am learning React Native programming for Android mobile apps. I am making a screen where I need to set height of button. I have added button in view and set the height of using style however there is no change on button height.
/**
* LoginComponent of Myntra
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from "react";
import { AppRegistry, Text, View, Button, TextInput } from "react-native";
class LoginComponent extends Component {
render() {
return (
<View style={{ flex: 1, flexDirection: "column", margin: 10 }}>
<TextInput
style={{
height: 40,
borderColor: "gray",
borderWidth: 0.5
}}
placeholder="Email address"
underlineColorAndroid="transparent"
/>
<TextInput
style={{
height: 40,
borderColor: "gray",
borderWidth: 0.5
}}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid="transparent"
/>
<View style={{ height: 100, marginTop: 10 }}>
<Button title="LOG IN" color="#2E8B57" />
</View>
</View>
);
}
}
AppRegistry.registerComponent("Myntra", () => LoginComponent);
Can anyone help me to set the height of button according to my requirement?
This component has limited options, so you can't resize it to a fixed height.
I recommend you to use the TouchableOpacity component to build your own button, with own properties and styles.
You can easily style it like this:
<TouchableOpacity style={{ height: 100, marginTop: 10 }}>
<Text>My button</Text>
</TouchableOpacity>
You can set the button width as per the mentioned width easily by using following method :
<View style={[{ width: "90%", margin: 10, backgroundColor: "red" }]}>
<Button
onPress={this.buttonClickListener}
title="Button Three"
color="#FF3D00"
/>
</View>
Best solution is to use minHeight or maxHeight instead of using Height const.
It often happens that we want to change the dimensions of the button, which by default is extended to the entire width of the parent element. While reducing its width is not a problem – it is enough to reduce the width of the parent, but changing the height is already problematic. The Button element has no style property, so apart from changing the text color on iOS and the background color on Android, we can not set much in it.
To have more control over the button, it is better to use TouchableOpacity or TouchableNativeFeedback instead.
TouchableOpacity Function Component Example -
import React, { useState } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
const App = () => {
const [count, setCount] = useState(0);
const onPress = () => setCount(prevCount => prevCount + 1);
return (
<View style={styles.container}>
<View style={styles.countContainer}>
<Text>Count: {count}</Text>
</View>
<TouchableOpacity
style={styles.button}
onPress={onPress}
>
<Text>Press Here</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
paddingHorizontal: 10
},
button: {
alignItems: "center",
backgroundColor: "#DDDDDD",
padding: 10
},
countContainer: {
alignItems: "center",
padding: 10
}
});
export default App;
<View style={styles.btnContainer}>
<TouchableOpacity>
<Button style={styles.btnSize}>
<Text>Change Address</Text>
</Button>
</TouchableOpacity>
<TouchableOpacity>
<Button style={styles.btnSize}>
<Text>Change Address</Text>
</Button>
</TouchableOpacity>
</View>
Style sheet code snippet
const styles = StyleSheet.create({
btnContainer:{
flexDirection:"row",
justifyContent:"space-between"
},
btnSize:{
width:"100%"
}
})
The component Button supports a minimal level of customization, so you have to use an other component.
You can use : Pressable or TouchableOpacity ,
<Pressable onPress={onPressFunction} style={styles.yourButtonStyle}>
<Text>I'm pressable!</Text>
</Pressable
const styles = StyleSheet.create({
yourButtonStyle: {
...
}
});
Doc Button

Categories

Resources