自定义View——React

编程入门 行业动态 更新时间:2024-10-06 04:10:16

<a href=https://www.elefans.com/category/jswz/34/1771438.html style=自定义View——React"/>

自定义View——React

我尽量不打错别字,用词准确,不造成阅读障碍。

最近一直在写RN,赶项目,好久没写博客和更新github了,加上昨天被一个json不会写、甩锅超强的菜鸡同事气到了,今天怎么也得写一些,哭~~。

很多人需要轮播图都会使用开源的"react-native-swiper"之类的东西,人家写的确实牛逼,但是我有个执念,不习惯随意使用第三方的东西,就喜欢造轮子,我一般选择把别人的原理看明白然后自己写,这样可以像做衣服一样,量身定制。所以本文也只是希望可以给需要帮助的人一些实现的思路或者可以学习的地方并顺道记录我的学习状态。

声明:我是Android原生开发出身,并不是前端出身,所以代码风格、js使用技巧等肯定不会很专业,难免会有"low"的地方,见谅见谅,笑~~。

先看效果:

哈哈,这个gif录的区域歪了,我把状态栏透明了,见谅见谅。

这个在Android和IOS平台都可以跑通,亲测,实际也是因为没有使用任何平台特有的属性和api。
原理:超级简单,就是ScrollView定时滚动,再加上页面指示器,就是底下的小白点。这里做的比较粗糙,没有考虑最后一个页面与第一个页面的过渡问题,完全交给了ScrollView自身Api——scrollTo去解决,实际效果看起来还可以,难道Facebook有处理?

 render() {//拿到内容的view集合和内容的stylelet {itemDataList, style, itemRootStyle} = this.props;let menuViews = [];pageCount = itemDataList.length;for (let i = 0; i < pageCount; i++) {let onePageDate;onePageDate = itemDataList[i];menuViews.push(<View style={itemRootStyle} key={i}>{onePageDate}</View>);}return (<Viewstyle={style}><ScrollViewref="scrollView"horizontal={true}showsHorizontalScrollIndicator={false}pagingEnabled={true}onScroll={(e) => this.onScroll(e)}>{menuViews}</ScrollView>//页面指示器{this.getPageControl(this.state.currentPage, pageCount)}</View>);}

其中滚动内容的View集合和内容style是从外面传过来的,用for循环加入到一个数组menuViews中,最后作为ScrollView的数据源,最最后,加入页面指示器。

页面指示器也是我自定义的,先写上调用方法:

getPageControl(currentPage, numberOfPages) {let control = (<PageControlstyle={MyCarouseStyle.pageControl}numberOfPages={pageCount}currentPage={this.state.currentPage}indicatorStyle={this.props.indicatorStyle}currentIndicatorStyle={this.props.currentIndicatorStyle}/>);return control;}

style是样式,nubmerOfPages是页面总数,根据数据源计算传入,currentPage是当前页面值,因为要根据ScrollView滚动来改变,所以我觉得写在外面好处理。indicatorStyle是默认指示器样式,currentIndicatorStyle是当前指示器样式,即选中状态。

贴上指示器代码:

import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {View, StyleSheet} from 'react-native'
import screen from "../utils/Screen";export default class PageControl extends Component {constructor(props: Object) {super(props);}static propTypes = {numberOfPages: PropTypes.number.isRequired,currentPage: PropTypes.number,indicatorStyle: PropTypes.object,currentIndicatorStyle: PropTypes.object,style: PropTypes.object,};static defaultProps = {numberOfPages: 0,currentPage: 0,indicatorStyle: {backgroundColor: "#000", width: 8, height: 8, borderRadius: 4},currentIndicatorStyle: {backgroundColor: "#ff0000",width: 8,height: 8,borderRadius: 4},style: {}};render() {let {indicatorStyle, currentIndicatorStyle, numberOfPages, currentPage, style} = this.props;return (<View style={style}>{this.setItem(numberOfPages, currentPage, currentIndicatorStyle, indicatorStyle)}</View>)}setItem(numberOfPages, currentPage, currentIndicatorStyle, indicatorStyle) {let menuViews = [];for (let i = 0; i < numberOfPages; i++) {let menuView = (<View key={i} style={i === currentPage ? currentIndicatorStyle : indicatorStyle}/>);menuViews.push(menuView);}return (<View style={styles.container}>{menuViews}</View>);}
}const styles = StyleSheet.create({container: {backgroundColor: 'transparent',alignItems: 'center',justifyContent: 'center',flexDirection: 'row',height: 10,width: screen.width,textAlign: 'center'}
});

很简单的,指示器的代码我贴的是最全的,就不用解释了吧,笑哭~。

再看一下定时器的处理:

 autoPlayInterval = null; //计时器componentDidMount() {let {isAutoPlay, width} = this.props;let page = 0;if (isAutoPlay) {this.autoPlayInterval = setInterval(() => {page = page < pageCount ? page + 1 : 0;this.refs.scrollView.scrollTo({x: width * page}, 0, true)}, 2000);}}//监听滚动事件更新viewonScroll(e: any) {let x = e.nativeEvent.contentOffset.x;let currentPage = Math.round(x / screen.width);if (this.state.currentPage !== currentPage) {this.setState({currentPage: currentPage});}}
//最后别忘了clear定时器,官方建议~~
componentWillUnmount() {this.autoPlayInterval && clearInterval(this.autoPlayInterval);}

isAutoPlay表示是否自动轮播。其实就是根据每一个页面的宽度去调用scrollTo函数,因为页面宽度不一定是屏幕宽度啊,谁知道会不会有左右间距25px之类的。

最后看看怎么调用的,毕竟有很多属性是外面传进来的。

 <MyCarouselView style={{}}itemDataList={this.headViewItem2()}itemRootStyle={{}}indicatorStyle={homeStyle.headIndicatorStyle}currentIndicatorStyle={homeStyle.headCurrentIndicatorStyle}isAutoPlay={true}width={screen.width}type=""/>

有些属性比如style、type传个空就好了,因为我这个是从项目中拿出来的,通用性没太考虑。headViewItem2()方法里面是数据源:

headViewItem2() {let imageList = [];for (let i = 0; i < 4; i++) {let itemView = (<TouchableOpacitykey={i}onPress={() => this.goProduceDetail()}><View style={homeStyle.headView}><Text style={{textAlign: "center",color: '#000',width: screen.width,paddingTop: 85,height: 180,backgroundColor: '#cc0000'}}>页面{i}</Text></View></TouchableOpacity>);imageList.push(itemView);}return imageList;}

举个例子这么写;

本文并没有github或其他Demo地址,因为这是我从项目里抠出来的,很多style和import我没写,这应该不会成为学习的障碍,除非你是比我还白的小白,笑哭~~~~。有问题欢迎提问,我看到就会尽力给你解答。

更多推荐

自定义View——React

本文发布于:2024-02-28 14:53:15,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1769844.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自定义   View   React

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!