mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
[ReactNative] OSS CameraRoll
This commit is contained in:
115
Examples/UIExplorer/CameraRollExample.ios.js
Normal file
115
Examples/UIExplorer/CameraRollExample.ios.js
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule CameraRollExample
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
CameraRoll,
|
||||
Image,
|
||||
Slider,
|
||||
StyleSheet,
|
||||
SwitchIOS,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
var CameraRollView = require('./CameraRollView.ios');
|
||||
|
||||
var CAMERA_ROLL_VIEW = 'camera_roll_view';
|
||||
|
||||
var CameraRollExample = React.createClass({
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
groupTypes: 'SavedPhotos',
|
||||
sliderValue: 1,
|
||||
bigImages: true,
|
||||
};
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<SwitchIOS
|
||||
onValueChange={this._onSwitchChange}
|
||||
value={this.state.bigImages} />
|
||||
<Text>{(this.state.bigImages ? 'Big' : 'Small') + ' Images'}</Text>
|
||||
<Slider
|
||||
value={this.state.sliderValue}
|
||||
onValueChange={this._onSliderChange}
|
||||
/>
|
||||
<Text>{'Group Type: ' + this.state.groupTypes}</Text>
|
||||
<CameraRollView
|
||||
ref={CAMERA_ROLL_VIEW}
|
||||
batchSize={5}
|
||||
groupTypes={this.state.groupTypes}
|
||||
renderImage={this._renderImage}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
_renderImage(asset) {
|
||||
var imageSize = this.state.bigImages ? 150 : 75;
|
||||
var imageStyle = [styles.image, {width: imageSize, height: imageSize}];
|
||||
var location = asset.node.location.longitude ?
|
||||
JSON.stringify(asset.node.location) : 'Unknown location';
|
||||
return (
|
||||
<View key={asset} style={styles.row}>
|
||||
<Image
|
||||
source={asset.node.image}
|
||||
style={imageStyle}
|
||||
/>
|
||||
<View style={styles.info}>
|
||||
<Text style={styles.url}>{asset.node.image.uri}</Text>
|
||||
<Text>{location}</Text>
|
||||
<Text>{asset.node.group_name}</Text>
|
||||
<Text>{new Date(asset.node.timestamp).toString()}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
_onSliderChange(value) {
|
||||
var options = CameraRoll.GroupTypesOptions;
|
||||
var index = Math.floor(value * options.length * 0.99);
|
||||
var groupTypes = options[index];
|
||||
if (groupTypes !== this.state.groupTypes) {
|
||||
this.setState({groupTypes: groupTypes});
|
||||
}
|
||||
},
|
||||
|
||||
_onSwitchChange(value) {
|
||||
this.refs[CAMERA_ROLL_VIEW].rendererChanged();
|
||||
this.setState({ bigImages: value });
|
||||
}
|
||||
});
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
flex: 1,
|
||||
},
|
||||
url: {
|
||||
fontSize: 9,
|
||||
marginBottom: 14,
|
||||
},
|
||||
image: {
|
||||
margin: 4,
|
||||
},
|
||||
info: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
exports.title = '<CameraRollView>';
|
||||
exports.description = 'Example component that uses CameraRoll to list user\'s photos';
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Photos',
|
||||
render() { return <CameraRollExample />; }
|
||||
}
|
||||
];
|
||||
231
Examples/UIExplorer/CameraRollView.ios.js
Normal file
231
Examples/UIExplorer/CameraRollView.ios.js
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* Copyright 2004-present Facebook. All Rights Reserved.
|
||||
*
|
||||
* @providesModule CameraRollView
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
ActivityIndicatorIOS,
|
||||
CameraRoll,
|
||||
Image,
|
||||
ListView,
|
||||
ListViewDataSource,
|
||||
StyleSheet,
|
||||
View,
|
||||
} = React;
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
var CameraRollView = React.createClass({
|
||||
propTypes: propTypes,
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
groupTypes: 'SavedPhotos',
|
||||
batchSize: 5,
|
||||
imagesPerRow: 1,
|
||||
renderImage: function(asset) {
|
||||
var imageSize = 150;
|
||||
var imageStyle = [styles.image, {width: imageSize, height: imageSize}];
|
||||
return (
|
||||
<Image
|
||||
source={asset.node.image}
|
||||
style={imageStyle}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
var ds = new ListViewDataSource({rowHasChanged: this._rowHasChanged});
|
||||
|
||||
return {
|
||||
assets: [],
|
||||
groupTypes: this.props.groupTypes,
|
||||
lastCursor: null,
|
||||
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 ListViewDataSource({rowHasChanged: this._rowHasChanged});
|
||||
this.state.dataSource = ds.cloneWithRows(
|
||||
groupByEveryN(this.state.assets, this.props.imagesPerRow)
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.fetch();
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
if (this.props.groupTypes !== nextProps.groupTypes) {
|
||||
this.fetch(true);
|
||||
}
|
||||
},
|
||||
|
||||
_fetch: function(clear) {
|
||||
if (clear) {
|
||||
this.setState(this.getInitialState(), this.fetch);
|
||||
return;
|
||||
}
|
||||
|
||||
var fetchParams = {
|
||||
first: this.props.batchSize,
|
||||
groupTypes: this.props.groupTypes,
|
||||
};
|
||||
if (this.state.lastCursor) {
|
||||
fetchParams.after = this.state.lastCursor;
|
||||
}
|
||||
|
||||
CameraRoll.getPhotos(fetchParams, this._appendAssets, logError);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (!this.state.loadingMore) {
|
||||
this.setState({loadingMore: true}, () => { this._fetch(clear); });
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<ListView
|
||||
renderRow={this._renderRow}
|
||||
renderFooter={this._renderFooterSpinner}
|
||||
onEndReached={this._onEndReached}
|
||||
style={styles.container}
|
||||
dataSource={this.state.dataSource}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
_rowHasChanged: function(r1, r2) {
|
||||
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, sectionID, rowID) {
|
||||
var images = rowData.map((image) => {
|
||||
if (image === null) {
|
||||
return null;
|
||||
}
|
||||
return this.props.renderImage(image);
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={styles.row}>
|
||||
{images}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
|
||||
_appendAssets: function(data) {
|
||||
var assets = data.edges;
|
||||
var newState = { 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({
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
flex: 1,
|
||||
},
|
||||
url: {
|
||||
fontSize: 9,
|
||||
marginBottom: 14,
|
||||
},
|
||||
image: {
|
||||
margin: 4,
|
||||
},
|
||||
info: {
|
||||
flex: 1,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = CameraRollView;
|
||||
@@ -36,6 +36,7 @@ var EXAMPLES = [
|
||||
require('./TabBarExample'),
|
||||
require('./SwitchExample'),
|
||||
require('./SliderExample'),
|
||||
require('./CameraRollExample.ios'),
|
||||
];
|
||||
|
||||
var UIExplorerList = React.createClass({
|
||||
|
||||
Reference in New Issue
Block a user