Only button text area is clickable - react-native

Clicking does not work for all parts of the button. Only the text area is clickable.
As a solution, I used contentStyle instead of style prop. But it changes only the color in the touching space of the button. I need to apply button click for the whole button and to change the color of the whole button when clicking on anywhere of the button.
Here is my code:
import * as React from "react";
import { Button } from "react-native-paper";
import styles from "./styles";
const Cbutton = ({ text, onPress }) => (
<Button style={styles.wrapper} mode="contained" onPress={onPress}>
{text}
</Button>
);
export default Cbutton;
This is my code for the stylesheet.
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
wrapper: {
flexDirection: 'row',
justifyContent:'center',
alignItems: 'center',
width: ( "96%" ),
},
});

I had this same problem, and thankfully the fix is super simple - just remove { alignItems: 'center' } from your Button's style prop 👍
When applied, it shrinks the Button's content container, and it's unnecessary anyways thanks to the Button's internal styling.
For height, I recommend setting { height: '100%' } in the contentStyle prop.
Not sure about customizing the onPress color, however. If you can't find a ready-made solution, I'd try rolling your own using react-native Pressable.

You must use TouchableHighlight to change on the active state.
As for as, the clickable area is concerned I think rn-paper button by default is proper. You must check the way you had exported the component.

The issue described by #os-hewawitharana just happen after you set the disabled to true and then set back to false.
Here is how to simulate the issue. In constructor the button is enabled, therefore you can tap all the button area, after disabling and reenabling his state you will only can tap in text area. There is nothing wrong with component and his export method.
constructor(props) {
super(props);
this.state = {
desativado: false
};
}
async componentDidMount() {
setTimeout(() => {
this.setState({ desativado: true });
}, 2000);
setTimeout(() => {
this.setState({ desativado: false });
}, 4000);
}
render(){
return (
<Button
label={'Entrar'}
color={'blue'}
onPress={async () => {
await this.setState({ desativado: true });
}}
disabled={this.state.desativado}
mode="contained"
ark={true} > <Text style={{ fontSize: 14 }}>Text</Text>
</Button>
);
For while the solution is use a version 3 alpha
npm i react-native-paper#3.0.0-alpha.3
Soon they will release a v3 stable release as they answer in my issue report in github: https://github.com/callstack/react-native-paper/issues/1297

Related

React-Native-Elements Tooltip non functional

I'm trying to add a tooltip component to my react native project, I installed React Native Elements to do this. I know it's installed correctly because the Divider component worked perfectly fine. For some reason though, the tooltip doesn't seem to work right, there are no errors but it simply doesn't do anything when I tap on the tooltip.
My entire component is here:
import React from 'react';
import {
StyleSheet,
View,
TouchableOpacity,
} from 'react-native';
import { MaterialCommunityIcons } from '#expo/vector-icons';
import { Tooltip, Text } from "#rneui/themed";
import {Colors} from './Colors';
const InfoTooltip = ({ label, info='' }) => {
return (
<View style={styles.inputLine}>
{ info != '' &&
<Tooltip popover={<Text>Tooltip Info</Text>}>
<Text>Press</Text>
</Tooltip>
}
{ info === '' &&
<Text style={styles.inputLabel}>{label}:</Text>
}
</View>
);
};
const styles = StyleSheet.create({
inputLine: {
flex: 1,
flexDirection: 'row',
},
inputLabel: {
color: Colors.Dove_Gray,
marginTop: 2,
fontSize: 14,
},
infoText: {
color: Colors.Silver,
fontSize: 12,
},
});
export default InfoTooltip;
I'm testing it on iOS and I see the text that says "Press", but when tapped, nothing happens, no popover, no error.
When setting visible to true, the tooltip is shown when I first render the app, but it locks the app up and I can no longer tap anything or scroll.
I'm not sure what I'm doing wrong, Thanks!
Starting with React Native Elements version 4.0, Tooltip is stateless. This means you need to use useState. You should declare a variable, like:
const [open, setOpen] = useState(false);
And include visible, onOpen & onClose Props for it to work:
<Tooltip
visible={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
popover="This is the popover text"
/>
More info in the Migration Guide.

Change the backgroundcolor of Touchable / Pressable Item after pressing

I'm currently working on an app prototype with react native. There's a lot out there on how to change the color of a component, here Touchable or Pressable, when pressing it (=> onPress).
But how do i change the backgroundcolor of such a component permanently after clicking – with onPressOut?.
Example:
simple "Click me" component that has a green background by default. If clicked once, it should change to a red background. Clicked once again, it should go back to green (and so on).
Can you help me with this?
You need to control it using the state of component.
I did a live demo for you:
https://codesandbox.io/s/silent-sea-5331l?file=/src/App.js
import React, { useState } from "react";
import { View, TouchableOpacity } from "react-native";
const App = props => {
const [selected, setSelected] = useState(false);
return (
<View style={{ width: "30%", alignItems: "center", marginTop: 20 }}>
<TouchableOpacity
onPress={() => setSelected(!selected)}
style={{ backgroundColor: selected ? "red" : "transparent" }}
>
Press me
</TouchableOpacity>
</View>
);
};
export default App;

React-native keyboard

When the texInput is focused in react-native then my header goes of the screen as the keyboard is opened. I cannot make the changes in android manifest.xml keyboardSoftINputMode to adjustResize. Because if i make it to adjustResize then the keyboardAwareScrollView does not work.
Please suggest me a way so that when my TextInput is focused then my header does not get off the screen. This is occurring in react-native.
You can use KeyboardAvoidingView to automatically resize your visible area when a TextInput is highlighted.
Usage: Simply wrap your top-level <View> or other component in your App's render() function with a <KeyboardAvoidingView>:
import {KeyboardAvoidingView} from 'react-native';
...
<KeyboardAvoidingView>
... your UI ...
</KeyboardAvoidingView>;
render() {
const { styles } = this.state
const style = this.props.testType === 'practice' ? styles.containerStyleCPP : styles.container
return (
{this.renderQuestionBasedOnType()}
{/* */}
)
}
}
const getStyle = () => StyleSheet.create({
container: {
height: heightPercentage(100)
},
containerStyleCPP: {
width: widthPercentage(100)
}
})
This is my code

How to disable highlighting effect of TouchableOpacity when scrolling?

<TouchableOpacity style={{ flex: 1 }} >
<ImageBackground
source={require('../../images/home.jpg')}>
<View style={styles.item} collapsable={false}>
<H3>{contentData[i].name}</H3>
<Text>{contentData[i].description}</Text>
</View>
</ImageBackground>
</TouchableOpacity>
I have a list of TouchableOpacity inside a ScrollView. I want to disable highlighting effect of TouchableOpacity. When scrolling I want to highlight only when onPress event is triggered. Because it may confuse the user that it is pressed.
Simply pass activeOpactity prop with value 1.
<TouchableOpacity activeOpacity={1}>....</TouchableOpacity>
Make sure you import TouchableOpacity from "react-native" not from "react-native-gesture-handler".
Try setting the activeOpacity prop on the TouchableOpacity to 1 when scrolling. Use default settings when the user stops scrolling.
https://facebook.github.io/react-native/docs/touchableopacity#activeopacity
You can try changing param delayPressIn. Look doc.
<TouchableOpacity delayPressIn={150} >
{children}
</TouchableOpacity>
You can make use of onScrollBeginDrag and onScrollEndDrag props.
state = {
scrollBegin: false
}
scrollStart = () => this.setState({scrollBegin: true})
scrollEnd = () => this.setState({scrollBegin: false})
<ScrollView onScrollBeginDrag={this.scrollStart} onScrollEndDrag={this.scrollEnd}>
... Other stuff
</ScrollView>
and set activeOpacity={1} for TouchableOpacity when this.state.scrollBegin=true
You could try replace TouchOpacity with RectButton in 'react-native-gesture-handler'. And don't forget to replace the ScrollView import from 'react-native' to 'react-native-gesture-handler'.
I found this solution in here.
It just said:
provides native and platform default interaction for buttons that are placed in a scrollable container (in which case the interaction is slightly delayed to prevent button from highlighting when you fling)
We implemeted a custom Touchable component using TouchableOpacity as click element and a wrapper View handling the opacity of the children elements.
By setting activeOpacity={1} to default and the pressed state to true when clicking, we can delay the rest of the onPress functionality by a unnoticeable 100ms to display an opacity shift when clicking. Which is shipped to the wrapper View. The View is wrapped inside the touchable instead of outside to better preserve styling.
We also added cleanup when component is unmounted in useEffect()
import React, { useEffect, useState } from "react";
import { View, TouchableOpacity } from "react-native";
const Touchable = (props) => {
const { children, onPress } = props;
const [pressed, setPressed] = useState(false);
useEffect(() => {
return setPressed(false);
}, []);
return (
<TouchableOpacity
{...props}
activeOpacity={1}
onPress={() => {
setPressed(true);
setTimeout(() => {
setPressed(false);
onPress();
}, 100);
}}
>
<View style={{opacity: pressed ? 0.8 : 1}}>
{children}
</View>
</TouchableOpacity>
);
};
export default Touchable;
I had the same issue, so I wrote this class that I use instead of <TouchableOpacity> in my code:
import React, { Component } from 'react';
import { TouchableOpacity } from 'react-native';
import TimerMixin from 'react-timer-mixin';
class TouchableOpacityScrollable extends Component {
_onPress() {
const { onPress } = this.props;
// Looking in the TouchableOpacity source code we see that
// the touch Opacity is 150, and that it comes back in 250 milliseconds.
// #see https://github.com/facebook/react-native/blob/c416b40542ece64e26fb2298485ae42eeebc352a/Libraries/Components/Touchable/TouchableOpacity.js
this.refs.touchableOpacity.setOpacityTo(0.2, 150);
TimerMixin.setTimeout(() => {
onPress();
this.refs.touchableOpacity.setOpacityTo(1, 250);
}, 150);
}
render() {
const { style, children } = this.props;
return (
<TouchableOpacity
ref="touchableOpacity"
style={style}
activeOpacity={1.0}
onPress={() => this._onPress()}
>
{children}
</TouchableOpacity>
);
}
}
export default TouchableOpacityScrollable;
You will have to install react-timer-mixin to prevent possible crashes.
Enjoy!
after upgrading RN version to 0.63.2 TouchableOpacity is working like it should, during scrolling, hover effect doesn't appears

Want to change opacity with react native refs on click

Here is my code. I want to change the opacity of refs when i click on any TouchableOpacity component.Please guide me how i can change opacity or change colour in react native with refs.
When i click my redirect function calls so i wanna change the opacity of particular ref in redirect function, i am passing ref and routename is redirect function.
i
mport React, { Component } from 'react';
import {
View,
Text,
TouchableOpacity,
StyleSheet
} from 'react-native';
export default class Navigation extends Component {
redirect(routeName,ref)
{
console.log(this.refs[ref]]);
this.props.navigator.push({
ident: routeName
});
}
render() {
return (
<View style={style.navigation}>
<View style={[style.navBar,styles.greenBack]}>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"AddItem","a")} ref="a">
<Text style={[style.navText,style.activeNav]}>HOME</Text></TouchableOpacity>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"AddItem","b")} ref="b">
<Text style={style.navText}>ORDER</Text></TouchableOpacity>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"ListItem","c")} ref="c">
<Text style={style.navText}>SHOP LIST</Text></TouchableOpacity>
<TouchableOpacity style={style.navPills} onPress={ this.redirect.bind(this,"ListItem","d")} ref="d">
<Text style={style.navText}>DUES</Text></TouchableOpacity>
</View>
<View style={style.titleBar}>
<Text style={style.titleBarText}>{this.props.title}</Text>
</View>
</View>
);
}
}
const style = StyleSheet.create({
navigation:{
top:0,
right:0,
left:0,
position:'absolute'
},
navBar:{
flexDirection:'row',
padding:10,
paddingTop:15,
paddingBottom:15,
},
navPills:{
flex:1,
alignItems:'center'
},
navText:{
flex:1,
textAlign:'center',
fontSize:16,
fontWeight:'bold',
color:'#ffffff',
opacity:0.7
},
titleBar:{
backgroundColor:'#ffffff',
flex:1,
padding:8,
alignItems:'center',
borderBottomWidth:1,
borderBottomColor:'#dddddd'
},
titleBarText:{
fontSize:18
},
activeNav:{
opacity:1
}
});
I am not exactly sure if the following is what u are searching:
If you want to change the opacity of the TouchableOpacity use the following
export default class Navigation extends Component {
state={
opacity: 0.1
}
handleOnPress = () => {
this.setState({
opacity: 0.5 //Anything u want
});
}
render(){
return(
<TouchableOpacity underlayColor={'rgba(0,0,0,this.state.opacity)'} onPress={this.handleOnPress}>
)
}
}
If you want to change the opacity of your text use the following
export default class Navigation extends Component {
state = {
opacity: 0.1
}
handleOnPress = () => {
this.setState({
opacity: 0.5 //Anything u want
});
}
render(){
return(
<TouchableOpacity onPress={this.handleOnPress}>
<Text style={[style.navText, {opacity: this.state.opacity}]}>DUES</Text>
</TouchableOpacity>
)
}
}
Using the Stylemethods in the render allows you to take variables from the state
Hope this is the answer you wanted. If One of both is the right let me know and i delete the other one.
Best Regards
Put your opacity value into state. Then make the button click change the value of that state. This will trigger a re-render and your view will update with the new opacity.
To expand on the answer from pomo...
With the styles as you currently have them, you can easily call setState within each of your onPress functions to change the opacity of the elements you need changed. You don't even need to pass a reference if you utilize a different key in the state for each item.
Then, in your styles you would use an array of styles to use the opacity value from the state.
style={[style.navPills, { opacity: this.state.opacityA }]}
I'm not a fan of inline styles at all. So, for my purposes in a recent project I set the style of an element using its 'ref' value, then triggered a state change merely to cause the render function to be called. This is what I believe you're asking for and this sample code should point you in the right direction, otherwise perhaps this will help someone else in the future.
toggleDisplay() {
if (this.refs.blah.style.display === "") { // currently visible
this.refs.blah.style.display = "none";
this.setState({showBlah = false});
} else { // currently not visible
this.refs.blah.style.display = "";
this.setState({showBlah: true});
}
}
render() {
// Some element defined with the ref value used above.
return (<div>
<div ref="blah">Now you see me...</div>
<button onClick="this.toggleDisplay">Toggle Me</button>
</div>);
}
Nothing in my render function changed by adding the toggle functionality, other than adding a button somewhere to call the function. As I already indicated, that state value is only used to trigger the render process.