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
Related
When I am using custom tab bar through tabBar function tabBarHideOnKeyboard does not work but without tabBar function it works fine, any ideas on how I can make it work using tabBar function as well.
Add "softwareKeyboardLayoutMode": "pan" in app.json file under "android" key and then restart your expo server with expo start -c
<Tab.Navigator
tabBarOptions={{
showLabel: false,
keyboardHidesTabBar: true, // use this props to hide bottom tabs when keyboard shown
}}
the docs says to use tabBarHideOnKeyboard, but not working at all.
then i found keyboardHidesTabBar and works like a charm
I was using my customTab as well. And after huge amount of search, solved the problem with the help of Keyboard event listeners.
This is the best solution, I've found so far.
Here's my solution:
import { useEffect, useState } from "react";
import { Keyboard, Text, TouchableOpacity, View } from "react-native"
export default function TabBar({ state, descriptors, navigation }) {
// As default it should be visible
const [visible, setVisible] = useState(true);
useEffect(() => {
const showSubscription = Keyboard.addListener("keyboardDidShow", () => {
//Whenever keyboard did show make it don't visible
setVisible(false);
});
const hideSubscription = Keyboard.addListener("keyboardDidHide", () => {
setVisible(true);
});
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}, []);
//Return your whole container like so
return visible && (
<View>
...
</View>
)
tabBarHideOnKeyboard or keyboardHidesTabBar options didn't work for me.
You'll get the tabBarHideOnKeyboard from the props for the custom tabBar.
tabBar={(props) => {
return (
<View>
{props.state.routes.map((route, index) => {
// You can replace Pressable and View with anything you like
return (
props.descriptors[route.key].options.tabBarHideOnKeyboard && (
<Pressable>
<View
style={{
width: 200,
height: 200,
backgroundColor: "green",
}}
/>
</Pressable>
)
);
})}
</View>
);
You can read more here
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
<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
Is it possible to tell a ScrollView to scroll to a specific position when we just navigated to the current screen via StackNavigator?
I have two screens; Menu and Items. The Menu is a list of Buttons, one for each item. The Items screen contain a Carousel built using ScrollView with the picture and detailed description of each Item.
When I click on a button in the Menu screen, I want to navigate to the Items screen, and automatically scroll to the Item that the button represent.
I read that you can pass in parameters when using the StackNavigator like so: but I don't know how to read out that parameter in my Items screen.
navigate('Items', { id: '1' })
So is this something that is possible in React Native and how do I do it? Or perhaps I'm using the wrong navigator?
Here's a dumbed down version of my two screens:
App.js:
const SimpleApp = StackNavigator({
Menu: { screen: MenuScreen},
Items: { screen: ItemScreen }
}
);
export default class App extends React.Component {
render() {
return <SimpleApp />;
}
}
Menu.js
export default class Menu extends React.Component {
constructor(props){
super(props)
this.seeDetail = this.seeDetail.bind(this)
}
seeDetail(){
const { navigate } = this.props.navigation;
navigate('Items')
}
render(){
<Button onPress={this.seeDetail} title='1'/>
<Button onPress={this.seeDetail} title='2'/>
}
}
Items.js
export default class Items extends React.Component {
render(){
let scrollItems = [] //Somecode that generates and array of items
return (
<View>
<View style={styles.scrollViewContainer}>
<ScrollView
horizontal
pagingEnabled
ref={(ref) => this.myScroll = ref}>
{scrollItems}
</ScrollView>
</View>
</View>
)
}
}
P.S I am specifically targeting Android at the moment, but ideally there could be a cross-platform solution.
I read that you can pass in parameters when using the StackNavigator like so: but I don't know how to read out that parameter in my Items screen.
That is achieved by accessing this.props.navigation.state.params inside your child component.
I think the best time to call scrollTo on your scrollview reference is when it first gets assigned. You're already giving it a reference and running a callback function - I would just tweak it so that it also calls scrollTo at the same time:
export default class Items extends React.Component {
render(){
let scrollItems = [] //Somecode that generates and array of items
const {id} = this.props.navigation.state.params;
return (
<View>
<View style={styles.scrollViewContainer}>
<ScrollView
horizontal
pagingEnabled
ref={(ref) => {
this.myScroll = ref
this.myScroll.scrollTo() // !!
}>
{scrollItems}
</ScrollView>
</View>
</View>
)
}
}
And this is why I use FlatLists or SectionLists (which inherit from VirtualizedList) instead of ScrollViews. VirtualizedList has a scrollToIndex function which is much more intuitive. ScrollView's scrollTo expects x and y parameters meaning that you would have to calculate the exact spot to scroll to - multiplying width of each scroll item by the index of the item you're scrolling to. And if there is padding involved for each item it becomes more of a pain.
Here is an example of scroll to the props with id.
import React, { Component } from 'react';
import { StyleSheet, Text, View, ScrollView, TouchableOpacity, Dimensions, Alert, findNodeHandle, Image } from 'react-native';
class MyCustomScrollToElement extends Component {
constructor(props) {
super(props)
this.state = {
}
this._nodes = new Map();
}
componentDidMount() {
const data = ['First Element', 'Second Element', 'Third Element', 'Fourth Element', 'Fifth Element' ];
data.filter((el, idx) => {
if(el===this.props.id){
this.scrollToElement(idx);
}
})
}
scrollToElement =(indexOf)=>{
const node = this._nodes.get(indexOf);
const position = findNodeHandle(node);
this.myScroll.scrollTo({ x: 0, y: position, animated: true });
}
render(){
const data = ['First Element', 'Second Element', 'Third Element', 'Fourth Element', 'Fifth Element' ];
return (
<View style={styles.container}>
<ScrollView ref={(ref) => this.myScroll = ref} style={[styles.container, {flex:0.9}]} keyboardShouldPersistTaps={'handled'}>
<View style={styles.container}>
{data.map((elm, idx) => <View ref={ref => this._nodes.set(idx, ref)} style={{styles.element}}><Text>{elm}</Text></View>)}
</View>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexGrow: 1,
backgroundColor:"#d7eff9"
},
element:{
width: 200,
height: 200,
backgroundColor: 'red'
}
});
export default MyCustomScrollToElement;
Yes, this is possible by utilising the scrollTo method - see the docs. You can call this method in componentDidMount. You just need a ref to call it like: this.myScroll.scrollTo(...). Note that if you have an array of items which are all of the same type, you should use FlatList instead.
For iOS - the best way to use ScrollView's contentOffset property. In this way it will be initially rendered in a right position. Using scrollTo will add additional excess render after the first one.
For Android - there is no other option rather then scrollTo
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.