React Native学习-CameraRoll

react-native中CameraRoll模块提供了访问本地相册的功能。

在react版本为0.23.0的项目中,不支持Android,而且在iOS中使用CameraRoll还需要我们手动操作:

iOS:

  1. 将RCTCameraRoll.xcodeproj添加到我们的项目中:展开项目 > Libraies  右键Libraies点击 “Add Files to ‘项目名’ ”,找到 项目文件夹/node_modules/react-native/Libraries/CameraRoll/RCTCameraRoll.xcodeproj , 添加到项目里。
  2. 我们要把libRCTCameraRoll.a这个苦添加到主项目的Link Binary With Libraries中,如下图:

经过这样的添加我们在项目中再使用CameraRoll里边的函数就不会出错了。

CameraRoll模块中有两个函数:saveImageWithTag()、getPhotos()。

saveImageWithTag()

保存一个图片到相册。

@param {string} tag 在安卓上,本参数是一个本地URI,例如"file:///sdcard/img.png".

在iOS设备上可能是以下之一:

  • 本地URI
  • 资源库的标签
  • 非以上两种类型,表示图片数据将会存储在内存中(并且在本进程持续的时候一直会占用内存)。

返回一个Promise,操作成功时返回新的URI。

示例:

CameraRoll.saveImageWithTag(image).then(function (success) {
            Alert.alert(
                '',
                '保存到相册成功',
                [
                    {text: '确定', onPress: () => console.log(success)}

                ]
            )
        }, function (error) {
            Alert.alert(
                '',
                '保存到相册失败',
                [
                    {text: '确定', onPress: () => console.log(error)}

                ]
            )
        }
    )
}

获得相册中的照片。getPhotos()

学习这个功能是在官方demo中学习的,它写成了一个可以使用的js文件CameraRollView.js,我们需要将该文件引入我们的项目中。

CameraRollView.js文件代码:

/**
 * The examples provided by Facebook are for non-commercial testing and
 * evaluation purposes only.
 *
 * Facebook reserves all rights not expressly granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
 * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @providesModule CameraRollView
 * @flow
 */
'use strict';

var React = require('react');
var ReactNative = require('react-native');
var {
  ActivityIndicatorIOS,
  CameraRoll,
  Image,
  ListView,
  Platform,
  StyleSheet,
    TouchableOpacity,
  View,
} = ReactNative;

var groupByEveryN = require('groupByEveryN');
var logError = require('logError');

var propTypes = {
  /**
   * The group where the photos will be fetched from. Possible
   * values are 'Album', 'All', 'Event', 'Faces', 'Library', 'PhotoStream'
   * and SavedPhotos.
   */
  groupTypes: React.PropTypes.oneOf([
    'Album',
    'All',
    'Event',
    'Faces',
    'Library',
    'PhotoStream',
    'SavedPhotos',
  ]),

  /**
   * Number of images that will be fetched in one page.
   */
  batchSize: React.PropTypes.number,

  /**
   * A function that takes a single image as a parameter and renders it.
   */
  renderImage: React.PropTypes.func,

  /**
   * imagesPerRow: Number of images to be shown in each row.
   */
  imagesPerRow: React.PropTypes.number,

   /**
   * The asset type, one of 'Photos', 'Videos' or 'All'
   */
  assetType: React.PropTypes.oneOf([
    'Photos',
    'Videos',
    'All',
  ]),

};

var CameraRollView = React.createClass({
  propTypes: propTypes,

  getDefaultProps: function(): Object {
    return {
      groupTypes: 'SavedPhotos',
      batchSize: 5,
      imagesPerRow: 1,
      assetType: 'Photos',
      renderImage: function(asset) {
        var imageSize = 150;
        var imageStyle = [styles.image, { imageSize, height: imageSize}];
        return (
          <Image
            source={asset.node.image}
            style={imageStyle}
          />
        );
      },
    };
  },

  getInitialState: function() {
    var ds = new ListView.DataSource({rowHasChanged: this._rowHasChanged});

    return {
      assets: ([]: Array<Image>),
      groupTypes: this.props.groupTypes,
      lastCursor: (null : ?string),
      assetType: this.props.assetType,
      noMore: false,
      loadingMore: false,
      dataSource: ds,
    };
  },

  /**
   * This should be called when the image renderer is changed to tell the
   * component to re-render its assets.
   */
  rendererChanged: function() {
    var ds = new ListView.DataSource({rowHasChanged: this._rowHasChanged});
    this.state.dataSource = ds.cloneWithRows(
      groupByEveryN(this.state.assets, this.props.imagesPerRow)
    );
  },

  componentDidMount: function() {
    this.fetch();
  },

  componentWillReceiveProps: function(nextProps: {groupTypes?: string}) {
    if (this.props.groupTypes !== nextProps.groupTypes) {
      this.fetch(true);
    }
  },

  _fetch: function(clear?: boolean) {
    if (clear) {
      this.setState(this.getInitialState(), this.fetch);
      return;
    }

    var fetchParams: Object = {
      first: this.props.batchSize,
      groupTypes: this.props.groupTypes,
      assetType: this.props.assetType,
    };
    if (Platform.OS === "android") {
      // not supported in android
      delete fetchParams.groupTypes;
    }
    if (this.state.lastCursor) {
      fetchParams.after = this.state.lastCursor;
    }

    CameraRoll.getPhotos(fetchParams)
      .then((data) => this._appendAssets(data), (e) => logError(e));
  },

  /**
   * Fetches more images from the camera roll. If clear is set to true, it will
   * set the component to its initial state and re-fetch the images.
   */
  fetch: function(clear?: boolean) {
    if (!this.state.loadingMore) {
      this.setState({loadingMore: true}, () => { this._fetch(clear); });
    }
  },

  render: function() {
    return (
        <View style={{flexWrap: 'wrap'}}>
              <ListView contentContainerStyle={{flex:1, flexDirection:'row',flexWrap: 'wrap', justifyContent:'center'}}
                renderRow={this._renderRow}
                renderFooter={this._renderFooterSpinner}
                onEndReached={this._onEndReached}
                style={{flex:1}}
                dataSource={this.state.dataSource}
              />
            </View>
    );
  },

  _rowHasChanged: function(r1: Array<Image>, r2: Array<Image>): boolean {
    if (r1.length !== r2.length) {
      return true;
    }

    for (var i = 0; i < r1.length; i++) {
      if (r1[i] !== r2[i]) {
        return true;
      }
    }

    return false;
  },

  _renderFooterSpinner: function() {
    if (!this.state.noMore) {
      return <ActivityIndicatorIOS style={styles.spinner} />;
    }
    return null;
  },

  // rowData is an array of images
  _renderRow: function(rowData: Array<Image>, sectionID: string, rowID: string)  {
    var images = rowData.map((image) => {
      if (image === null) {
        return null;
      }
      return this.props.renderImage(image);
    });

    return (
        <View>
         {images}
      </View>
    );
  },

  _appendAssets: function(data: Object) {
    var assets = data.edges;
    var newState: Object = { loadingMore: false };

    if (!data.page_info.has_next_page) {
      newState.noMore = true;
    }

    if (assets.length > 0) {
      newState.lastCursor = data.page_info.end_cursor;
      newState.assets = this.state.assets.concat(assets);
      newState.dataSource = this.state.dataSource.cloneWithRows(
        groupByEveryN(newState.assets, this.props.imagesPerRow)
      );
    }

    this.setState(newState);
  },

  _onEndReached: function() {
    if (!this.state.noMore) {
      this.fetch();
    }
  },
});

var styles = StyleSheet.create({
  image: {
    margin: 4,
  },
});

module.exports = CameraRollView;

文件打开会有错误显示,只是语法不一样,这个不影响效果。

使用方法:

import CameraRollView from '../CameraRollView';

export  default class CameraRollView extends Component {
    constructor(props) {
        super(props);
        CameraRoll.getPhotos({
            first: 21,
            assetType: 'Photos'
        }).then(function (data) {

        }, function (error) {

        })
    }

    _renderImage(asset) {
        var windowSize = require('Dimensions').get('window');
        return (
            <TouchableOpacity key={asset}>
                <Image source={asset.node.image} style={{ (windowSize.width-30)/3, height: 110, margin:5}}/>
            </TouchableOpacity>
        );
    }

    render() {
        return (<View style={{flex:1}}>
                  <CameraRollView renderImage={this._renderImage}/>
                </View>
        )
    }
}
原文地址:https://www.cnblogs.com/maoyazhi/p/5411759.html