Demo展示
Github上有兩個實現(xiàn)輪播圖的控件,一個是React-native-swiper旗国,一個是react-native-viewpager职员,不過今天我們不是去使用它拴还,而是自己簡單的來實現(xiàn)這個效果短曾。
Demo實現(xiàn)
<ScrollView
ref="scrollView"
horizontal={true}
showsHorizontalScrollIndicator={false}
pagingEnabled={true}
onMomentumScrollEnd={(scrollView)=>this.onAnimationEnd(scrollView)}
onScrollBeginDrag={this.onScrollBeginDrag.bind(this)}
onScrollEndDrag={this.onScrollEndDrag.bind(this)}
>
我們來看看每一行屬性的作用
-
ref
在界面中略步,如果想拿到一個組件的實例阅畴,我們可以通過ref來獲取抗果,也就是相當(dāng)于Android當(dāng)中的id筋帖。獲取的方法就是:this.refs.xxx
-
horizontal
這個就很簡單了,ScrollView滑動的方向有兩個冤馏,一個是horizontal(水平方向)日麸,另一個默認(rèn)是垂直方向滑動
-
showsHorizontalScrollIndicator & showsVerticalScrollIndicator
用來控制在滑動時是否顯示滾動條
-
pagingEnabled
水平滑動時,可以出現(xiàn)分頁效果逮光,讓一張圖片剛好顯示在屏幕上代箭。若不設(shè)置的話,當(dāng)滑動時可能會出幾張圖片都出現(xiàn)在屏幕上
-
onMomentumScrollEnd
監(jiān)聽一幀滾動完畢的時候的回調(diào)涕刚。我們可以通過這個屬性嗡综,可以算出當(dāng)前圖片中的第幾頁,從而可以控制下面的圓點滾動杜漠。后面代碼會講到
-
onScrollBeginDrag & onScrollEndDrag
滑動開始和結(jié)束的回調(diào)极景。在本Demo中是用來開啟和停止計時器察净。因為需要實現(xiàn)自動輪播,所以需用到計時器
View的渲染
在Demo中包含有兩個View盼樟,一個是由ScrollView包裹的Image塞绿,還有一個是構(gòu)成了圓點的Text,我們來看看它們的實現(xiàn)方式
/**
* 演染圖片
* @returns {Array}
* @private
*/
_renderAllImage() {
var imgArr = [];
var imgData = this.props.imgData;
for (var i in imgData) {
imgArr.push(
<Image
key={i}
source={{uri: imgData[i].icon}}
style={{width: width, height: 140}}
/>
)
}
return imgArr;
}
/**
* 渲染圓點指示器
* @private
*/
_renderCircleIndicator() {
var circleArr = [];
var imgData = this.props.imgData;
var style;
for (var i in imgData) {
style = i == this.state.currentPage ? {color: 'orange'} : {color: 'white'};
circleArr.push(
<Text key={i} style={[{fontSize: 25}, style]}>?</Text>
);
}
return circleArr;
}
方法前加了一個下劃線恤批,表示這個方法是private的异吻,然后圓點的表示方法是用"?
" ,這個可以在html標(biāo)簽中查到喜庞。圓點的數(shù)量由Image的數(shù)量決定诀浪,當(dāng)前currentPage為哪一張圖片,對應(yīng)的圓點就應(yīng)該是orange延都,其他就為white雷猪。我們的圓點并沒有包含在ScrollView中,而是通過樣式來完成的晰房。
// 絕對定位
position:'absolute',
bottom:0,
改變圓點樣式
那么在什么時候來改變圓點樣式了求摇?答案肯定是在一張圖片滑動結(jié)束后來改變它。上面已經(jīng)提到了殊者,可以通過onMomentumScrollEnd屬性來監(jiān)聽与境。那我們就來看看this.onAnimationEnd里同做了什么。
/**
* 當(dāng)一頁滑動結(jié)束時調(diào)用
* @param scrollView
*/
onAnimationEnd(scrollView) {
// 計算一頁滑動的偏移量
var offSetX = scrollView.nativeEvent.contentOffset.x;
console.log(offSetX);
// 算出當(dāng)前為第幾頁
var currentPage = Math.floor((offSetX / width));
this.setState({
currentPage: currentPage
});
}
其實就只做了一件事猖吴,那就是算出當(dāng)前圖片是第幾張摔刁,然后通過狀態(tài)來改變currentPage的值進行重新渲染。我們可以來看看滑動時的偏移量的值的log:
顯示第一張圖片時的offset是從0到384海蔽,然后依此類推共屈,當(dāng)反方向滑回去時,是從1536一直到第一張時党窜,offset就又變?yōu)?了拗引。初始坐標(biāo)值為左上角。
自動輪播
當(dāng)我們在界面啟動時就開啟了圖片自動輪播幌衣,也就是界面加載的時候我們需要開啟計時器矾削,那在哪里去開啟計時器了?在RN中泼掠,對于一些耗時操作都會把它放到它生命周期中的一個方法內(nèi)怔软,這就好比于在Android垦细,耗時操作只能放在子線程去操作择镇。
/**
* 一般在此方法中處理一些耗時操作
*/
componentDidMount() {
this._startTimer();
}
/**
* 在界面被銷毀時最好把計時器關(guān)掉,防止造成內(nèi)存泄露
*/
componentWillUnMount() {
clearInterval(this.interval);
}
我們再來看看開啟計時器做了一些什么事:
/**
* 開啟定時器
* @private
*/
_startTimer() {
var scrollView = this.refs.scrollView;
var imgCount = this.props.imgData.length;
this.interval = setInterval(() => {
//記錄當(dāng)前正在活動的圖片
var activePage = 0;
if ((this.state.currentPage + 1) >= imgCount) { //防止越界
activePage = 0;
} else {
activePage = this.state.currentPage + 1;
}
this.setState({
currentPage: activePage
});
//讓ScrollView動起來
var offSetX = activePage * width;
scrollView.scrollResponderScrollTo({x: offSetX, y: 0, animated: true});
}, this.state.duration);
}
這里的this.interval就是一個隱式的全局變量括改,所以在clearInterval(this.interval);
方法可以直接拿到它腻豌。用一個變量來記錄當(dāng)前的活動的頁,然后通過設(shè)置currentPage的狀態(tài)來刷新View,
最后ScrollView自身滑動到指定的位置吝梅。
即開了計時器虱疏,我們又手動去滑動圖片,此時我們還需要處理一些手動和自動不能并存的問題苏携。其實很簡單做瞪。只需要在手動時滑動停止計時器,松開時又開啟計時器就可以解決右冻。
/**
* 開始拖拽時的回調(diào)
* @private
*/
onScrollBeginDrag() {
clearInterval(this.interval);
}
/**
* 拖拽停止時的回調(diào)
* @private
*/
onScrollEndDrag() {
this._startTimer();
}
ScrollView還有幾個比較常用的屬性装蓬,雖然在本Demo中沒有使用到,有哪些了纱扭?
-
keyboardDismissMode 用戶拖拽滾動視圖的時候牍帚,是否要隱藏軟鍵盤(枚舉類型)
none(默認(rèn)值),拖拽時不隱藏軟鍵盤乳蛾。
on-drag 當(dāng)拖拽開始的時候隱藏軟鍵盤暗赶。
interactive 軟鍵盤伴隨拖拽操作同步地消失,并且如果往上滑動會恢復(fù)鍵盤肃叶。安卓設(shè)備上不支持這個選項蹂随,會表現(xiàn)的和none一樣。
-
keyboardShouldPersistTaps bool
當(dāng)此屬性為false的時候因惭,在軟鍵盤激活之后糙及,點擊焦點文本輸入框以外的地方,鍵盤就會隱藏筛欢。如果為true浸锨,滾動視圖不會響應(yīng)點擊操作,并且鍵盤不會自動消失版姑。默認(rèn)值為false柱搜。
好了。ScrollView組件我們就學(xué)習(xí)完了剥险。如有不對之處聪蘸,還請各位拍磚。完整代碼