Two cards side by side react native - react-native

I referred to lot of places but still the issue persist, I've a card list here im displaying just four cards, now I want each row to have two cards each, but unable to do so. Here is the code for reference.
<View style={styles.panelBox}>
<TouchableOpacity
activeOpacity={1}
onPress={() => navigation.navigate('ExploreCareersIndex', { pathway_id: pathway.id })}
style={[styles.card]}>
<ImageBackground
resizeMode='cover'
style={styles.cardBody}
imageStyle={styles.imageRadius}
source={{uri: pathway.avatar_url}}>
</ImageBackground>
<Text style={styles.textImageStyle}>{pathway.name}</Text>
</TouchableOpacity>
</View>
and the CSS
panelBox: {
paddingHorizontal: 15,
paddingLeft: 10,
paddingRight: 10,
backgroundColor:'blue',
flexDirection:'row',
flexWrap:'wrap',
flex:1,
flexBasis:2,
},
card: {
backgroundColor: Colors.white,
width: "40%",
height:130,
textAlign: "center",
backgroundColor:'red',
},
cardBody: {
padding: 10,
justifyContent: "space-between",
overflow: "hidden",
shadowColor: Colors.black,
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
height: 80,
},
imageRadius: {
borderTopLeftRadius: 5,
borderTopRightRadius: 5,
},
cardtitle: {
textAlign: "left",
fontSize: 12,
lineHeight: 16,
color: Colors.white,
fontFamily: primaryFont.fontMedium,
paddingRight: 10,
},
textImageStyle: {
textAlign: 'center',
fontSize: 12.5,
fontFamily: primaryFont.fontMedium,
marginTop: 5,
color: Colors.gray4,
height: '100%',
},
still unsure why it isnt working. If you still need more reference I can provide some screenshot as well.

Since you are trying to display a list of items try to use FlatList or SectionList. Using numColumns Props in React Native FlatList you can easily display multiple columns layout.
Check below sample
import React, { Component } from "react";
import { View, FlatList, StyleSheet, Text, Dimensions } from "react-native";
const ScreenWidth = Dimensions.get("window").width;
const DATA = [
{
id: "1",
title: "1"
},
{
id: "2",
title: "2"
},
{
id: "3",
title: "3"
}
];
export default class Example extends Component {
renderItems = ({ item }) => (
<View style={styles.item}>
<Text style={styles.title}>{item.title}</Text>
</View>
);
render() {
return (
<View style={styles.container}>
<FlatList
data={DATA}
renderItem={this.renderItems}
keyExtractor={item => item.id}
numColumns={2}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center"
},
item: {
width: (ScreenWidth - 40) / 2 - 10,
backgroundColor: "#000",
padding: 10,
marginVertical: 10,
marginHorizontal: 10
},
title: {
fontSize: 32,
color: "#fff",
alignSelf: "center"
}
});
If you have any doubts feel free to ask. Hope this will helps you.

Not sure is this what you want, two card in a row. So, in react-native you can just flex:1 for parent, and set width:'100%' for child, and it will auto divided by two.
.grandparent{
display:flex;
flex-direction:column;
}
.parent{
display:flex; // in react-native just flex:1
}
.child{
background-color:#333;
height:100px;
width:100%;
border:1px solid #ccc;
text-align:center;
color:#fff;
font-size:30px;
}
<div class="grandparent">
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
</div>
<div class="parent">
<div class="child">3</div>
<div class="child">4</div>
</div>
</div>

You need to add ScrollView Insid the ScrollView add cards then in ScrollView add property horizontal={true}

Related

React Navigation (native): Overflow visible not working on custom header

I'm implementing a custom header for #react-navigation/native-stack. Using React Navigation v6.
One of the elements within the custom header has a native shadow on iOS added (via the style prop). The shadow is a tad bigger than the header and unfortunately, I can't get it to display beyond the boundaries of the header. Of course, I've tried using overflow: visible on basically every component in the tree, but no success. The shadow is clipped off:
Here's my custom header:
function CustomHeader(props: NativeStackHeaderProps) {
const { options, route, navigation } = props;
const insets = useSafeAreaInsets();
const headerHeight = Helpers.getHeaderHeight(insets);
return (
<View style={{
height: headerHeight,
paddingTop: insets.top,
width: '100%',
backgroundColor: Colors.white,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 20,
paddingRight: 20,
overflow: 'visible',
}}
>
<View style={{
flex: 1, display: 'flex', alignItems: 'flex-start',
}}
>
{ options.headerLeft ? options.headerLeft({ canGoBack: false }) : (
<TouchableOpacity
onPress={() => route.name === 'Home'
? null
: navigation.reset({ index: 0, routes: [{ name: 'Home' }] })}
>
<Image
style={{ width: Sizing.logo, height: Sizing.logo }}
source={Logo}
/>
</TouchableOpacity>
)}
</View>
<Text style={{
textAlign: 'center', color: Colors.purple,
}}
>
{(options.title || route.name).toUpperCase()}
</Text>
<View style={{
flex: 1, display: 'flex', alignItems: 'flex-end', overflow: 'visible',
}}
>
{ options.headerRight ? options.headerRight({ canGoBack: false }) : null}
</View>
</View>
);
}
The button on the right with the shadow is passed in through the headerRight option and contains this shadow style:
nativeShadow: {
shadowColor: Colors.gray,
shadowOffset: { width: 0, height: 8 },
shadowRadius: Colors.shadows.gray.distance,
shadowOpacity: 0.5,
},
Any idea what I could try next? I don't want to increase the headers' height since this would break the layout elsewhere.
I had a similar problem with the menu. I think i was taking another way and maybe you should try it.
Be sure that all the parent elements has at least the same height than the navmenu's height.
import React, { Component } from 'react';
import { TouchableOpacity, StyleSheet, Image, View, Text } from 'react-native';
const styles = StyleSheet.create({
menuParent: {
marginLeft: 30,
justifyContent: "flex-start",
alignItems: "flex-end",
flex: 1,
height: 250
},
btnContainer: {
width: 40,
height: 40,
elevation: 50,
zIndex: 50,
marginTop: 5
},
image: {
width: 40,
height: 40,
},
menuContainer: {
position: "absolute",
top: 5,
left: -5,
right: -5,
padding: 20,
borderRadius: 10,
elevation: 10,
zIndex: 10,
flex: 1,
height: 230,
backgroundColor: "#fff",
}
});
export default class DefaultHeaderMenu extends Component {
state = {
menuVisible: false
};
constructor(props) {
super(props);
}
render() {
return (
<View style={ styles.menuParent }>
{this.state.menuVisible ? <View style={ styles.menuContainer }></View> : null }
<TouchableOpacity
style={ styles.btnContainer }
onPress={ () => this.setState({ menuVisible: !this.state.menuVisible }) }
>
<Image
source={ require('#/assets/img/menu.png') }
style={ styles.image }
/>
</TouchableOpacity>
</View>
);
}
}
This is the component i used and the passed it to nav as headerRight element.
In my case, the problem was that height: 250 was missing in menuParent.
I hope it helps you and good luck
I had a problem like this once and fixed it by using 'zIndex'. Try setting it as the* max index in your project. Hope it helps

React Native view being pushed up and height changes dynamically when keypad pops out

I am designing an app in React Native and the problem I am facing right now is when I try to type in the TextBox, the keypad comes up and it pushes up or out the view changing height dynamically of other views too. Please check the Before and After image below:
The Code:
import React, { Component } from 'react';
import t from 'tcomb-form-native'; // 0.6.9
const Form = t.form.Form;
import {
StyleSheet,
View,
KeyboardAvoidingView,
TouchableOpacity,
ToastAndroid
} from 'react-native';
import { RFPercentage, RFValue } from "react-native-responsive-fontsize";
const styles = StyleSheet.create({
parentSectionContainer: {
flex: 1,
justifyContent: 'space-evenly',
backgroundColor: '#F1F0F2'
},
SignupFormParent: {
marginTop: 100,
alignSelf: 'center',
backgroundColor: '#FFFFFF',
height: '45%',
width: '85%',
borderRadius: 100,
shadowColor: '#2AC062',
shadowOpacity: 0.4,
shadowOffset: { height: 10, width: 0 },
shadowRadius: 20,
},
textMelow: {
width: RFPercentage(10),
fontSize: RFPercentage(2),
fontWeight: "normal",
color: '#FFFFFF',
textTransform: 'uppercase',
fontStyle: 'normal'
},
textBold: {
width: RFPercentage(10),
fontSize: RFPercentage(2),
fontWeight: "bold",
color: '#FFFFFF',
textTransform: 'uppercase',
fontStyle: 'normal'
},
btnContainer: {
paddingTop: 8,
width: '100%',
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignContent: 'center'
},
signupBodyStyle: {
position: "absolute",
bottom: 0,
width: '90%',
marginBottom: 20,
},
signinSignupButtonsBtnsContainer: {
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
alignItems: 'center',
width: '100%'
},
signupButtonBodyStyle: {
flex: 1,
backgroundColor: '#8A56AC',
borderRadius: 100,
alignItems: 'center',
padding: 25
},
signinSignupTextStyle: {
color: '#FFFFFF',
fontSize: 18,
}
});
const User = t.struct({
name: t.String,
email: t.String,
password: t.String,
"Confirm Password": t.String,
location: t.String
});
const SignupForm = (props) => {
const options = {
auto: 'placeholders',
};
return (
<View style={styles.SignupFormParent}>
<View style={{ paddingLeft: 20, paddingRight: 20, marginTop: 80 }}>
{/* <Text style={styles.text}>FORM</Text> */}
<Form type={User} options={options}/>
</View>
</View>
);
};
const ContinueButton = (props) => {
const { onPress, style } = props;
return (
<TouchableOpacity onPress={onPress} style={style.bodyStyle}>
<View
style={style.buttonStyle}>
<Text style={style.textStyle}>{props.title}</Text>
</View>
</TouchableOpacity>
);
}
export default class SignUpView extends Component {
// constructor(props) {
// }
fetch('${Config.IP}:${Config.PORT}/login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'jayndoe#foobar.com',
password: "jynd1234",
}),
})
.then(response => response.json())
.then(responseJson => {
ToastAndroid.showWithGravity(
JSON.stringify(responseJson),
ToastAndroid.SHORT,
ToastAndroid.CENTER,
);
})
.catch(error => {
ToastAndroid.showWithGravity(
JSON.stringify(error),
ToastAndroid.SHORT,
ToastAndroid.CENTER,
);
})
}
render() {
return(
<View style={styles.parentSectionContainer}>
<KeyboardAvoidingView style={{ position: 'absolute', top: 0, width: '100%', backgroundColor: '#8A56AC', height: '30%', borderBottomLeftRadius: 120 }}/>
<View style={{ position: 'absolute', top: 50, width: '100%', flexDirection: 'row', justifyContent: 'space-evenly', margin: 'auto' }}>
<Text style={styles.textBold}>LOG IN</Text>
<Text style={styles.textMelow}>SIGN UP</Text>
</View>
<SignupForm
title="SIGN UP USING INSTAGRAM"
onPress={() => {this.instagramSSO()}}
style={{formStyles: styles.formStyles}}
/>
<View style={{ flex: 1, flexDirection: 'column', alignItems: 'center' }}>
<ContinueButton
title="CONTINUE"
style={{ bodyStyle: styles.signinBodyStyle, buttonStyle: styles.signinButtonBodyStyle, textStyle: styles.signinSignupTextStyle }}
onPress={() => Alert.alert('Please sign-in!!')}
/>
</View>
</View>
);
}
}
Appreciate any help in resolving this issue :)
This is because of the absolute positionning of your views,
I think you used it because you needed to put the white input wrapper on top of the purple one view. Maybe you could remove the absolute positionning and use negative paddingTop on the white wrapper instead ? I am not sure how to achieve this using good practices, but that could prevent the keyboardavoidingview to push your other components.

How to add clickable rightButtons under topBar React Native Navigation?

I have integrated React Native navigation package. I want to add badge with the dynamic value on my topBar rightButton.
Github link of the package:: https://github.com/wix/react-native-navigation
I want an output like this. You can check this screenshot::
Issue::
If I am adding a count value on notification icon then there is no event occurs when I am trying to click on button. On click of this button I want to open up my notification screen.
Code:
static options({ menuIcon }) {
return {
topBar: {
title: {
fontFamily: font,
fontSize: fontSize.heading,
color: colors.white,
alignment: 'center',
text: strings.dashboard
},
alignment: 'center',
elevation: 0,
noBorder: true,
background: {
color: colors.dark
},
leftButtons: [
{
id: 'openSideMenu',
icon: menuIcon ? menuIcon : APIURLServiceSingleton.getInstance()._menuIcon
}
],
rightButtons: [
{
id: 'notificationButton',
component: {
name: 'component.notificationButton'
}
}
]
}
}
}
Code for my custom component::
<TouchableOpacity
onPress={() => this.openSystemAlerts()}
style={{ position: 'absolute', right: 0, bottom: -13 }}
>
<View style={styles.button}>
<View style={[posRelative]}>
<Icon
name="notifications-none"
size={27}
color={colors.white}
/>
{(unseen_count && unseen_count > 0) &&
<Text style={styles.badge}>{unseen_count}</Text>
}
</View>
</View>
</TouchableOpacity>
Environment
React Native Navigation version: 2.12.0
React Native version: 0.58
Platform(s) : IOS only(on version 10.0)
It seems that, position:'absolute' is creating problem,
Either ,
add zIndex:2 ...here, number must be greater than any other zIndex in its parent or if there is not any zIndex used then any number>0 is fine.
or
remove position:'absolute' and try styling without it.
try this component; worked fine for me
https://github.com/RajenderDandyal/smart-city-Mobile-App/blob/master/src/UI/TopBarCartCount/index.js
`
class TopBarCartCount extends Component {
handleCartPress = () => {
if (!this.props.isAuthenticated) {
NavigateUser(2, componentIds.myAccountStack, screenNames.signIn)
} else {
NavigateUser(2, componentIds.myAccountStack, screenNames.myCart)
}
};
render() {
return (
<View style={styles.containerWrapper}>
<TouchableOpacity onPress={this.handleCartPress}>
<View style={styles.container}>
{cartPlus}
<View style={styles.badge}>
<Text style={styles.countText}>
{this.props.cart.length}
</Text>
</View>
</View>
</TouchableOpacity>
</View>
);
}
}
let mapStateToProps = (state) => {
return {
cart: state.auth.user.cart ? state.auth.user.cart : [],
isAuthenticated: state.auth.isAuthenticated
}
}
export default connect(mapStateToProps)(TopBarCartCount);
const styles = StyleSheet.create({
containerWrapper: {
flex: 1,
height: 40,
width: 50,
justifyContent: 'center',
paddingTop: 15,
paddingRight: 5,
alignItems: 'center'
},
container: {
flex: 1,
height: 40,
width: 50,
paddingLeft: 5,
flexDirection: 'row',
alignItems: 'flex-start'
},
badge: {
backgroundColor: themeConstants.danger,
width: 15,
height: 15,
alignItems: 'center',
justifyContent: 'center',
paddingLeft: 0,
paddingTop: 1,
paddingBottom: 2,
marginLeft: 0,
borderRadius: 10
},
countText: {
fontSize: 10,
paddingLeft: 0,
color: themeConstants.offWhite
}
});`

React Native: Display FlatList data in Modal

I have a react native flat list that renders some data from a Wordpress website using wp rest api. The flat list is displaying the post correctly, and when clicked, it opens the modal, but I am having some trouble pushing the state to the modal.
Currently, when the modal opens, it shows the same (last post/item) for every item in the flat list. Any suggestions? Any help appreciated.
import React, { Component } from 'react';
import {
Image, Dimensions, View, ActivityIndicator, TouchableOpacity, TouchableHighlight,
WebView, ScrollView, StyleSheet, ImageBackground, FlatList, Text
} from 'react-native';
import Moment from 'moment';
import HTML from 'react-native-render-html';
import Modal from "react-native-modal";
export default class LatestNews extends Component {
constructor(props) {
super(props);
this.state = {
isModalVisible: false,
isLoading: true,
posts: [],
id: null,
};
}
componentDidMount() {
fetch(`http://mywebsite.com/wp-json/wp/v2/posts/?_embed&categories=113`)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
posts: responseJson,
})
})
.catch((error) => {
console.error(error);
});
}
_toggleModal = () =>
this.setState({
isModalVisible: !this.state.isModalVisible,
});
_renderItem = ({item}) => {
return (
<TouchableOpacity onPress={() => this._onPressItem(item.id)} key={item.id}>
<View>
{item._embedded['wp:featuredmedia'].filter(
element => element.id == item.featured_media
).map((subitem, index) => (
<View style={{
margin: '5%',
borderWidth: 1,
borderColor: '#d8d8d8',
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 5 },
shadowOpacity: 0.2,
shadowRadius: 8,
elevation: 1,
}}>
<ImageBackground
style={styles.news}
source={{ uri: subitem.media_details.sizes.medium.source_url }}
key={item.id}>
<View style={styles.itemTitle}>
<Text style={{ fontSize: 16, fontWeight: 'bold' }}>
{item.title.rendered}
</Text>
</View>
</ImageBackground>
</View>
))}
</View>
</TouchableOpacity>
)
};
_onPressItem(id) {
this.setState({
isModalVisible: true,
id: id,
});
};
render() {
if (this.state.isLoading == true) {
return (
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center', }}>
<ActivityIndicator size="large" color="#1C97F7" />
</View>
)
}
else {
Moment.locale('en');
return (
<View>
{this.state.posts.map((item, index) => (
<Modal isVisible={this.state.isModalVisible} id={this.state.id}>
{item._embedded['wp:featuredmedia'].filter(
element => element.id == item.featured_media
).map((subitem, index) => (
<ScrollView style={
{ flex: 1, backgroundColor: 'white', padding: 20, paddingBottom: 40,}
}>
<ImageBackground
style={styles.news}
source={{ uri: subitem.media_details.sizes.medium.source_url }}
key={item.id} />
<TouchableOpacity onPress={this._toggleModal}>
<Text>Hide me!</Text>
</TouchableOpacity>
<HTML
tagsStyles={{
body: {fontSize: 16, paddingBottom: 20,},
p: {fontSize: 16, fontWeight: "normal", marginTop: 10, marginBottom: 20},
strong: {fontSize: 20,},
blockquote: {fontSize: 20},
a: {fontSize: 16, color: "#0044e2"},
em: {fontSize: 20,},
img: {height: 250, width: 350},
}}
key={item.id}
styleName="paper md-gutter multiline"
html={item.content.rendered}
imagesMaxWidth={Dimensions.get('window').width * .9}
ignoredStyles={['width', 'height', 'video']}
/>
</ScrollView>
))}
</Modal>
))}
<FlatList
data={this.state.posts}
renderItem={this._renderItem}
keyExtractor={(item, index) => index}
/>
</View>
)
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingTop: 0,
},
h1: {
color: 'black',
fontSize: 24,
paddingTop: 20,
fontWeight: 'bold',
},
h2: {
color: 'black',
fontSize: 24,
paddingTop: 20,
fontWeight: 'bold',
},
h3: {
fontSize: 13,
},
button: {
width: '45%',
margin: 5,
backgroundColor: '#492661',
padding: 8,
height: 36,
borderRadius: 18,
},
buttonGrey: {
width: '45%',
margin: 5,
backgroundColor: '#353535',
padding: 8,
height: 36,
borderRadius: 18,
},
buttonText: {
color: 'black',
alignSelf: 'center',
},
highlight: {
backgroundColor: '#f5f5f5',
borderRadius: 50,
width: 100,
height: 100,
marginRight: 20,
alignItems: 'center',
justifyContent: 'center',
borderColor: 'gold',
borderWidth: 0,
},
news: {
backgroundColor: '#f5f5f5',
borderRadius: 10,
width: '100%',
height: 200,
overflow: 'hidden',
},
hero: {
backgroundColor: '#492661',
width: '110%',
height: 260,
alignSelf: 'center',
marginTop: 0,
overflow: 'hidden'
},
itemTitle: {
backgroundColor: 'rgba(255,255,255,0.9)',
paddingVertical: 10,
position: 'absolute',
bottom: 0,
right: 0,
width: '100%',
paddingHorizontal: 10,
},
});
In FlatList, this is the issue it can't re-render again if dataModel is being there. For this You can use this :
in FlatList there is a propsTypes: ExtraData={} in this you should add a new boolean state, and wherever you again add the data in flatlist . set the state for that boolean key , that would help you :
<FlatList
data={this.state.posts}
renderItem={this._renderItem}
keyExtractor={(item, index) => index}
extraData={this.state.extraData}
/>
where you want add flatList data again add this line:
this.setState({extraData:!this.state.extraData})
by this line render method run again , and you will find a new update records.
Use this, this help me.

react native alignself not working with position absolute

I am trying to create a small tooltip in react native. For the most part it works. But want to use alignself, to auto size the view that contains text. It works with position relative, but that pushes the content away. Position absolute puts all the text inside the tooltip below each other and the tooltip is very narrow.
I have seen some modules for react native tooltip, but those use actions, and I just need to use text.
Anybody an idea on how to get this working?
The is what I have:
constructor(props) {
super(props);
this.state = {
visible: false,
};
}
toggleStatus() {
this.setState({visible: true});
setTimeout(() => {
this.setState({visible: false});
}, 3000);
}
toolTip = () => {
return (
<View style={styles.containerMain}>
{renderIf(this.state.visible,
<View style={styles.tooltipWrapper}>
<Text style={styles.tooltipStyle}>{this.props.tooltipText}</Text>
</View>
)}
<View style={styles.questionMarkWrapper}>
<TouchableOpacity disabled={this.state.visible} onPress={()=>this.toggleStatus()}>
<Text style={styles.questionMark}>?</Text>
</TouchableOpacity>
</View>
</View>
)
}
render() {
return (
<View style={styles.containerStyle}>
{this.toolTip()}
</View>
)
}
And styling I use:
containerMain: {
alignItems: 'flex-end',
},
tooltipWrapper: {
position: 'absolute',
top: 0,
right: 10,
padding: 5,
borderRadius: 4,
backgroundColor: 'rgba(0,0,0,0.6)',
},
tooltipStyle: {
fontSize: 11,
color: 'white',
},
questionMarkWrapper: {
justifyContent: 'center',
flexDirection: 'row',
marginRight: 10,
},
questionMark: {
fontSize: 16,
color: 'rgba(255,255,255,0.4)',
borderRadius: 50,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.4)',
borderStyle: 'solid',
height: 26,
width: 26,
paddingLeft: 9,
paddingTop: 2,
}
This is how the tooltip should look like (not the actual location):
And this is how it looks like now: