I'm trying to style my renderItem in FlatList but elevation not working properly. Is there anything I'm wrong or this is a React Native issue?
I tested ListView too but it still not working properly
This is TodoItem component
import React, { Component } from 'react'
import { Text, View, StyleSheet } from 'react-native'
const styles = StyleSheet.create({
container: {
height: 60,
backgroundColor: 'white',
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 2, height: 2 },
shadowOpacity: 0.4,
shadowRadius: 2,
elevation: 3,
justifyContent: 'center',
paddingHorizontal: 30,
marginBottom: 12
},
text: {
fontSize: 18,
fontWeight: '400',
color: '#080808'
}
})
export default class TodoItem extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.text}> {this.props.text} </Text>
</View>
)
}
}
And this is where I call it in FlatList
<FlatList
data={this.props.items}
renderItem={(item) => <TodoItem key={item.index} text={item.item} />}
/>
The point is that elevation works properly if I don't use FlatList like this
<TodoItem text="Hello world" />
What I excepted
What I see
Most issues like this are caused by styling that is applied to your surrounding view or the row that you are trying to render.
If you add a marginHorizontal: 10 to the styles.container for the row that should probably do it for you.
Here is a simplified example where the edges of the row are not cut off. It has a couple of tweaks to make it work, using state.items instead of props.items and changing the style name for the TodoItem to itemContainer. It should give you an idea of how to implement it.
import * as React from 'react';
import { Text, View, StyleSheet, FlatList } from 'react-native';
import { Constants } from 'expo';
export default class App extends React.Component {
state = {
items: [
'Hello'
]
}
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.items}
renderItem={(item) => <TodoItem key={item.index} text={item.item} />}
/>
</View>
);
}
}
class TodoItem extends React.Component {
render() {
return (
<View style={styles.itemContainer}>
<Text style={styles.text}> {this.props.text} </Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight + 10,
backgroundColor: '#ecf0f1',
},
itemContainer: {
marginHorizontal: 10,
height: 60,
backgroundColor: 'white',
borderRadius: 10,
shadowColor: '#000',
shadowOffset: { width: 2, height: 2 },
shadowOpacity: 0.4,
shadowRadius: 2,
elevation: 3,
justifyContent: 'center',
paddingHorizontal: 30,
marginBottom: 12
},
text: {
fontSize: 18,
fontWeight: '400',
color: '#080808'
}
});
Here is a snack showing it working https://snack.expo.io/#andypandy/flatlist-with-elevation-on-rows
Related
I am using this package react-native-toast-notifications for my application. When toaster is display, I am blocked and I am not able to click anything in the length of the toaster.
How can I fix that?
That's my component:
import React from 'react';
import { Colors } from '#utils';
import { Text } from '#components';
import { ToastProvider } from 'react-native-toast-notifications';
import { View } from 'react-native';
interface IProps {
children: JSX.Element;
}
export const CustomToastProvider = ({ children }: IProps) => {
return (
<ToastProvider
placement="top"
duration={5000}
animationType="slide-in"
animationDuration={250}
textStyle={{ fontSize: 20 }}
offset={50}
offsetTop={30}
offsetBottom={40}
swipeEnabled={true}
renderType={{
custom: toast => (
<View
style={{
maxWidth: '95%',
paddingHorizontal: 15,
paddingVertical: 10,
backgroundColor: Colors.BlackLight,
marginVertical: 4,
marginRight: 40,
borderRadius: 8,
borderLeftColor: toast.data?.type === 'error' ? Colors.Red : Colors.GreenSuccess,
borderLeftWidth: 6,
justifyContent: 'center',
alignSelf: 'flex-end',
}}>
<Text
style={{
fontSize: 14,
color: Colors.White,
fontWeight: 'bold',
textAlign: 'left',
}}>
{toast.data.title}
</Text>
<Text style={{ color: Colors.White, marginTop: 2 }}>{toast.message}</Text>
</View>
),
}}>
{children}
</ToastProvider>
);
};
I wanted to add a Image Header Scroll View for my Project. I used the below code and which gives me the error
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined."
I tried everything i could but i didn't find a solution. Also I totally don't understand why this error is popping.
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
Image,
Dimensions,
StatusBar,
} from 'react-native';
import * as Animatable from 'react-native-animatable';
import {Header} from 'react-navigation-stack';
import HeaderImageScrollView, {
TriggeringView,
} from 'react-native-image-header-scroll-view';
const MIN_HEIGHT = Header.HEIGHT;
const MAX_HEIGHT = 250;
const styles = StyleSheet.create({
title: {
fontSize: 20,
},
section: {
padding: 20,
borderBottomWidth: 1,
borderBottomColor: '#cccccc',
backgroundColor: 'white',
},
sectionTitle: {
fontSize: 18,
fontWeight: 'bold',
},
titleContainer: {
flex: 1,
alignSelf: 'stretch',
justifyContent: 'center',
alignItems: 'center',
},
navTitleView: {
height: MIN_HEIGHT,
justifyContent: 'center',
alignItems: 'center',
paddingTop: 16,
opacity: 0,
},
navTitle: {
color: 'white',
fontSize: 18,
backgroundColor: 'transparent',
},
sectionLarge: {
height: 600,
},
});
class TvShow extends Component {
constructor() {
super();
this.state = {showNavTitle: false};
}
render() {
return (
<View style={{flex: 1}}>
<StatusBar barStyle="light-content" />
<HeaderImageScrollView
maxHeight={MAX_HEIGHT}
minHeight={MIN_HEIGHT}
maxOverlayOpacity={0.6}
minOverlayOpacity={0.3}
fadeOutForeground
renderHeader={() => (
<Text>Hiiii</Text>
)}
renderFixedForeground={() => (
<Animatable.View
style={styles.navTitleView}
ref={navTitleView => {
this.navTitleView = navTitleView;
}}>
<Text style={styles.navTitle}>
Hii
</Text>
</Animatable.View>
)}
renderForeground={() => (
<View style={styles.titleContainer}>
<Text>Hii</Text>
</View>
)}>
<TriggeringView
style={styles.section}
onHide={() => this.navTitleView.fadeInUp(200)}
onDisplay={() => this.navTitleView.fadeOut(100)}>
<Text style={styles.title}>
<Text>Hii</Text>, ( 1998)
</Text>
</TriggeringView>
<View style={styles.section}>
<Text style={styles.sectionTitle}>Overview</Text>
<Text>Hii</Text>
</View>
<View style={[styles.section, styles.sectionLarge]}>
</View>
</HeaderImageScrollView>
</View>
);
}
}
export default TvShow;
it's a library problem, use the version 0.10.3
"react-native-image-header-scroll-view": "0.10.3"
I am trying to create 6 customized button (3 buttons in each row) using TouchableOpacity. I was able to add the 3 buttons in the first row but when try to add the other three buttons in the next row, for some reason it pushes the the first row up. I want the gap/height between each rows to be at most 10px.
and my other question is, when I try to wrap the customized card with TouchableOpacity, it ignores the width I specify on the StyleSheet.
I am new to react native. So, if this is dumb question to ask, I apologize.
Here is the code I have,
//Card component
import React from "react";
import { StyleSheet, View, TouchableOpacity } from "react-native";
function Card(props) {
return (
<View style={{ ...styles.CardSytle, ...props.style }}>
{props.children}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
CardSytle: {
shadowColor: "black",
shadowOffset: { width: 0, height: 2 },
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 10,
backgroundColor: "white",
padding: 20,
borderRadius: 10,
marginHorizontal: 10,
marginVertical: 10,
},
});
export default Card;
//MainPage
import React from "react";
import { View, StyleSheet, Dimensions } from "react-native";
import Card from "../components/Card";
const MainPageScreen = (props) => {
return (
<View style={styles.body}>
<View style={styles.cardContainer}>
<Card style={styles.card} />
<Card style={styles.card} />
<Card style={styles.card} />
</View>
<View style={styles.cardContainer}>
<Card style={styles.card} />
<Card style={styles.card} />
<Card style={styles.card} />
</View>
</View>
);
};
const styles = StyleSheet.create({
body: {
flex: 1,
backgroundColor: "white",
},
cardContainer: {
flex: 1,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
},
card: {
width: Dimensions.get("window").width / 3,
maxWidth: "28%",
height: 150,
maxHeight: "28%",
},
});
export default MainPageScreen;
//Here is screenshot of the buttons
[1]: https://i.stack.imgur.com/9z84U.png
You are setting a maxHeight of 28% which is setting the button height to 28% of parent and creates a blank space under the row. So you should remove it.
card: {
width: Dimensions.get('window').width / 3,
maxWidth: '28%',
height: 150,
},
As for the touchable opacity, Rather than wrapping the view you can use it as the main wrapper and style it Like below.
function Card(props) {
return (
<TouchableOpacity style={[styles.CardSytle, props.style]}>
{props.children}
</TouchableOpacity>
);
}
I am new to react native and am struggling to round the corners to text elements, as you can see the corners are still sticking out of the rounded border, and the same happens when I wrap the text in a view element, I don't know how to fix this. Here is the code:
import React from 'react';
import { StyleSheet, Text, View, Button, Alert, Touchable, TouchableHighlight} from 'react-native';
import { render } from 'react-dom';
export default class App extends React.Component {
myButtonPressed(){
Alert.alert("Logout");
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={this.myButtonPressed}
>
<Text style={styles.text}> Login </Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontSize: 30,
backgroundColor: "#BB2CD9",
paddingVertical: 10,
paddingHorizontal: 40,
color: "#FFFFFF",
borderRadius: 10,
borderWidth: 2,
borderColor: "#FFFFFF"
}
});
What you can do is wrap the text inside view component and pass all neccessary styling to the view.
export default class App extends React.Component {
myButtonPressed(){
Alert.alert("Logout");
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={this.myButtonPressed}
>
<View style={styles.btnContainer}>
<Text style={styles.text}> Login </Text>
</View>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
btnContainer: {
backgroundColor: "#BB2CD9",
paddingVertical: 10,
paddingHorizontal: 40,
borderRadius: 10,
borderWidth: 2,
borderColor: "#FFFFFF"
},
text: {
fontSize: 30,
color: "#FFFFFF",
}
});
You can use TouchableOpacity for better experience. You don't need to define border n all with TouchableOpacity.
Try this - Live Demo
export default class App extends React.Component {
myButtonPressed(){
Alert.alert("Logout");
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
onPress={this.myButtonPressed}
style={styles.hLight}
>
<Text style={styles.text}> Login </Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
hLight: {
fontSize: 30,
backgroundColor: "#BB2CD9",
paddingVertical: 10,
paddingHorizontal: 40,
borderRadius: 10,
borderWidth: 2,
borderColor: "#FFFFFF"
},
text: {
fontSize:20,
color:'white'
}
});
Using TouchableHighlight - Live
export default class App extends React.Component {
myButtonPressed(){
Alert.alert("Logout");
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={this.myButtonPressed}
style={styles.hLight}
>
<Text style={styles.text}> Login </Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
hLight: {
fontSize: 30,
backgroundColor: "#BB2CD9",
paddingVertical: 10,
paddingHorizontal: 40,
borderRadius: 10,
borderWidth: 2,
borderColor: "#FFFFFF"
},
text: {
fontSize:20,
color:'white'
}
});
I am using a custom component with image and text. The image is relative to the text. Please see the screenshot.
image 1
image 2.
I have used the TouchableOpacity component as root view for that.
In screenshots when long press on the component, two views are overlapping with shadow. It looks ugly when long press.
Please see the code below for reusable component.
'use strict';
import React, {Component} from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
} from 'react-native';
export default class ExampleButton extends Component {
constructor (props) {
super (props);
}
_handleOnPress = () => {
console.log('pressed!!!');
};
render () {
console.log (this.props);
return (
<TouchableOpacity
onPress={this.handleOnPress}
>
<View style={styles.btnCompContainer}>
<View
style={{
backgroundColor: '#FFF',
justifyContent: 'center',
borderRadius: 30,
height: 50,
width: '100%',
}}
>
<Text style={styles.btnTxt}>{this.props.buttonText}</Text>
</View>
<View style={[styles.btnElmContainer]}>
<Image
style={[{height: 30, width: 30,resizeMode:'stretch'}]}
source={this.props.image}
/>
</View>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create ({
btnCompContainer: {
flexDirection: 'row',
alignItems: 'center',
height: 60,
marginLeft: 10,
marginRight: 20,
},
btnElmContainer: {
position: 'absolute',
justifyContent: 'center',
alignItems: 'center',
width: 60,
height: 60,
backgroundColor:'#fff',
borderRadius: 30,
shadowColor: '#000000',
shadowOffset: {
width: 1,
height: 1,
},
elevation:5,
shadowRadius: 2,
shadowOpacity: 0.3,
},
btnTxt: {
marginLeft: 80,
color: '#9e9e9e',
fontSize: 16,
fontWeight: 'bold',
textAlign: 'left',
},
});
Here I am using this reusable component in code.
'use strict';
import React, {Component} from 'react';
import {
Animated,
StyleSheet,
Text,
TextInput,
View,
Image,
ImageBackground,
TouchableOpacity,
Button,
StatusBar,
Easing
} from 'react-native';
// Custom Components
const searchBGImg = require('../assets/search-bg-kit.png');
const houseLogo = require('../Resources/house.png');
import ExampleButton from './components/common/example-button';
export default class TypeSelect extends Component<Props> {
// Navigation Option
static navigationOptions = {
header: null
}
constructor() {
super();
this.state = {
visible: false,
x: new Animated.Value(-100),
};
}
slide = () => {
Animated.spring(this.state.x, {
toValue: 0,
easing: Easing.easeOutBack
}).start();
this.setState({
visible: true,
});
};
gotoSearch = () =>{
this.props.navigation.navigate('DocSearch')
}
componentDidMount(){
this.slide();
}
render() {
return (
<View style={styles.container}>
<ImageBackground source={searchBGImg} style={styles.imgBG}>
<View style={{alignItems:'center', marginBottom:20}}>
<Image style={{height:57, width:69, marginBottom:12}} source={houseLogo} />
</View>
<View>
<Animated.View
style={[styles.slideView, {
transform: [
{
translateX: this.state.x
}
]
}]}>
<ExampleButton image={houseLogo} buttonText={'Click here'} />
<ExampleButton image={houseLogo} buttonText={'Click here'} />
</Animated.View>
</View>
</ImageBackground>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
imgBG:{
flex: 1,
flexDirection: "column",
justifyContent:"center",
width: "100%",
height: "100%"
}
})
It is working fine in iOS, but it's not working in android up to the mark. Please help me to work it in android.
Thanks in advance.
You should use renderToHardwareTextureAndroid prop on <View /> component.
In your example like this:
<View style={styles.btnCompContainer} renderToHardwareTextureAndroid >
<View
style={{
backgroundColor: '#FFF',
justifyContent: 'center',
borderRadius: 30,
height: 50,
width: '100%',
}}
>
<Text style={styles.btnTxt}>{this.props.buttonText}</Text>
</View>
<View style={[styles.btnElmContainer]}>
<Image
style={[{height: 30, width: 30,resizeMode:'stretch'}]}
source={this.props.image}
/>
</View>
</View>