注意:我主要用的包管理工具是yarn(也可以用npm或者cnpm);这里只介绍第三方库的基本集成,属性和方法可以去参考文章和github查找学习。
个人意见:集成第三方库最好不要制定固定的版本,因为可能会和你的react native版本不相符,导致报错!!!
这篇文章主要记录一些 react-native-image-crop-picker 和 react-native-image-zoom-viewer 的基本用法....
前言:目前大多数app中图片展示是一个非常常见的功能,在实际开发中,上传图片,设置头像等功能更是屡见不鲜。而在react native的开发前提下,这些需求也变得越来越频繁;但是react native框架本身在拍照和图片选择这方面并没有很好的解决方法。而众多优秀的开源库却可以让我们实现非常好的效果并且使用也比较简单。如:react-native-image-crop-picker,该库实现了本地相册和照相机来采集图片,并且提供多选、图片裁剪等功能,支持iOS和Android两个平台,但需要分别配置。另外:react-native-image-picker这个库也不错,实现启动本地相册和照相机来采集图片,但是作者没有实现裁剪功能。
react-native-image-crop-picker
一、安装:
yarn add react-native-image-crop-picker(npm i react-native-image-crop-picker --save)
yarn add react-native-image-crop-picker@0.16.0 ==>> 我是指定安装的 0.16.0 版本
link:react-native link react-native-image-crop-picker ==>>自动配置react-native-image-crop-picker在环境中的一些修改(不是全部)
二、配置
android平台:
- android平台的Gradle版本必须大于2.2,例如React Native 0.44 创建项目,查看工程的build.gradle中默认gradle版本
- 在app下的build.gradle中添加useSupportLibrary,添加在android / defaultConfig / 节点下
===>>> vectorDrawables.useSupportLibrary = true
- AndroidManifest.xml配置文件,添加相机权限 ==>> 可以打开相机
===>>> <uses-permission android:name="android.permission.CAMERA"/>
三、页面中简单使用
import React, {Component} from "react";
import {
View,
Text,
Button,
} from 'react-native'
import ImagePicker from 'react-native-image-crop-picker';
export class PicScreen extends Component{
static navigationOptions = {
header: null, //去除页面中顶部的空白导航栏
};
constructor() {
super();
this.state = {
}
}
pic(){
// ImagePicker.openPicker({ //选择照片
// width: 300,
// height: 400,
// cropping: true,
// }).then(image => {
// console.log(' 图片路径:'+ image);
// });
ImagePicker.openCamera({ //启动相机拍照
width: 300,
height: 400,
cropping: false //是否打开剪裁
}).then(image => {
console.log(image);
});
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text style={{fontSize:24,color:'red'}}>图片选择</Text>
<View style={{marginTop:20}}>
<Button
title="选择图片"
onPress={() => this.pic()}
/>
</View>
</View>
)
}
}
参考博客:https://blog.csdn.net/u013718120/article/details/72781285
https://www.jianshu.com/p/8420b08062c7
github:https://github.com/ivpusic/react-native-image-crop-picker
react-native-image-zoom-viewer
前言:项目中经常需要点击一张图片或者一组图片来查看大图,react-native-image-zoom-viewer就是一个非常好用的第三方库。
一、安装:
yarn add react-native-image-zoom-viewer(npm i react-native-image-zoom-viewer --save)
参考博客:https://www.jianshu.com/p/3137f0e56d68
https://blog.csdn.net/sinat_17775997/article/details/74971315
github:https://github.com/magicwing/react-native-image-zoom-viewer
react-native-image-crop-picker 和 react-native-image-zoom-viewer综合使用:
代码(有些样式没有):
imageList.js ===>>> 组件主文件
import React, {Component} from "react";
import {
View,
Text,
// Button,
Image,
TouchableOpacity,
Dimensions,
StatusBar,
Animated,
Platform,
Modal,
} from 'react-native';
import {
Container,
Header,
Title,
Content,
Footer,
FooterTab,
Button,
Left,
Right,
Body,
Icon,
Form,
Item,
Picker,
Input,
Label,
Radio,
H1,
Thumbnail,
List,
ListItem,
// Text,
CheckBox
} from 'native-base';
import ImagePicker from 'react-native-image-crop-picker';
import R from 'ramda';
import {ImageBrowser} from "./imageBrowser";
import {SquareView} from "./squareView";
import {config} from "../../config";
import {_noPadding,_noMargin} from "../common";
export class ImageList extends Component {
constructor() {
super();
this.state = {
show: false,
index: 0,
shareModalVisible: false,
modalAnimatedValue: new Animated.Value(0),
};
}
onAdd(){
this.setState({shareModalVisible: true,});
Animated.timing(this.state.modalAnimatedValue, {
toValue: 1,
duration: 200
}).start();
}
renderItem(its, index) {
const {edit, onAdd, onDel} = this.props;
const blankButton = (
<SquareView layout='row' style={{flex: 1, margin: 2, flexDirection: 'column',}}>
</SquareView>
);
const addButton = (
<SquareView layout='row' style={{flex: 1, margin: 2, flexDirection: 'column',}}>
<Button transparent
onPress={this.onAdd.bind(this)}
style={{..._noPadding, ..._noMargin, flex: 1, justifyContent: 'center', alignSelf: 'stretch', borderStyle: 'dashed', borderWidth: 1, borderColor: '#BDBEBF',}}>
<Icon name='add' style={{color: '#BDBEBF', fontSize: config.FONT_SIZE_CONTENT_TEXT * 3,}}/>
</Button>
</SquareView>
);
const delButton = index => {
return edit ? (
<Button transparent
onPress={() => onDel(index)}
style={{..._noPadding, ..._noMargin, position: 'absolute', padding: 9, top: 0, right: -10,}}>
<Icon name="close" style={{alignSelf: 'flex-start', color: '#e1e1e1', fontSize: config.FONT_SIZE_CONTENT_TEXT * 1.5,}}/>
</Button>
) : null;
};
const imgButtn = (source, index) => {
return (
<SquareView layout='row' style={{flex: 1, margin: 2, flexDirection: 'column',}}>
<Button transparent
onPress={() => this.onBrowserOpen(index)}
style={{..._noPadding, ..._noMargin, flex: 1, flexDirection: 'row', alignSelf: 'stretch',}}>
<Image resizeMode='cover' source={source} style={{flex: 1,alignSelf: 'stretch'}}/>
</Button>
{delButton(index)}
</SquareView>
);
};
const item = its[index];
if (item) {
const {key} = item;
switch (key) {
case 'add':
return addButton;
default:
return imgButtn(item, index);
}
}
return blankButton;
}
render(){
const {edit, items} = this.props;
const {show, index} = this.state;
let its = items;
// 如果是编辑状态&&在最大个数内,先补上添加按钮
if (edit && items.length < 3 * 2) {
its = [...items, {key: 'add',}];
}
let vs = [];
for (let i = 0; i < its.length; i += 3) {
vs = [...vs, (
<View key={i} style={{flexDirection: 'row'}}>
{this.renderItem(its, i)}
{this.renderItem(its, i + 1)}
{this.renderItem(its, i + 2)}
</View>
)];
}
return (
<View style={{flex:1, margin: 8, alignItems: 'center', justifyContent: 'center',}}>
{vs}
<ImageBrowser ref={browser => this.browser = browser}
show={show}
index={index}
onClose={() => this.onBrowserClose()}
images={items.map(item => ({...item, url: item.uri}))}
saveToLocalByLongPress={false}/>
<Modal animationType="fade"
visible={this.state.shareModalVisible}
transparent={true}
onRequestClose={()=>{}}
>
{this._renderShareView()}
</Modal>
</View>
);
}
onBrowserOpen(index) {
this.setState({show: true, index});
}
onBrowserClose() {
this.setState({show: false});
}
onMenu(type){
switch (type) {
case 'camera':
ImagePicker.openCamera({
// width: 300,
// height: 400,
// compressImageMaxWidth: 1440,
// compressImageMaxHeight: 2560,
// compressImageQuality: 0.8,
compressImageMaxWidth:1024,
compressImageMaxHeight:1024,
cropping: false,
}).then(this.onImage.bind(this));
break;
case 'gallery':
ImagePicker.openPicker({
// width: 300,
// height: 400,
compressImageMaxWidth:1024,
compressImageMaxHeight:1024,
cropping: false,
}).then(this.onImage.bind(this));
break;
}
}
onImage(image){
this.setState({ shareModalVisible: false });
this.state.modalAnimatedValue.setValue(0);
const {onAdd} = this.props;
if (R.is(Function)(onAdd)) {
onAdd(image);
}
}
_renderShareView() {
const {width, height} = Dimensions.get('window');
const itemWidth = width;//(width - 15 * 2) / 5;
const itemHeight = 44;//(height * 0.45 - 50 - 48) / 2;
const logoWidth = itemWidth * 0.6;
const statusHeight = Platform.select({ios: 0, android: StatusBar.currentHeight});
return (
<View style={{width: width, height: height,}}>
<TouchableOpacity
activeOpacity={1}
style={{width: width, flex: 5.5}}
onPress={() => {
this.setState({shareModalVisible: false})
this.state.modalAnimatedValue.setValue(0)
}}
>
<Animated.View
style={{backgroundColor: 'rgba(0, 0, 0, 0.65)', width: width, flex: 1, opacity: this.state.modalAnimatedValue}}/>
</TouchableOpacity>
<Animated.View
style={{
backgroundColor: '#444',
width: width,
height: height * 0.4,
paddingHorizontal: 15,
position: 'absolute',
top: this.state.modalAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [height, height * 0.6 - statusHeight]
})
}}
>
<View
style={{flexDirection: 'row', justifyContent: 'center', alignItems: 'center', height: 50, borderBottomWidth: 1, borderColor: '#555'}}>
<Text style={{color: '#bbb', fontSize: 14, marginLeft: 5}}>添加照片</Text>
</View>
<View style={{flexDirection: 'column', flex: 1, paddingVertical: 19,}}>
{[{title: '拍照', type: 'camera',}, {title: '从相册选择', type: 'gallery',}].map(menu => {
return (
<TouchableOpacity
key={`imagelist-${menu.type}`}
activeOpacity={0.75}
style={{flex: 1, height: itemHeight, justifyContent: 'center', alignItems: 'center'}}
onPress={() => this.onMenu(menu.type)}
>
{/*<Image style={{width: logoWidth, height: logoWidth}} source={channel.logo}/>*/}
<Text style={{fontSize: 14, color: '#fff',}}>{menu.title}</Text>
</TouchableOpacity>
)
})}
</View>
<TouchableOpacity
activeOpacity={0.75}
style={{width: width, marginLeft: -15, borderTopWidth: 1, borderColor: '#777', height: 48, justifyContent: 'center', alignItems: 'center'}}
onPress={() => {
this.setState({shareModalVisible: false});
this.state.modalAnimatedValue.setValue(0)
}}
>
<Text style={{fontSize: 14, color: '#ccc',}}>取消</Text>
</TouchableOpacity>
</Animated.View>
</View>
)
}
}
squareView.js ===>>> 针对主文件封装的类View组件
/**
* Created by sysssc on 2017/5/31.
*/
import React, {Component} from "react";
import {
Alert,
View,
Text,
TextInput,
// Button,
TouchableOpacity,
Switch,
} from "react-native";
import {
Container,
Header,
Title,
Content,
Footer,
FooterTab,
Button,
Left,
Right,
Body,
Icon,
Form,
Item,
Input,
Label,
H1,
ListItem,
// Text,
CheckBox
} from 'native-base';
export class SquareView extends Component {
constructor() {
super();
this.state = {
width: 0,
height: 0,
direction: 'row' // 'column' and 'row'
};
}
render() {
const square = (
<View
{...this.props}
style={
[this.props.style,
{width: this.state.width, height: this.state.height}]
}
onLayout={event => {
const {width, height} = event.nativeEvent.layout;
switch (this.props.layout) {
case 'column':
if (this.state.height !== height) {
this.setState({width: height, height: height});
}
break;
case 'row':
if (this.state.width !== width) {
this.setState({width: width, height: width});
}
break;
}
}}>
{this.props.children}
</View>
);
return square;
}
}
imageBrowser.js ===>>> 点击图片放大组件
/**
* Created by sysssc on 2017/6/7.
*/
import React, {Component} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Modal
} from 'react-native';
import {
Container,
Header,
Title,
Content,
Footer,
FooterTab,
Button,
Left,
Right,
Body,
Icon,
Form,
Item,
Picker,
Input,
Label,
Radio,
H1,
Thumbnail,
List,
ListItem,
// Text,
CheckBox
} from 'native-base';
import ImageViewer from 'react-native-image-zoom-viewer';
export class ImageBrowser extends Component {
render() {
const {show, onClose, images, index, saveToLocalByLongPress} = this.props;
return (
<Modal visible={show} transparent={true} animationType={'slide'} onRequestClose={()=>{}}>
<ImageViewer imageUrls={images} index={index} saveToLocalByLongPress={!!saveToLocalByLongPress}/>
<Button transparent style={styles.back} onPress={onClose}>
<Icon name='close' style={{color: '#fffa', fontSize: 38,}}/>
</Button>
</Modal>
)
}
}
const styles = {
back: {
position: 'absolute',
borderRadius: 5,
padding: 40,
top: 28,
right: 0,
},
};
效果:
文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出
对博客文章的参考,若原文章博主介意,请联系删除!请原谅