I am learning carousel in react native for the first time. I am experiencing error " width must be specified for horizontal carousels. "
import React from "react";
import styled from "styled-components/native";
import Carousel from "react-native-reanimated-carousel";
import { View, Text, StyleSheet, Image, Dimensions } from "react-native";
class CourseScreen extends React.Component
{
_renderItem = ({ item, index }) =>
{
return (
<View>
<Image
source={{ uri: item.image }}
style={{ width: "100%", height: 350 }}
/>
</View>
);
};
render() {
return (
<Container>
<Carousel
ref={(c) => {
this._carousel = c;
}}
data={MovieCardData}
renderItem={this._renderItem}
sliderWidth={Dimensions.get("screen").width}
itemWidth={Dimensions.get("screen").width / 3}
/>
</Container>
);
}
}
export default CourseScreen;
const Container = styled.View`
flex: 1;
justify-content: center;
align-items: center;
`;
const MovieCardData = [
{
image:
"https://www.animenewsnetwork.com/images/encyc/A4313-23.jpg",
title: "Sample Picture 1",
},
{
image:
"https://www.animenewsnetwork.com/images/encyc/A4313-23.jpg",
title: "Sample Picture 2",
},
{
image:
"https://m.media-amazon.com/images/M/MV5BMWNhMzc2MzMtYzliMS00MTVkLTgwNTgtMTZjMzc5ZDNlNDY1XkEyXkFqcGdeQXVyMjc2Nzg5OTQ#._V1_FMjpg_UX1000_.jpg",
title: "Sample Picture 3",
},
{
image: "https://www.animenewsnetwork.com/images/encyc/A4313-23.jpg",
title: "Sample Picture 4",
},
];
need to add width, thats all
const width = Dimensions.get('window').width;
return (
...
<Carousel
ref={(c) => {
this._carousel = c;
}}
width={width}
data={MovieCardData}
renderItem={this._renderItem}
sliderWidth={Dimensions.get("screen").width}
itemWidth={Dimensions.get("screen").width / 3}
/>
...
Related
I am new to ReactNative programming and .tsx files in general. I'm trying to display a basic FlatList and have copied the below code from the ReactNative docs here: (https://reactnative.dev/docs/flatlist). It's only slightly modified to fit into my ReactNative app which I am editing in Visual Studio code.
Does anyone know the correct way to display a FlatList? I've spent 2-3 days tinkering with this but I'm obviously missing some crucial ingredient. Beats me.
import * as React from "react";
import { useState, Component } from "react";
import EditScreenInfo from "../components/EditScreenInfo";
import { StyleSheet, Text, View, Dimensions, TouchableOpacity, Alert, FlatList, SafeAreaView, StatusBar } from "react-native";
// import PaymentScreen from "./PaymentScreen";
import { Driver } from "../models/Driver";
// tslint:disable-next-line:typedef
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#FFF"
},
container: {
height: 750,
width: 750,
backgroundColor: "tomato"
},
map: {
flex: 1,
height:750,
width:750
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
title: {
fontSize: 18
}
});
// tslint:disable-next-line: typedef
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
title: "First Item",
},
{
id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",
title: "Second Item",
},
{
id: "58694a0f-3da1-471f-bd96-145571e29d72",
title: "Third Item",
},
];
// tslint:disable-next-line:typedef
const Item = ({ item, onPress, backgroundColor, textColor }: {
item: any;
onPress: any;
backgroundColor: any;
textColor: any;
}) => (
<TouchableOpacity onPress={onPress} style={[styles.item, backgroundColor]}>
<Text style={[styles.title, textColor]}>{item.title}</Text>
</TouchableOpacity>
);
export default class TabFourScreen extends Component {
drivers: Driver[] = []; // fetch these from backend... for now you can STUB
selectedId: any = useState(null);
setSelectedId: any = useState(null);
renderItem: any = ({ item }: {item: any}) => {
// tslint:disable-next-line:typedef
const backgroundColor = item.id === this.selectedId ? "#6e3b6e" : "#f9c2ff";
// tslint:disable-next-line:typedef
const color = item.id === this.selectedId ? "white" : "black";
return (
<Item
item={item}
onPress={() => this.setSelectedId(item.id)}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
}
render = () => {
return (
<View style={styles.page}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
extraData={this.selectedId}
/>
</SafeAreaView>
</View>
);
}
}
First of all you can't use hooks like useState in a Class Component, you have to use Function Component: https://reactnative.dev/docs/getting-started#function-components-and-class-components.
Secondly, you have set width: 750 to your SafeAreaView's style, so the text doesn't appear on the screen you see but appears before.
Try this code:
import * as React from 'react';
import { useState, Component } from 'react';
import {
StyleSheet, Text, View, Dimensions, TouchableOpacity, Alert, FlatList, SafeAreaView, StatusBar,
} from 'react-native';
// import PaymentScreen from "./PaymentScreen";
// tslint:disable-next-line:typedef
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFF',
},
container: {
height: 750,
width: '100%',
backgroundColor: 'tomato',
},
map: {
flex: 1,
height: 750,
width: 750,
},
item: {
height: 44,
},
title: {
fontSize: 25,
color: 'white',
},
});
// tslint:disable-next-line: typedef
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
// tslint:disable-next-line:typedef
const Item = ({
item, onPress, backgroundColor, textColor,
}) => (
<TouchableOpacity onPress={onPress} style={[styles.item, backgroundColor]}>
<Text style={[styles.title, textColor]}>{item.title}</Text>
</TouchableOpacity>
);
const TabFourScreen = () => {
const [selectedId, setSelectedId] = useState(null);
const renderItem = ({ item }) => {
// tslint:disable-next-line:typedef
const backgroundColor = item.id === selectedId ? '#6e3b6e' : '#f9c2ff';
// tslint:disable-next-line:typedef
const color = item.id === selectedId ? 'white' : 'black';
return (
<Item
item={item}
key={item.id}
onPress={() => setSelectedId(item.id)}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
};
return (
<View style={styles.page}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
/>
</SafeAreaView>
</View>
);
};
export default TabFourScreen;
I removed typescript just to test, feel free to add it again.
don't use this.renderItem use only renderItem
Hi I just want to make simple starter game. Rock paper scissors. This code is all I do.
I just want to animate the image and the text on every buttonpress.
Image is animating once, when press the button stops animating.
How can I show the image with animation every button press
I'm using the react-native-animatable library from npm.Also you can suggest me another
import React from 'react';
import { View, Text, TouchableOpacity, Image } from 'react-native';
import { TextAnimationSlideUp, TextAnimationDeZoom } from 'react-native-text-effects';
import * as Animatable from 'react-native-animatable';
import { Colors } from './constants';
var arr = [{ image: require('./assets/rock.png') }, { image: require('./assets/paper.png') }, { image: require('./assets/scissors.png') }];
var arr2 = [{ image: require('./assets/rock2.png') }, { image: require('./assets/paper2.png') }, { image: require('./assets/scissors2.png') }];
var win_case = [['rock', 'scissor'], ['scissor', 'paper'], ['paper', 'rock']];
var SELECTIONS = [
{
name: 'rock',
beats: 'scissors',
rank: 0
},
{
name: 'paper',
beats: 'rock',
rank: 1
},
{
name: 'scissors',
beats: 'paper',
rank: 2
}
]
function isWinner(selection, opponentSelection) {
return selection.beats === opponentSelection.name
}
function randomSelection() {
const randomIndex = Math.floor(Math.random() * SELECTIONS.length)
return SELECTIONS[randomIndex]
}
export default class App extends React.Component {
state = {
selected_uri: './assets/rock.png',
uri: require('./assets/rock.png'),
player1choose: 0,
player2choose: 0,
player1message: "-",
player2message: "-",
};
render() {
return (
<View>
<View >
<TouchableOpacity
onPress={() => {
const player1choice = randomSelection();
const player2choice = randomSelection();
const player1win = isWinner(player1choice, player2choice);
const player2win = isWinner(player2choice, player1choice);
if (player1win) { this.setState({ player1message: "Win", player2message: "Lose" });}
else if (player2win) {this.setState({ player1message: "Lose", player2message: "Win" });}
else {this.setState({ player1message: "Draw", player2message: "Draw" });}
this.setState({ player1choose: player1choice.rank, player2choose: player2choice.rank })
}}>
<View >
<Image source={require('./assets/playicon.png')} />
</View>
<View >
<Text>{this.state.player1message} </Text>
</View>
</TouchableOpacity>
</View>
<TextAnimationSlideUp value={this.state.player2message} delay={100} duration={1000} style={{ transform: [{ rotateX: "180deg" }, { rotateY: '180deg' }], color: 'purple', fontSize: 40 }} />
<TextAnimationSlideUp value={this.state.player1message} delay={100} duration={1000} style={{ color: 'yellow', fontSize: 40 }} />
<Animatable.Text animation="zoomInUp">
<Text>{this.state.player1message} </Text>
</Animatable.Text>
<View >
<Animatable.Image source={arr[this.state.player1choose].image} animation="zoomInUp">
</Animatable.Image>
</View>
</View>
); }}
Can anybody help me with this
How to dispaly 2 items for one pagination(first dot) and if we swipe then next 2 items should display with showing second dot active.
And if it is odd then last item should display my own component in react native snap carousel.
I would suggest that you go ahead and make the item you're rendering in the Carousel one that renders 2 things at once. The Carousel will paginate on whatever you pass to it, so if you're passing something with 2 items in it, it'll paginate on that, so for example:
<Carousel
layout="default"
data={arr}
renderItem={
({ item, index }) => (
<View style={styles.imageWrapper}>
<Image
style={styles.image}
source={item[0]}
resizeMode="cover"
accessibilityLabel="thumbnail"
/>
<Image
style={styles.image}
source={item[1]}
resizeMode="cover"
accessibilityLabel="thumbnail"
/>
</View>
)
}
lockScrollWhileSnapping={true} // Prevent the user from swiping again while the carousel is snapping to a position.
sliderWidth={screenWidth}
sliderHeight={screenWidth * 0.5}
itemWidth={screenWidth - 40}
activeSlideOffset={50}
enableSnap
onSnapToItem={onSnapToItem}
removeClippedSubviews={false}
firstItem={0}
contentContainerCustomStyle={styles.style}
/>
Create a function that split "entries" array into smaller arrays based on the size that you want
var slides = [];
const entriesSplitter = () => {
let size = 2; //Based on the size you want
while (entries.length > 0) {
slides.push(entries.splice(0, size));
}
};
then pass the slides array to <Carousel data={slides}/> then render each slide
in _renderItem
consider the following example:-
import React, { useState, useRef } from "react";
import { View,Text, Dimensions } from "react-native";
import Carousel, { Pagination } from "react-native-snap-carousel";
const { width: screenWidth, height: screenHeight } = Dimensions.get("window");
const myCarousel = () => {
const [activeSlide, setActiveSlide] = useState(0);
const carousel = useRef();
const entries = [
{
title: "Adidas"
},
{
title: "Nike"
},
{
title: "Puma"
},
{
title: "Reebok"
}
];
var slides = [];
const entriesSplitter = () => {
let size = 2; //Based on the size you want
while (entries.length > 0) {
slides.push(entries.splice(0, size));
}
};
// render every single slide
const _renderItem = ({ item,index }) => {
return (
<View style={{ flexDirection: "row", flexWrap: "wrap" }}>
{item.map(item => {
return <Text key={index}>{item.title}</Text>;
})}
</View>
);
};
return (
<View>
{entriesSplitter()}
<Carousel
ref={carousel}
data={slides}
renderItem={_renderItem}
onSnapToItem={index => setActiveSlide(index)}
sliderWidth={screenWidth}
sliderHeight={screenHeight}
itemWidth={screenWidth}
/>
<Pagination
dotsLength={2} // also based on number of sildes you want
activeDotIndex={activeSlide}
containerStyle={{ backgroundColor: "red", borderWidth: 2 }}
dotStyle={{
width: 10,
height: 10,
borderRadius: 5,
marginHorizontal: 8,
backgroundColor: "black"
}}
inactiveDotStyle={{
backgroundColor: "pink"
}}
inactiveDotOpacity={0.4}
inactiveDotScale={0.6}
/>
</View>
);
};
export default myCarousel;
This is how I implemented to show 3 carousels. We can customize it in many ways
import React from "react";
import { View, Dimensions, StyleSheet, Image } from "react-native";
import Carousel from "react-native-snap-carousel";
const windowWidth = Dimensions.get("window").width;
export default function MyCarousel() {
const images = [
{ id: 1, image: require("../assets/home-slider-1.jpg") },
{ id: 2, image: require("../assets/home-slider-2.jpg") },
{ id: 3, image: require("../assets/home-slider-3.jpg") },
{ id: 4, image: require("../assets/home-slider-4.jpg") }
];
// const imagesUri = [
// { id: 1, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } },
// { id: 2, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } },
// { id: 3, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } },
// { id: 4, image: { uri: 'https://i.imgur.com/gG5Egof.jpg' } }
// ];
const _renderItem = ({ item }) => {
return (
<View style={styles.slide}>
<Image
source={item.image}
style={styles.image}
// resizeMode="center"
></Image>
</View>
);
};
return (
<View style={styles.wrapper}>
<Carousel
data={images}
renderItem={_renderItem}
sliderWidth={windowWidth}
itemWidth={windowWidth - 70}
enableMomentum={false}
lockScrollWhileSnapping
autoplay
useScrollView
loop
autoplayInterval={3000}
/>
</View>
);
}
const styles = StyleSheet.create({
wrapper: {
height: 150
},
slide: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff"
},
image: {
flex: 1,
height: "100%",
width: "100%",
alignItems: "center",
justifyContent: "center"
}
});
I am trying to display a simple .jpg image by sending the Image path as a prop to the component which is supposed to render it. In the below way.
App.js
import React, { Component } from 'react';
import { View, Text, Image } from 'react-native';
import Header from './components/Header';
import ImageSlider from './components/ImageSlider';
import ImageShow from './components/ImageShow';
class App extends Component {
render () {
return (
<View style={{flex:1}}>
<Header headerText = "HONEST REVIEWS" />
<ImageSlider />
<ImageShow imagePath = "./abc.jpg"/>
<ImageShow imagePath = "./abc.png" />
</View>
);
}
}
export default App;
ImageShow.js
import React from 'react';
import { View, Image, Dimensions } from 'react-native';
const widthOfScreen = Dimensions.get('window').width;
const ImageShow = (imageProps) => {
return (
<View>
<Image style = { {width: 50, height: 50} } source = { {uri: imageProps.imagePath} } />
</View>
);
};
const styles = {
ImageStyle : {
height: 30,
width: widthOfScreen
}
}
export default ImageShow;
ImageSlider.js
import React from 'react';
import Carousel from 'react-native-banner-carousel';
import { StyleSheet, Image, View, Dimensions } from 'react-native';
const BannerWidth = Dimensions.get('window').width;
const BannerHeight = 250;
const images = [
require('./abc.jpg'),
require('./abc.jpg'),
require('./abc.jpg')
];
export default class ImageSlider extends React.Component {
renderPage(image, index) {
return (
<View key={index}>
<Image style={styles.imagesInSlider} source = { image } />
</View>
);
}
render() {
return (
<View style={styles.container}>
<Carousel
autoplay
autoplayTimeout={2000}
loop
index={0}
pageSize={BannerWidth}
>
{images.map((image, index) => this.renderPage(image, index))}
</Carousel>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'flex-start',
alignItems: 'center'
},
imagesInSlider: {
width: BannerWidth,
height: 250,
resizeMode: 'stretch',
}
});
My folder structure is :
ProjectName
------src
--------components
-----------ImageShow.js
-----------ImageSlider.js
-----------Header.js
-----------abc.jpg
--------App.js
Ideally the Image should be displayed when I am passing the locally stored Image path, but I am not getting any Image displayed but a Warning message which says:
"failed prop type: invalid prop 'source' supplied to 'ForwardRef(image)'"
This code work for me to get the image
import image1 from '../assets/images/abc.png'
import image2 from '../assets/images/abc.png'
const images = [
{
name: image1
},
{
name: image2
}]
const RenderPage = ({ image }) => {
return (
<Image resizeMode="contain" style={{ width: 50, height: 100, marginBottom: 5 }} source={image} />
)
}
class myclass extends Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
{images.map((image, index) =>
<RenderPage key={index} image={image.name} />
)}
</View>
)
}
}
Here the screenshot:
I have installed react-native-snap-carousel and I am using it's tinder effect.
I have added 6 slides as a carousel data. It is perfectly fine for top 3 slides after that it's touch work only slide top right corner.
I find many other library of carousel but I need to remove card in 1 direction and add the same card in reverse direction in the card stack.
Here is my code: Please help me and here is video which i can achieved by it.
https://www.dropbox.com/s/50t76ordotsuvrf/Animation.mov?dl=0
import React, { Component } from 'react';
import {
View, Text, StyleSheet, TextInput, TouchableOpacity, Image,
Platform, Dimensions,
ImageBackground
} from 'react-native';
import styled from "styled-components/native"; // Version can be specified in package.json
import Carousel from 'react-native-snap-carousel';
// here is my data array
init() {
this.state = {
videos: [
{
id: "WpIAc9by5iU",
thumbnail: require('../../img/whitecard.png'),
title: "a",
slideNumber: "1"
}, {
id: "sNPnbI1arSE",
thumbnail: require('../../img/whitecard.png'),
title: "the",
slideNumber: "2"
}, {
id: "VOgFZfRVaww",
thumbnail: require('../../img/whitecard.png'),
title: "come",
slideNumber: "3"
},
{
id: "VOgFZfRVawp",
thumbnail: require('../../img/whitecard.png'),
title: "on",
slideNumber: "4"
},
{
id: "VOgFZfRVawq",
thumbnail: `require('./whitecard.png')`,
title: "see",
slideNumber: "5"
},
{
id: "VOgFZfRVaw3",
thumbnail: require('../../img/whitecard.png'),
title: "go",
slideNumber: "6"
},
],
};
}
Here I am rendering each item
_renderItem = ({item, index}) => {
return (
<View style={styles.card}>
<View activeOpacity={1} onPress={() => {
console.log("clicked to index", index)
this._carousel.snapToItem(index);
}}>
<CurrentVideoImage source={item.thumbnail} resizeMode={'cover'}>
<View>
<TouchableOpacity
style={[styles.container,{marginTop:20}]}
onPress={() => this.setState({isView:!this.state.isView})}>
<Image source={require('../../../arrownext.png')} style={stylesButton.imageCamera}/>
</TouchableOpacity>
<Text
style={styles.label}>{item.title}</Text>
</View>
</CurrentVideoImage>
</View>
{/*<NextVideoImage source={{ uri: this.state.currentVideo.nextVideoId }}/>*/}
</View>
);
}
Now it is my carousel code.
return(
<CarouselBackgroundView style={styles.content}>
<Carousel
ref={(c) => {
this._carousel = c;
}}
data={this.state.videos}
renderItem={this._renderItem.bind(this)}
onSnapToItem={this.handleSnapToItem.bind(this)}
sliderWidth={width}
itemWidth={290} //256
containerCustomStyle={{ overflow: 'visible' }}
contentContainerCustomStyle={{ overflow: 'visible' }}
layout={'tinder'}
firstItem={0}
layoutCardOffset={16} //For showing card deck height.
/>
</CarouselBackgroundView>
);
Here my view css
const CurrentVideoImage = styled.ImageBackground`
width: 290;
height: 500;
border-radius: 20;
`;
const CarouselBackgroundView = styled.View`
transform: rotate(180deg);
flex-direction: column;
justifyContent: center;
alignItems: center;
height: 100%;
width: 100%;
`;
You can set prop removeClippedSubviews to false on the Carousel component to solve this. Note that you'll then lose all FlatList optimizations - which shouldn't be a problem if you don't try to render a huge dataset.
More information about the issue can be found in this thread: https://github.com/archriss/react-native-snap-carousel/issues/262