Custom pagination with ScrollView in React Native - javascript

In my app i'm using ScrollView for showing images. Below my ScrollViewcomponent i have two buttons like prev and next. I want to add custom pagination with the buttons. Also my images are coming from an array in a loop. I want 4 images to show at a time. So, the next button should show next 4 images if there are any and prev button should take 4 previous images if there are any. My ScrollView is currently like this:
<View>
<View style={{width:width,paddingHorizontal:10,paddingVertical:20}}>
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false} >
{list.map((item, i)=>(
<Image key={i} source={{uri: item}}
style={{width: 80, height: 80,marginLeft:5}} />
)
)}
</ScrollView>
</View>
</View>
Below this i have two buttons.I have created two different fuctions for those. Here's what it's like now:
<View>
<Button
title="Prev"
color="#841584"
onPress={handleClickBackward}
/>
</View>
<View>
<Button
title="Next"
color="#841584"
onPress={handleClickForward}
/>
</View>
How can i manipulate with my list array so that the custom pagination works. I have tried array slice method on next but it removes the first images and i don't find those after pressing prev button.

you can use onNextPress function and add ref in scrolview
const scrollRef = useRef<ScrollView>();
const onNextPress = () => {
scrollRef.current?.scrollTo({
y : 0,//you must increase x or y
animated : true
});
}
return (
<View style={{width:width,paddingHorizontal:10,paddingVertical:20}}>
<ScrollView
ref={scrollRef}//ref
horizontal={true}
showsHorizontalScrollIndicator={false} >
{list.map((item, i)=>(
<Image key={i} source={{uri: item}}
style={{width: 80, height: 80,marginLeft:5}} />
)
)}
</ScrollView>
</View>
);

Related

How to create a carousel like this?

I want to create a carousel like the one shown below. The center item will have a higher elevation to indicate that this is the current item and whenever the user scrolls, the next item will be elevated and so on. The center item will be overlapping the left and the right item. I tried to use react-native-snap-carousel with the stack option, but that only shows the left item and in case of ios, only the right item. I tried tinder, but that is quite same as well. I tried default, but there are gaps in between each item which I do not want. I tried react-native-anchor-carousel. But, this makes the center item transparent for some reason.
<Carousel
style={styles.carousel}
data={review}
renderItem={renderitem}
itemWidth={240}
activeSlideAlignment="center"
sliderWidth={windowWidth - 20}
separatorWidth={-100}
itemContainerStyle={{
alignItem: 'center',
marginTop: 18,
}}
inActiveOpacity={0.1}
ref={carouselRef}
loop={true}
/>
Render Item is below
const renderitem = ({item}) => {
return (
<View
style={[styles.item]}
onPress={() => {
this._carousel.scrollToIndex(index);
}}>
<View style={styles.circle}>
<Image
style={styles.image}
source={{uri: item.serviceImage}}
resizeMode="cover"
/>
</View>
<Text style={styles.serviceNameText}>{item.serviceName}</Text>
<Text style={styles.name}>{item.reviewerName}</Text>
<Text style={styles.content}>{item.content}</Text>
</View>
);
};

How to get current slide position or number in react-native flatlist

Hy, I'm creating a slider in react-native. It works perfectly. It having three slides on scrolling. I done this using Animated.FlatList and scrollX. But One thing I'm not getting is how I can know which slide is currently displaying. I want to because it onboard screen I want to display the skip button on the first two slides and on the third I want to display something else button how I can do that.
const OnBoardScreen = () => {
const scrollX = useRef(new Animated.Value(0)).current;
// flatlist render function
const renderSplash = ({ item, index }) => {
return (
<View style={styles.mainWrapper}>
<View style={styles.imageWrapper}>{item.image}</View>
<View style={[styles.titleWrapper,
{marginTop:index==1 ? hp(4):index == 2 ? hp(10):null}
]}>
<Text style={styles.titleText}>{item.title}</Text>
</View>
<View style={styles.bodyWrapper}>
<Text style={styles.bodyText}>{item.body}</Text>
</View>
</View>
);
};
return (
<View style={styles.container}>
{/* background Svgs */}
<View style={styles.blueSvgWrapper}>
<BlueSvg />
</View>
<View style={styles.dotSvgWrapper}>
<DotsSvg />
</View>
<View style={styles.orangeSvgWrapper}>
<OrangeSvg />
</View>
{/* Main Content */}
<Animated.FlatList
data={onBoardData}
keyExtractor={(item, index) => item.key}
renderItem={renderSplash}
horizontal
scrollEventThrottle={32}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { x: scrollX } } }],
{ useNativeDriver: false }
)}
pagingEnabled
showsHorizontalScrollIndicator={false}
/>
<Indicator scrollX={scrollX} />
{skip == false ?
<TouchableOpacity style={styles.skipWrapper} >
<Text style={styles.skipText} >Skip</Text>
</TouchableOpacity>
: null }
</View>
);
};
I try to do conditions on scrollX but it's not updating the value like states do.
My Issue:
How to know apply condition on slides which thing should be show or which not?
FlatList inherits all of ScrollView props.
Therefore you can use onScroll.
onScroll = (event) => {
const scrollOffset = event.nativeEvent.contentOffset.y
}

React Native Touchable Opacity

I have this code, in which TouchableOpacity is not working and i don't know why:
const Box = (props) => {
return (
<View>
<TouchableOpacity onPress={() => {props.callBackProp(); props.budCallBackProp(props.name)}}>
<View style={styles.inputBox}>
<Text style={styles.testText}>{props.name}</Text>
</View>
</TouchableOpacity>
</View>
);
}
What is wrong here?
Edit:
At first, i click on this blue button with "budynek" text inside it, which opens something that looks like a list. Then after i click on some option i want it to dissapear, which is what these callbacks are for. I wrapped each option in this TouchableOpacity component but nothing happens after i click it - there is no effect of a click. A view which holds these "Box" component is absolutely positioned. Here is rest of the code:
return (
<View style={styles.rozwijanaPoz}>
<Pusty/>
<Box name={"budynek 1"} callBackProp={props.callBack} budCallBackProp={props.budCallBack}/>
<Box name={"budynek 2"} callBackProp={props.callBack} budCallBackProp={props.budCallBack}/>
<Box name={"budynek 3"} callBackProp={props.callBack} budCallBackProp={props.budCallBack}/>
</View>
);
}
const styles = StyleSheet.create({
rozwijanaPoz: {
position: "absolute",
left: 60,
},
});
And the main container:
<TouchableOpacity onPress={() => setIsVisible(true)}>
<View style={styles.budynekContainer}>
<Text style={styles.budynekTekst}>{budynekText}</Text>
{isVisible ?
<Rozwijana callBack={visibleCallBack} budCallBack={budynekCallBack}/>
: null}
</View>
</TouchableOpacity>

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'search'

The search is perfect and it's all looks fine, but gets this warning.
I get this warning when I press any key to start the search method.
"Song_ID", "Song_Name" and "Image" are of the variable names from the SQL Database.
- I looked on other question as this, but it didn't help me at all.
This is the code where the error is :
return (
<View>
<ScrollView>
{musicList.map(songObj => {
return (
<View style={styles.resultsContainer}> /// Its written that the erorr in this line
<TouchableOpacity onPress={this.GetListViewItem.bind(this, songObj.Song_Name)}>
<Text style={{ fontSize: 16 }} key={songObj.Song_ID}>
{songObj.Song_Name}</Text>
<Image source={{ uri: songObj.Image }} style={styles.img} />
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
}
I don't understand where to put the key and/or what does it mean, I tried so many times but it didn't went well.
If more details is needed please tell me and I'll insert the right code.
You should add the key onto the outermost component inside the map. In your case, this is the View. Try this:
return (
<View>
<ScrollView>
{musicList.map(songObj => {
return (
<View style={styles.resultsContainer} key={songObj.Song_ID}>
<TouchableOpacity onPress={this.GetListViewItem.bind(this, songObj.Song_Name)}>
<Text style={{ fontSize: 16 }}>
{songObj.Song_Name}</Text>
<Image source={{ uri: songObj.Image }} style={styles.img} />
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
}
Adding the key prop lets react optimize rendering which is why it recommends you add it. Read the docs for more info.

Use same onPress handle with multiple TouchableOpacity

I am using a GridView to show multiple products and on click i want to go to details screen , however I am unable to find a way to identify which product grid view cell was selected / tapped by user , I think sending some parameter to handle method should do the trick.
return (
<GridView
itemDimension={130}
items={this.state.dataSource}
style={styles.gridView}
renderItem={item => (
<View style={styles.itemContainer}>
<TouchableOpacity onPress={ this.onPressStone } style={styles.itemContainer}>
<Image source = {{uri:item.url}} style={styles.imageView} />
<Text style={styles.itemName}>{item.name}</Text>
</TouchableOpacity>
</View>
)}
/>
);
You can send parameters to your function like you said.
Example
onPress={ () => this.onPressStone(item.id) }
You can pass to the method onPressStone the item and depending the item you could do that print what you want. And if you want to know who was pressed you just have to make a log with the name of the item or take the index for example
return (
<GridView
itemDimension={130}
items={this.state.dataSource}
style={styles.gridView}
renderItem={(item, index) => {
//to know who was pressed:
console.log('pressedItemName-->', item.name);
//to know index pressed:
console.log('pressedItemName-->', item);
return (
<View style={styles.itemContainer}>
<TouchableOpacity onPress={ ()=> {this.onPressStone(item)} } style={styles.itemContainer}>
<Image source = {{uri:item.url}} style={styles.imageView} />
<Text style={styles.itemName}>{item.name}</Text>
</TouchableOpacity>
</View>
)}
/>
);

Categories

Resources