React Native Scrollview keyboardshouldpersisttaps not working for ios - reactjs

I have a Login screen where I wrap the entire component with ScrollView and apply keyboardshouldpersisttaps prop as always. The prop seems to work fine on android but not on ios, on tapping the textInput, it gets hidden under keyboard.
Below is my code for the login screen
<View>
<ScrollView
style={styles.scrollviewStyle}
keyboardShouldPersistTaps="always">
<View style={styles.topContainerStyle}>
<View style={styles.padding}>
<Text style={styles.skipTextStyle}>SKIP</Text>
<Image source={BlackLogo} style={styles.logoStyle} />
</View>
</View>
<Image source={PreLoginImage} style={styles.preLoginImageStyle} />
<View style={styles.padding}>
<Text style={styles.getStartedTextStyle}>Let's Get started</Text>
<View style={styles.bottomContainer}>
<TextInput
// onChangeText={mobile => this.onMobileEnter(mobile)}
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
value={this.state.mobile}
maxLength={10}
onCodeChange={this.onCodeChange}
/>
<TouchableHighlight
disabled={!this.state.mobile ? true : false}
onPress={() => this.onProceedPress()}
style={
!this.state.mobile
? styles.disabledContinueButtonStyles
: styles.continueButtonStyles
}>
<Text
style={{
alignSelf: 'center',
fontFamily: 'Roboto-Medium',
fontSize: 16,
marginTop: 18,
color: '#FFFFFF',
}}>
CONTINUE
</Text>
</TouchableHighlight>
</View>
<Text style={styles.termsStyle}>
By continuing, you agree to Remedico's terms of use and privacy
Policy.
</Text>
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
topContainerStyle: {
backgroundColor: '#F4EBE4',
height: deviceHeight * 0.4,
},
logoStyle: {
width: 139,
height: 45,
resizeMode: 'contain',
top: 123,
},
padding: {
padding: 24,
},
preLoginImageStyle: {
width: 178,
height: 167,
position: 'absolute',
top: deviceHeight * 0.2,
left: deviceWidth * 0.5,
},
getStartedTextStyle: {
paddingTop: 60,
fontFamily: 'Ubuntu-Medium',
fontSize: 20,
},
skipTextStyle: {
left: deviceWidth - 80,
fontFamily: 'Roboto-Medium',
fontSize: 16,
},
bottomContainer: {
paddingTop: 32,
},
continueButtonStyles: {
marginTop: 84.5,
borderRadius: 25,
backgroundColor: '#00ACC1',
height: 55,
},
disabledContinueButtonStyles: {
marginTop: 84.5,
borderRadius: 25,
backgroundColor: '#CCCCCC',
height: 55,
},
termsStyle: {
fontFamily: 'Roboto-Regular',
fontSize: 12,
paddingTop: 32,
color: '#808080',
},
scrollviewStyle: {
backgroundColor: '#FFF',
height: deviceHeight,
},
// activityIndicatorStyle:{
// marginTop: 84.5
// },
});
Please do suggest why is it so, and how will it be working on ios, any suggestion would be a help,thanks in advance.

I don't think keyboardshouldpersisttaps props of ScrollView will solve your problem. This props will only dismiss the keyboard when you press on the container view.
Please check ref: https://reactnative.dev/docs/scrollview#keyboardshouldpersisttaps
I suggest you to use https://github.com/APSL/react-native-keyboard-aware-scroll-view for your problem.
Hope that help. :)

Related

Flex value for main view causing all of my content to dissapear

I am working on a react native coffee app and trying to create the lay out where I have
the header
the scrollable container holding my coffee
a footer with a text input
a '+' icon to add the coffees to the container
Currently the flex value of my main 'View' is causing my entire app to push to the top of the screen and i have no idea why. I can set the height and width to 100% without flex and i can fill the screen but then i cannot configure my footer properly (+ i know this is bad practice..)
What am i doing wrong with my styles?
const Main = () => {
return(
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerText}> List of Coffee </Text>
</View>
<ScrollView styles={styles.scrollContainer}>
</ScrollView>
<View styles={styles.footer}>
<TextInput
styles={styles.textInput}
placeholder="add your latest coffee here"
placeholderTextColor="#EEE">
</TextInput>
</View>
<TouchableOpacity style={styles.addButton}>
<Text style={styles.addButtonText}>+</Text>
</TouchableOpacity>
</View>
);};
const styles = StyleSheet.create({
container: {
flex:1,
flexDirection:"column",
backgroundColor: 'grey',
},
footer: {
position: 'absolute',
bottom: 10,
left: 10,
right: 10,
backgroundColor: 'white',
zIndex: 9,
},
header: {
backgroundColor: 'black',
alignItems: 'center',
justifyContent: 'center',
borderBottomWidth: 10,
borderBottomColor: 'yellow' ,
paddingTop: 20,
},
headerText: {
color: 'white',
fontSize: 36,
padding: 26,
fontWeight: "500",
fontFamily: 'Helvetica',
},
scrollContainer:{
marginBottom: 100,
},
textInput: {
alignSelf: 'stretch',
color: 'black',
padding:20,
backgroundColor: 'black',
borderTopWidth: 2,
borderTopColor: 'black',
fontSize: 32,
},
addButton: {
position: 'absolute',
zIndex: 11,
right: 20,
bottom: 100,
backgroundColor: 'black',
width: 80,
height: 80,
borderRadius: 50,
justifyContent: 'center',
alignItems: 'center',
} ,
addButtonText:{
color: '#FFD700',
fontSize: 36,
fontWeight: '700',
},
});
export default Main;

Stack Masked View to Make Curved Card React Native

Anyone know how to make card like this using view only?
desired result
Currently I'm still using SVG combined with view, but I'm curious if this result can be achieved using view only method.
I've searching about masked-view in react native using this library
https://github.com/react-native-masked-view/masked-view
but I have a gradle issue when I'm trying to build the app.
And apparently this issue hasn't solved yet.
https://github.com/react-native-masked-view/masked-view/issues/89
Current Result using SVG
current result
Component :
<View style={styles.card}>
<Image
source={{
uri:
'https://media.istockphoto.com/vectors/flat-cityscape-with-blue-sky-white-clouds-and-sun-modern-city-skyline-vector-id931139544?s=612x612',
}}
style={[
styles.cardImage,
{
justifyContent: 'center',
marginTop: 0,
resizeMode: 'cover',
},
]}
/>
{/* <View style={[styles.cardImage, {}]} /> */}
<View
style={{
position: 'absolute',
bottom: 60,
}}>
<SvgExclude color={'#FFF'} />
</View>
<View style={[styles.cardDescription, {}]}>
<Text>
Kota Indonesia dan Keunikannya
</Text>
</View>
</View>
Style :
const styles = StyleSheet.create({
card: {
marginTop: 16,
width: windowWidth - 32,
marginHorizontal: 16,
backgroundColor: '#FFF',
height: 179,
borderRadius: 16,
elevation: 2,
overflow: 'hidden',
},
cardImage: {
width: '100%',
height: 134,
backgroundColor: 'black',
position: 'absolute',
top: 0,
},
cardDescription: {
height: 60,
width: windowWidth - 32,
borderBottomEndRadius: 16,
borderBottomStartRadius: 16,
borderTopEndRadius: 16,
backgroundColor: '#FFF',
position: 'absolute',
bottom: 0,
padding: 12,
},
});
SVG :
import * as React from 'react';
import Svg, {Path} from 'react-native-svg';
function SvgExclude(props) {
return (
<Svg
width={16}
height={16}
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}>
<Path
fillRule="evenodd"
clipRule="evenodd"
d="M0 0c0 8.837 7.163 16 16 16H0V0z"
fill={props.color}
/>
</Svg>
);
}
export default SvgExclude;
Thankyou..
I tried it on snack please have a look at it. I'm using View only for this design.
import * as React from 'react';
import { View } from 'react-native';
export default function App() {
return (
<View style={{
alignSelf:'center',
marginTop:100
width:300,
height:250,
backgroundColor:'red',
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
borderRadius:10
}}>
<View style={{
position:'absolute',
bottom:0,
height:100,
width:'100%',
backgroundColor:'white',
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 10,
},
shadowOpacity: 0.5,
shadowRadius: 13.84,
elevation: 10,
borderBottomLeftRadius:10,
borderBottomRightRadius:10,
borderTopRightRadius:10,
}}>
<View style={{
position:'abolute',
backgroundColor:'red',
top:0,
width:'100%',
height:20,
borderBottomLeftRadius:20
}}>
</View>
</View>
</View>
);
}

Why my horizontal ScrollView is not working?

I´m trying without success to use the ScrollView component in React Native, below the code:
const width_proportion = '97%';
const height_proportion = '75%';
const styles = StyleSheet.create({
container: {
height: '100%'
},
image: {
flex: 1,
resizeMode: "cover",
justifyContent: "center"
},
text: {
color: "grey",
fontSize: 30,
fontWeight: "bold"
},
popup: {
color: '#CA0',
},
box: {
width: width_proportion,
height: height_proportion,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'steelblue',
// position: "absolute",
marginTop: '5%',
marginBottom: '3%',
marginLeft: '2%'
},
bottomBox: {
width: '97%',
height: 125,
backgroundColor: 'steelblue',
marginLeft: '2%',
marginBottom: 10,
marginTop: 5,
padding: 5
}
});
const MyTheme = {
colors: {
...DefaultTheme.colors,
background: '#EFA',
primary: '#000',
text: '#000',
},
};
function HomeScreen({ navigation }) {
return (
<View style={styles.container}>
<View style={{ width: '100%', height: 50, backgroundColor: 'steelblue' }}>
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<Image source={hamburgerMenu} style={{ height: 45, width: 45, alignItems: 'center' }}>
</Image>
</TouchableOpacity>
</View>
<ImageBackground source={imgBackground} style={styles.image}>
<View style={styles.box}>
</View>
<ScrollView horizontal={true} >
<View style={styles.bottomBox}>
</View>
<View style={styles.bottomBox}>
</View>
<View style={styles.bottomBox}>
</View>
</ScrollView>
</ImageBackground>
</View >
);
}
When I set the horizontal property to "true" from ScrollView, the component disappears. Only I set horizontal to "false" and the ScrollView workks fine in Vertical.
wrap your scrollview like this
<ScrollView horizontal={true}>
<View style={styles.bottomBox} />
<View style={styles.bottomBox} />
<View style={styles.bottomBox} />
</ScrollView>
bottomBox : {
width: 40,
height: 125,
backgroundColor: 'steelblue',
padding: 5,
marginRight: 10,
}

ripple effect leaking at corners as if Pressable button has a borderRadius

I'm using Pressable for buttons after referring this docs pressable docs
Now I want to add ripple effect to the button but it is not working properly.
<Pressable
android_ripple={{color: 'red', borderless: false}}
style={{backgroundColor: 'blue',borderRadius : 10}}>
<Text style={{alignSelf: 'center'}}>Button</Text>
</Pressable>
Ripple effect don't have border radius if button has radius.
it looks awkward that ripple effect corners go out of the curved radius.
Snack demonstrating the problem: https://snack.expo.dev/6U8dxxzLx
Nothing worked for me, So I solved this myself.
pressable should be wrapped in a view
view must have margin not padding
border radius must be on view not on pressable
pressable component must have padding not margin
then add ripple by android_ripple={{color: 'black', borderless: true}} to pressable.
<View style={styles.buttonView}>
<Pressable
onPress={() => {}}
android_ripple={{color: 'black', borderless: true}}
style={styles.loginButton}>
<Text style={styles.buttonText}>Login</Text>
</Pressable>
</View>
buttonView: {
alignSelf: 'stretch',
justifyContent: 'center',
borderRadius: 10,
elevation: 25,
margin: 10,
},
loginButton: {
height: 50,
backgroundColor: '#0f4c75',
padding: 10,
alignItems: 'center',
justifyContent: 'center',
},
buttonText: {
color: 'white',
fontSize: 16,
textTransform: 'uppercase',
fontFamily: 'sans-serif-light',
},
Update:-
Floating pressable component with ripple leakage fixed
<View style={{
position: 'absolute',
bottom: 250,
borderRadius: 50,
overflow: 'hidden',
alignSelf: 'center'
}}>
<Pressable
style={{
height: 60,
width: 60,
borderRadius: 50,
backgroundColor: 'red',
justifyContent: 'center',
alignItems: 'center',
elevation: 4,
}}
android_ripple={{
color: 'black',
}}
onPress={() => { console.log('om') }}>
<Text>O</Text>
</Pressable>
</View>
You can wrap pressable into View and pass borderRadius:10 and overflow:'hidden' to View style.
<View style={{ borderRadius: 10, overflow: 'hidden' }}>
<Pressable
android_ripple={{ color: 'red', borderless: false, }}
style={{ backgroundColor: 'blue', borderRadius: 10 }}>
<Text style={{ alignSelf: 'center' }}>Button</Text>
</Pressable>
</View>
Turns out the other solution don't cover all edge cases... I needed to wrap the view 2 times to manage elevation and shadow on iOS. (The button is in absolute position also).
export const PNFloatingButton = ({ children, ...props }) => {
return (
<View style={thisStyles.shadow}>
<View style={thisStyles.parentContainer}>
<Pressable style={thisStyles.button}
android_ripple={{ borderless: false, color: "#0F0" }}>
<Text>Button</Text>
</PNPressable>
</View>
</View>
)
}
const thisStyles = StyleSheet.create({
shadow: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.4,
shadowRadius: 4,
width: 56,
height: 56,
position: 'absolute',
elevation: 2,
right: 0,
bottom: 0,
},
button: {
padding: 4,
backgroundColor: "#F00",
},
parentContainer: {
// Pressable has issues with borderRadius on the ripple on android
overflow: "hidden",
borderRadius: 40,
},
})
For those that are using the Button element I found a simple workaround. Since this problem happens always when border od the button is changed (like became rounded) I just pass to the containerStyle of the button all the props + my button border radius. I add also the overflow property with hidden attribute.
Some little context: myButtonStyle is the style I want to apply to that button. If it's null, I'll apply a default style. Same for myContainerStyle.
The function inplemented before return():
function fixRippleBorder() {
const borderRadius = myButtonStyle
? EStyleSheet.flatten(myButtonStyle).borderRadius
: EStyleSheet.flatten(defaultButtonStyle).borderRadius;
return {
borderRadius: borderRadius,
overflow: 'hidden',
};
}
The button itself:
<Button
containerStyle={[
myContainerStyle ?? defaultContainerStyle,
fixRippleBorder(),
]}
buttonStyle={myButtonStyle ?? defaultButtonStyle}
...
You can add the style overFlow: 'hidden' to a view that wraps around your pressable object as long as that view also contains your borderRadius. Below is an example of a file I worked on recently that does this
import React from 'react';
import {Pressable, View, Text, StyleSheet, Platform} from 'react-native';
export default function CategoryGridTile({title, color, onPress}) {
return (
<View style={styles.gridItem}>
<Pressable
android_ripple={{color: '#ccc'}}
style={({pressed}) => [
styles.button,
pressed ? styles.buttonPressed : null,
]}
onPress={onPress}>
<View style={[styles.innerContainer, {backgroundColor: color}]}>
<Text style={styles.title}>{title}</Text>
</View>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
gridItem: {
flex: 1,
margin: 16,
height: 150,
borderRadius: 8,
elevation: 4,
backgroundColor: 'white',
shadowColor: 'black',
shadowOpacity: 0.25,
shadowOffset: {width: 0, height: 2},
shadowRadius: 8,
overflow: 'hidden',
},
button: {
flex: 1,
},
buttonPressed: {
opacity: 0.5,
},
innerContainer: {
flex: 1,
padding: 16,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontWeight: 'bold',
fontSize: 18,
},
});

React Native. Lagged scroll animation in ScrollView

When I scroll vertically up and down, animation starts lagging in the first two components (CompetitionsList, CampList) after the slider (BannerSwiper). I couldn’t fix it. I tried using Animation.ScrollView with "UseNativeDriver: true", but it didn’t help. Something might be wrong with css.
Here is a gif of screen:
https://i.yapx.ru/DT9CR.gif
This is my code:
export default class HomeComponent extends React.Component {
render() {
return (
<View style={styles.container}>
<ScrollView >
<BannerSwiper/>
<CompetitionsList home={true} {...this.props}/>
<CustomDivider/>
<CampList home={true} {...this.props}/>
<CustomDivider/>
<NewsComponent home={true} {...this.props}/>
<CustomDivider/>
<AthletesBirthdayList {...this.props}/>
<CustomDivider/>
<RatingsBlock/>
<CustomDivider/>
<SocialBlock/>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f2f2f2',
}
});
export default class CompetitionsList extends React.Component {
...
render() {
const {
compListForHome
} = this.props.competitions;
return (
<View style={styles.homeContainer}>
<View style={styles.headerContainer}>
<Text style={[styles.header, {marginRight: 'auto'}]}>СОРЕВНОВАНИЯ</Text>
<Text
style={[styles.header, {marginLeft: 'auto', color: '#2f95dc'}]}
onPress={() => this.props.routing('navigate', 'Competitions')}
>ВСЕ</Text>
</View>
<View style={{alignItems: 'center'}}>
<View style={styles.contentContainer}>
<ScrollView
style={{flex: 1}}
horizontal={true}
showsHorizontalScrollIndicator={false}>
<AnimatedComponent>
<View style={styles.cardContainer}>
<View style={styles.cardWrapper}>
{
compListForHome.map(event =>
<TouchableWithoutFeedback key={event.id} onPress={() => console.log(event.id)}>
<Card
containerStyle={styles.cardWidth}
title={
<View style={styles.cardTitleStyleContainer}>
<Text numberOfLines={1} style={styles.cardTitleStyleText}>{event.name}</Text>
</View>
}
imageStyle={styles.image}
image={event.URL_logo? {uri: event.URL_logo} : SP_IMAGE}>
<View style={styles.cardLabeledContainer}>
<Text style={styles.cardTextLabeled} numberOfLines={1}>{dateFormatter(event.start_date)}</Text>
<Text style={styles.cardTextLabeled} numberOfLines={1}>{dateFormatter(event.end_date)}</Text>
</View>
<Text style={styles.cardText} numberOfLines={1}>{getFullCourseNameByCode(event.course)}</Text>
<Text style={styles.cardText} numberOfLines={1}>{getFullCompetitionStatusByCode(event.status)}</Text>
{
event.reg_status
? <Text style={styles.cardText} numberOfLines={1}>Регистрация: {getFullRegistrationStatusByCode(event.reg_status)}</Text>
: null
}
</Card>
</TouchableWithoutFeedback>
)
}
</View>
</View>
</AnimatedComponent>
</ScrollView>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
spinContainer: {
height: 50
},
overlay: {
flex: 1,
position: 'absolute',
bottom: 10,
width: SCREEN_WIDTH,
justifyContent: 'center',
alignItems: 'center'
},
filterBtn: {
backgroundColor: '#2f95dc',
alignSelf: 'center'
},
homeContainer: {
flex: 1,
marginHorizontal: 50
},
fullListContainer: {
flex:1
},
headerContainer: {
flex: 1,
flexDirection: 'row',
width: SCREEN_WIDTH-80
},
header: {
fontSize: 17,
color: 'rgba(96,100,109, 1)',
lineHeight: 24,
marginTop: 15
},
contentContainer: {
flex: 1,
marginTop: 10,
width: SCREEN_WIDTH
},
cardContainer: {
flex: 1,
flexDirection: 'column',
marginRight: 10
},
cardWrapper: {
flex: 1,
flexDirection: 'row'
},
cardTitleStyleContainer: {
padding: 20,
marginBottom: 15,
borderTopStartRadius: 5,
borderTopEndRadius: 5,
backgroundColor: "#2f95dc",
alignItems: 'center'
},
cardTitleStyleText: {
fontSize: 16,
lineHeight: 24,
color: '#fff',
fontWeight: 'bold'
},
cardWidth: {
width: 250,
height: 360,
borderWidth: 1,
borderRadius: 6,
borderColor: '#ddd',
shadowColor: '#000',
shadowOffset: { width: 5, height: 5 },
shadowOpacity: 0.8,
shadowRadius: 5,
elevation: 4,
marginBottom: 7
},
image: {
width: 100,
height: 100,
borderRadius: 100,
overflow: 'hidden',
alignSelf: 'center'
},
cardText: {
color: 'rgba(96,100,109, 0.8)',
fontSize: 14,
lineHeight: 14,
alignSelf: 'center',
marginBottom: 10
},
cardLabeledContainer: {
backgroundColor: 'rgba(0,0,0,0.05)',
borderRadius: 3,
marginTop: 10,
marginBottom: 20,
marginHorizontal: 30,
padding: 5
},
cardTextLabeled: {
alignSelf: 'center',
fontSize: 15,
color: 'rgba(96,100,109, 0.8)'
}
});
Thank you for your help!

Resources