前因:最近在用React-native 做一个APP,其中有一个新闻页面用到了轮播图,而且要求轮播图的图片都是异步获取的,经过测试,发现只有静态写死的一组图片或者一组文本,才能正常轮播,ajax获取到的无法正常轮播,作死就这样开始了。。。
坑:在父级View容器flex:1时,Swiper的高度是谜一样的存在,平白的多出了不少高度占用了很大空间,给Swiper设置了style不管用,给指示点加样式也不起效,最后,直接给父级View容器加个高度解决问题。
PS:这边是Swiper组件属性介绍的传送门:https://blog.youkuaiyun.com/hzxOnlineOk/article/details/104019665
今天学习了轮播图的使用,上网查阅了一下,发现有react-native-swiper和React-Native-Viewpager(https://blog.youkuaiyun.com/zhukui66/article/details/51077592)两种封装的比较好的第三方组件,对比了下文档,觉得react-native-swiper功能更加完善,而且文档说明比较全面,所以只用了react-native-swiper,下面介绍下react-native-swiper的使用。该组件同时支持android和iOS。
react-native-swiper的github地址
使用说明:
- 先安装React-native-swiper
npm install react-native-swiper --save - 导入Swiper
import Swiper from ‘react-native-swiper’;
3.使用Swiper
<Swiper
style={styles.swiper}
height={200}
horizontal={true}
paginationStyle={{bottom: 10}}
showsButtons={false}>
<Image source={require('./js/img/a.jpg')} style={styles.img}/>
<Image source={require('./js/img/b.jpg')} style={styles.img}/>
<Image source={require('./js/img/c.jpg')} style={styles.img}/>
</Swiper>
const styles = StyleSheet.create({
swiper: {},
img: {
width: dimensions.width,
height: 200,
}
});
4.相关属性和方法介绍
<Swiper
style={styles.swiper} //样式
height={200} //组件高度
loop={true} //如果设置为false,那么滑动到最后一张时,再次滑动将不会滑到第一张图片。
autoplay={true} //自动轮播
autoplayTimeout={4} //每隔4秒切换
horizontal={true} //水平方向,为false可设置为竖直方向
paginationStyle={{bottom: 10}} //小圆点的位置:距离底部10px
showsButtons={false} //为false时不显示控制按钮
showsPagination={false} //为false不显示下方圆点
dot={<View style={{ //未选中的圆点样式
backgroundColor: 'rgba(0,0,0,.2)',
width: 18,
height: 18,
borderRadius: 4,
marginLeft: 10,
marginRight: 9,
marginTop: 9,
marginBottom: 9,
}}/>}
activeDot={<View style={{ //选中的圆点样式
backgroundColor: '#007aff',
width: 18,
height: 18,
borderRadius: 4,
marginLeft: 10,
marginRight: 9,
marginTop: 9,
marginBottom: 9,
}}/>}
>
<Image source={require('./js/img/a.jpg')} style={styles.img}/>
<Image source={require('./js/img/b.jpg')} style={styles.img}/>
<Image source={require('./js/img/c.jpg')} style={styles.img}/>
</Swiper>
image.png
image.png
image.png
作者:现实梦想_96b0
链接:https://www.jianshu.com/p/8905d988d1db
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
经排查,发现this.state.list在初始化时是一个空数组[],在Swiper组件内通过list&&list.map去遍历,这会导致Swiper组件初始化时,采用list的初始化值也就是空数组[],Swiper组件默认它不存在“滑动子元素(slider)” 也就是slider数为0
解决:将list移动到Swiper组件外面进行判断,也就是list.length ? <Component/> : null,由于js的0代表false,因此会在初始化时不渲染Swiper组件,因此避免了Swiper在list没有获取到数据的情况下事先初始化,代码如下:
<View style={styles.headImage}>
{
list.length ? <Swiper style={styles.wrapper} height={200} horizontal={true} autoplay autoplayTimeout={1}>
{
list.slice(0, 3).map((item, index) => {
return (
<TouchableOpacity onPress={() => this._onPressButton(item.id, item)}>
<View style={styles.headImage}>
<ImageAction key={index} style={styles.headImage} reqUrl={api.getImage} reqParams={[item.id, "newsLogo"]} />
<View style={styles.slogan}>
<Text style={styles.sloganTitle} numberOfLines={1}>{item.title}</Text>
</View>
</View>
</TouchableOpacity>
)
})
}
</Swiper> : null
}
</View>
这是原故障完整代码:
import React from 'react';
import { Text, View, TouchableOpacity, ScrollView, Image } from 'react-native';
import Swiper from 'react-native-swiper';
import OAColor from '../../theme/OAColor';
import BaseScene from "../../base/BaseScene";
import RefreshPageContainer from '../../base/RefreshPageContainer';
import { ImageAction } from '../../components';
import { post } from '../../common';
import api from '../../services/app';
import styles from './styles/private-styles';
type IProps = {};
type IState = {};
export default class PrivateIndex extends BaseScene<IProps, IState> {
constructor(props: Props) {
super(props);
mb(this).init(props, {
list: [],
pageNum: 1,
pageSize: 3,
});
}
componentWillMount() {
super.showNavTitle("私募圈");
this.getNewsFn()
}
getNewsFn = () => {
const { pageNum, pageSize } = this.state;
const reqUrl = api.getBestNewNewsList;
const reqParam = {
"params": [
{}, pageNum, pageSize
]
};
post(reqUrl, reqParam)
.then(res => {
this.setState({ list: res.rows })
})
.catch(error => {
MOALog.info('==>error', error);
});
};
render() {
const { list } = this.state;
return (
<View style={{ flex: 1 }}>
<ScrollView style={{ flex: 1 }}>
<View style={styles.headImage}>
<Swiper style={styles.wrapper} height={200} horizontal={true} autoplay autoplayTimeout={1}>
{
list ? list.map((item, index) => {
if (index < 3)
return (
<TouchableOpacity onPress={() => this._onPressButton(item.id, item)}>
<View style={styles.headImage}>
<ImageAction key={index} style={styles.headImage} reqUrl={api.getImage} reqParams={[item.id, "newsLogo"]} />
<View style={styles.slogan}>
<Text style={styles.sloganTitle} numberOfLines={1}>{item.title}</Text>
</View>
</View>
</TouchableOpacity>
)
}) : ['', '', ''].map(it => {
return (
<Image source={require('./img/private.png')} style={{ width: '100%', height: 150 }} />
)
})
}
</Swiper>
</View>
<RefreshPageContainer
style={{ marginTop: 10, backgroundColor: OAColor.barTint }}
api={api.getBestNewNewsList}
renderItem={this.renderMainItem}
pager={true}
pageSize={6}
mutilParams={[{}]}
dataHandler={(rows, pageNum) => {
return pageNum === 1 ? rows.slice(3) : rows;
}}
showSeparatorComponent={false}
pageStatusStyle={{ marginTop: 45 }}
/>
</ScrollView>
</View>
)
}
renderMainItem = ({ item }) => {
return (
<TouchableOpacity onPress={() => this._onPressButton(item.id, item)}>
<View style={styles.mainItemContainer}>
<View style={styles.items}>
<Text numberOfLines={2} style={{ fontSize: 16, color: '#262626' }}>{item.title}</Text>
<Text style={{ fontSize: 12, color: OAColor.descText }}>{item.createTime}</Text>
</View>
<ImageAction style={styles.rightImage} reqUrl={api.getImage} reqParams={[item.id, "newsLogo"]} />
</View>
</TouchableOpacity>
)
};
_onPressButton = (id, item) => {
mb(this).getNavigator().push('PrivateDetailScene', { id: item.id, item });
}
}
这是解决完整代码:
import React from 'react';
import { Text, View, TouchableOpacity, ScrollView, Image } from 'react-native';
import Swiper from 'react-native-swiper';
import OAColor from '../../theme/OAColor';
import BaseScene from "../../base/BaseScene";
import RefreshPageContainer from '../../base/RefreshPageContainer';
import { ImageAction } from '../../components';
import { post } from '../../common';
import api from '../../services/app';
import styles from './styles/private-styles';
type IProps = {};
type IState = {};
export default class PrivateIndex extends BaseScene<IProps, IState> {
constructor(props: Props) {
super(props);
mb(this).init(props, {
list: [],
pageNum: 1,
pageSize: 3,
});
}
componentWillMount() {
super.showNavTitle("私募圈");
this.getNewsFn()
}
getNewsFn = () => {
const { pageNum, pageSize } = this.state;
const reqUrl = api.getBestNewNewsList;
const reqParam = {
"params": [
{}, pageNum, pageSize
]
};
post(reqUrl, reqParam)
.then(res => {
this.setState({ list: res.rows })
})
.catch(error => {
MOALog.info('==>error', error);
});
};
render() {
const { list } = this.state;
return (
<View style={{ flex: 1 }}>
<ScrollView style={{ flex: 1 }}>
<View style={styles.headImage}>
{
list.length ? <Swiper style={styles.wrapper} height={200} horizontal={true} autoplay autoplayTimeout={1}>
{
list.slice(0, 3).map((item, index) => {
return (
<TouchableOpacity onPress={() => this._onPressButton(item.id, item)}>
<View style={styles.headImage}>
<ImageAction key={index} style={styles.headImage} reqUrl={api.getImage} reqParams={[item.id, "newsLogo"]} />
<View style={styles.slogan}>
<Text style={styles.sloganTitle} numberOfLines={1}>{item.title}</Text>
</View>
</View>
</TouchableOpacity>
)
})
}
</Swiper> : null
}
</View>
<RefreshPageContainer
style={{ marginTop: 10, backgroundColor: OAColor.barTint }}
api={api.getBestNewNewsList}
renderItem={this.renderMainItem}
pager={true}
pageSize={6}
mutilParams={[{}]}
dataHandler={(rows, pageNum) => {
return pageNum === 1 ? rows.slice(3) : rows;
}}
showSeparatorComponent={false}
pageStatusStyle={{ marginTop: 45 }}
/>
</ScrollView>
</View>
)
}
renderMainItem = ({ item }) => {
return (
<TouchableOpacity onPress={() => this._onPressButton(item.id, item)}>
<View style={styles.mainItemContainer}>
<View style={styles.items}>
<Text numberOfLines={2} style={{ fontSize: 16, color: '#262626' }}>{item.title}</Text>
<Text style={{ fontSize: 12, color: OAColor.descText }}>{item.createTime}</Text>
</View>
<ImageAction style={styles.rightImage} reqUrl={api.getImage} reqParams={[item.id, "newsLogo"]} />
</View>
</TouchableOpacity>
)
};
_onPressButton = (id, item) => {
mb(this).getNavigator().push('PrivateDetailScene', { id: item.id, item });
}
}