@42px/react-native-image-swiper 中文文档教程
react-native-image-swiper
bi-directional swiper for ReactNative
Features
- Android/iOS support
- zoom image
- correct behavior when adding new images
Why does the world need another swiper?
如果你在 ReactNative 上使用/编写了一些 swiper,你一定很痛苦。 当您开始将项目动态添加到列表的开头时,大问题就开始了。 发生这种情况是因为 maintainVisibleContentPosition
prop 在 Android 上的 ScrollView (Flatlist) 中不受支持(仅支持 iOS)。 并且 ScrollView 在添加新项目时的默认行为是移动到开头。 这会导致糟糕的用户体验。
这种情况android的标准解决方案是使用RecyclerView
。 这正是我们通过为 Android 实现本机刷卡模块所做的(iOS 实现基于 Flatlist)。
Is it customizable?
一点点。 我们只添加了一些基本道具,因为我们需要为我们自己的项目提供快速解决方案。 但它有效! 如果您需要一个在添加新图像时不会中断的简单图像滑动器,那么这就是您的最佳选择。
也许我们将来会自定义这个组件。
Installation
npm install @42px/react-native-image-swiper
Usage
import React from 'react'
import { Button, StyleSheet, View } from 'react-native'
import { Colors } from 'react-native/Libraries/NewAppScreen'
import { RnImageSwiper } from '@42px/react-native-image-swiper'
const sampleImages = [
'https://hatrabbits.com/wp-content/uploads/2017/01/random.jpg',
'https://cdn02.nintendo-europe.com/media/images/06_screenshots/games_5/nintendo_switch_download_software_2/nswitchds_lostinrandom/NSwitchDS_LostInRandom_06.jpg',
'https://cdn02.nintendo-europe.com/media/images/10_share_images/games_15/nintendo_switch_download_software_1/H2x1_NSwitchDS_LostInRandom_image1600w.jpg',
]
type CreateImagesParams = CreateImageParams & {
count: number
width: number
height: number
}
const createImages = ({ count, width, height }: CreateImagesParams) => {
const images = []
for (let i = 0; i < count; i++) {
images.push({
id: randomString(10),
src: sampleImages[Math.floor(Math.random() * sampleImages.length)],
})
}
return images
}
const initImages = (() => {
return createImages({ count: 4, width: 200, height: 800 })
})()
type ImageData = {
id: string
src: string
}
export default () => {
const [images, setImages] = React.useState<ImageData[]>(initImages)
const [currentId, setCurrentId] = React.useState<string | void>(initImages[0].id)
const addToStart = () => {
const newImages = createImages({ count: 5, width: 300, height: 900 })
setImages([...newImages, ...images])
}
const addToEnd = () => {
const newImages = createImages({ count: 5, width: 1000, height: 800 })
setImages([...images, ...newImages])
}
const toLastItem = () => {
if (!images.length) {
return
}
const { id } = images[images.length - 1]
setCurrentId(id)
}
return (
<View style={{ width: '100%', flexDirection: 'column' }}>
<View style={styles.sliderWrap}>
<RnImageSwiper
currentId={currentId}
onChange={setCurrentId}
images={images}
minScale={0.6}
maxScale={8}
/>
</View>
<View style={styles.buttons}>
<Button title="add to start" onPress={addToStart} />
<Button title="add to end" onPress={addToEnd} />
<Button title="to last item" onPress={toLastItem} />
</View>
</View>
)
}
const styles = StyleSheet.create({
sliderWrap: {
width: '100%',
height: 400,
backgroundColor: 'green',
},
buttons: {
flexDirection: 'row',
justifyContent: 'center',
},
})
react-native-image-swiper
bi-directional swiper for ReactNative
Features
- Android/iOS support
- zoom image
- correct behavior when adding new images
Why does the world need another swiper?
if you use/wrote a some swiper on ReactNative, you must have suffered. The big problem starts when you start adding items dynamically to the beginning of the list. This happens because the maintainVisibleContentPosition
prop is not supported in ScrollView (Flatlist) on android (only iOS support). And the default behavior of ScrollView when adding new items is to shift to the beginning. This leads to a terrible UX.
The standard solution for android in this situation is to use RecyclerView
. That's exactly what we did by implementing a native swiper module for Android (The iOS implementation is based on Flatlist).
Is it customizable?
Just a little bit. We added only some basic props because we needed a quick solution for our own project. But it works! If you need a simple image swiper that won't break when you add new images, this is the one for you.
Perhaps we will customize this component in the future.
Installation
npm install @42px/react-native-image-swiper
Usage
import React from 'react'
import { Button, StyleSheet, View } from 'react-native'
import { Colors } from 'react-native/Libraries/NewAppScreen'
import { RnImageSwiper } from '@42px/react-native-image-swiper'
const sampleImages = [
'https://hatrabbits.com/wp-content/uploads/2017/01/random.jpg',
'https://cdn02.nintendo-europe.com/media/images/06_screenshots/games_5/nintendo_switch_download_software_2/nswitchds_lostinrandom/NSwitchDS_LostInRandom_06.jpg',
'https://cdn02.nintendo-europe.com/media/images/10_share_images/games_15/nintendo_switch_download_software_1/H2x1_NSwitchDS_LostInRandom_image1600w.jpg',
]
type CreateImagesParams = CreateImageParams & {
count: number
width: number
height: number
}
const createImages = ({ count, width, height }: CreateImagesParams) => {
const images = []
for (let i = 0; i < count; i++) {
images.push({
id: randomString(10),
src: sampleImages[Math.floor(Math.random() * sampleImages.length)],
})
}
return images
}
const initImages = (() => {
return createImages({ count: 4, width: 200, height: 800 })
})()
type ImageData = {
id: string
src: string
}
export default () => {
const [images, setImages] = React.useState<ImageData[]>(initImages)
const [currentId, setCurrentId] = React.useState<string | void>(initImages[0].id)
const addToStart = () => {
const newImages = createImages({ count: 5, width: 300, height: 900 })
setImages([...newImages, ...images])
}
const addToEnd = () => {
const newImages = createImages({ count: 5, width: 1000, height: 800 })
setImages([...images, ...newImages])
}
const toLastItem = () => {
if (!images.length) {
return
}
const { id } = images[images.length - 1]
setCurrentId(id)
}
return (
<View style={{ width: '100%', flexDirection: 'column' }}>
<View style={styles.sliderWrap}>
<RnImageSwiper
currentId={currentId}
onChange={setCurrentId}
images={images}
minScale={0.6}
maxScale={8}
/>
</View>
<View style={styles.buttons}>
<Button title="add to start" onPress={addToStart} />
<Button title="add to end" onPress={addToEnd} />
<Button title="to last item" onPress={toLastItem} />
</View>
</View>
)
}
const styles = StyleSheet.create({
sliderWrap: {
width: '100%',
height: 400,
backgroundColor: 'green',
},
buttons: {
flexDirection: 'row',
justifyContent: 'center',
},
})