ReactNative開發入門教學(6)-用ScrollView製作有換頁功能的相本

大家應該都很常在APP上看到這個功能。一開始在網路上找看看是不是

有人已經寫好套件可以直接使用,後來找到了一個叫做react-native-image-slider

的套件,的確就是這個功能。但是實裝之後發現圖片無法正常的顯示出來

在該套件的github上也有人提出相同的疑問,但是作者並沒有回答。

有興趣使用的可以上NPM看看https://www.npmjs.com/package/react-native-image-slider

所以我看了一下這個套件的原始碼,大概知道原理之後就朝ScrollView這

方面找資料,其實在ReactNative上可以很簡單的實現!

雖然稱不上完美,但是最基本的功能還是有的。

代碼如下:

import React, { Component } from 'react';
import { View, Image, ScrollView, StyleSheet, } from 'react-native';

class ImageSlide extends Component {
  constructor(props) {
    super(props);
    this.state = {
      images:  ['http://--/xxx.jpg','http://--/xxx.jpg','http://--/xxx.jpg'],
    };
  }
  _renderImage() {
    let result = [];
    this.state.images.map((url, index) => {
      result.push(<Image key={index} source={ {uri: url} } style={styles.thumbnail_l}>);
    });
    return result;
  }
  render() {
    return (
      <View style={styles.thumbnail_area}>
        <ScrollView 
          horizontal={true}
          showsHorizontalScrollIndicator={false}
          pagingEnabled={true}
          style={styles.thumbnail_scroll}
        >
        {this._renderImage()}
        </ScrollView>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  thumbnail_area: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  thumbnail_scroll: {
    flexDirection: 'row',
    width: 250,
    height: 150,
  },
  thumbnail_l: {
    flex: 1,
    width: 250,
    resizeMode: 'contain',
  },
});

export default ImageSlide;

其實就是把每一張圖片分別做好之後塞到ScrollView裡面,並且開啟換頁功能(pagingEnabled)

然後再把排列設定成row就可以了。

但是單純這個樣子沒辦法知道有幾張圖片,也不知道現在在第幾張圖片,所以得加上一個顯示

當前位子的功能。我們加上一個顯示頁碼的方法後程式碼如下

import React, { Component } from 'react';
import { View, Image, ScrollView, StyleSheet, } from 'react-native';

class ImageSlide extends Component {
  constructor(props) {
    super(props);
    this.state = {
      images:  ['http://--/xxx.jpg','http://--/xxx.jpg','http://--/xxx.jpg'],
    };
  }
  _renderImage() {
    let result = [];
    this.state.images.map((url, index) => {
      result.push(<Image key={index} source={ {uri: url} } style={styles.thumbnail_l}>);
    });
    return result;
  }
  _renderPaging(count) {
    let result = [], icon_color;
    for(var i = 0; i < count; i++ ) {
      icon_color = (this.state.image_position === i) ? {color: 'red'} : {color: 'gray'};
      result.push(
        <Text key={i} style={[{fontSize: 20}, icon_color]}>●</Text>
      );
    }
    return result;
  }
  render() {
    return (
      <View style={styles.thumbnail_area}>
        <ScrollView 
          horizontal={true}
          showsHorizontalScrollIndicator={false}
          pagingEnabled={true}
          style={styles.thumbnail_scroll}
        >
          {this._renderImage()}
        </ScrollView>
        <View style={styles.thumbnail_paging}>
          {this._renderPaging(this.state.images.length)}
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  thumbnail_area: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  thumbnail_scroll: {
    flexDirection: 'row',
    width: 250,
    height: 150,
  },
  thumbnail_l: {
    flex: 1,
    width: 250,
    resizeMode: 'contain',
  },
  thumbnail_paging: {
    flexDirection: 'row',
    justifyContent: 'center',
    width: 250,
    position: 'absolute',
    bottom: 0,
    backgroundColor: 'rgba(255,255,255,0.0)'
  },
});

export default ImageSlide;

總共幾張圖片是顯示出來了,但是移動圖片的時候下面的頁碼圖示並不會跟著變動,那是因為我們沒有加上

onMomentumScrollEnd的參數,這是一個ScrollView移動完後執行的參數。我們加上並且寫一個切換圖示

的方法

import React, { Component } from 'react';
import { View, Image, ScrollView, StyleSheet, } from 'react-native';

class ImageSlide extends Component {
  constructor(props) {
    super(props);
    this.state = {
      images:  ['http://--/xxx.jpg','http://--/xxx.jpg','http://--/xxx.jpg'],
    };
  }
  _renderImage() {
    let result = [];
    this.state.images.map((url, index) => {
      result.push(<Image key={index} source={ {uri: url} } style={styles.thumbnail_l}>);
    });
    return result;
  }
  _renderPaging(count) {
    let result = [], icon_color;
    for(var i = 0; i < count; i++ ) {
      icon_color = (this.state.image_position === i) ? {color: 'red'} : {color: 'gray'};
      result.push(
        <Text key={i} style={[{fontSize: 20}, icon_color]}>●</Text>
      );
    }
    return result;
  }
  _changeImage(event) {
    let offset_x = event.nativeEvent.contentOffset.x;
    let position = offset_x / 250;
    this.setState({image_position: position});
  }
  render() {
    return (
      <View style={styles.thumbnail_area}>
        <ScrollView 
          horizontal={true}
          showsHorizontalScrollIndicator={false}
          pagingEnabled={true}
          style={styles.thumbnail_scroll}
          onMomentumScrollEnd={this._changeImage.bind(this)}
        >
          {this._renderImage()}
        </ScrollView>
        <View style={styles.thumbnail_paging}>
          {this._renderPaging(this.state.images.length)}
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  thumbnail_area: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  thumbnail_scroll: {
    flexDirection: 'row',
    width: 250,
    height: 150,
  },
  thumbnail_l: {
    flex: 1,
    width: 250,
    resizeMode: 'contain',
  },
  thumbnail_paging: {
    flexDirection: 'row',
    justifyContent: 'center',
    width: 250,
    position: 'absolute',
    bottom: 0,
    backgroundColor: 'rgba(255,255,255,0.0)'
  },
});

export default ImageSlide;

其實就是去取到現在的畫面所在的x軸,然後用這個軸的數據去除以圖片的寬度就可以

算出現在在第幾張圖片了!這樣一個簡單的有換頁功能的滑動相簿就完成啦!