0.数据存储
https://github.com/sunnylqm/react-native-storage
1.图片多选、裁剪
https://github.com/ivpusic/react-native-image-crop-picker
注意:如果你不是用cocoapad导入的,可以打包,但是导出会报错:Failed to verify bitcode in......
需要在project-build settings 搜索bitcode,把yes改为no
Alert.alert('请选择', '拍照方式', [{
text: '相机', onPress: () => {
this.getPhotoFromCameraOGallary(true);
}
},{
text: '相册', onPress: () => {
this.getPhotoFromCameraOGallary(false);
}
},{
text: '取消', onPress: () => {
//this.getPhotoFromCameraOGallary(true);
}
}], {cancelable: false});
//分别从相册和相机选择
getPhotoFromCameraOGallary(isCamera) {
console.log("isCamera"+isCamera);
if (isCamera) {
console.log('111');
ImagePicker1.openCamera({
width: 300,
height: 400,
cropping: false,
compressImageQuality: 0.8,
}).then(image2 => {
console.log(image2.path);
var images = this.state.images;
images.pop();//移除最后一项
var image = new ImageBean();
image.isAdd = false;
image.uri = image2.path;
images.push(image);
var image1 = new ImageBean();
image1.isAdd = true;
images.push(image1);
this.setState((prevState) => ({images: images}));
});
} else {
ImagePicker1.openPicker({
compressImageQuality: 0.8,
multiple: true,
waitAnimationEnd: false,
includeExif: true,
forceJpg: true,
}).then(images2 => {
console.log(images2);
var images = this.state.images;
images.pop();//移除最后一项
for (let i = 0; i < images2.length; i++) {
var image = new ImageBean();
image.isAdd = false;
image.uri = images2[i].path;
images.push(image);
console.log('图片的地址是' + images2[i].path);
}
var image1 = new ImageBean();
image1.isAdd = true;
images.push(image1);
this.setState((prevState) => ({images: images}));
});
}
}
2.图片单选
https://github.com/react-community/react-native-image-picker
3.图片浏览
https://github.com/ascoders/react-native-image-viewer
实际使用(GitHub附带的有内存泄露):
//https://github.com/ascoders/react-native-image-viewer
import React, {PureComponent, Component} from 'react'
import {
Text,
TouchableOpacity,
View, Modal, Navigator
} from 'react-native';
import ImageViewer from 'react-native-image-zoom-viewer';
const Dimensions = require('Dimensions'); //必须要写这一行,否则报错,无法找到这个变量
const ScreenWidth = Dimensions.get('window').width;
const ScreenHeight = Dimensions.get('window').height;
let images1 = [{
url: "http://192.168.1.199:8013/upload/images/shgz/6283e29d-adca-4ce8-98c4-e723a3b00ad9.jpg",
},
{url: "http://192.168.1.199:8013/upload/images/shgz/6283e29d-adca-4ce8-98c4-e723a3b00ad9.jpg"}
];
class Image {
url;
}
export default class ShowImagesActivity extends Component {
//
// state = {
//
// modalVisible: true,
//
//
// };
constructor(props) {
super(props);
//type表示需要获取的工单类型:草稿逾期等等
this.state = {
showImages: [],
index: 0,
}
}
componentWillMount() {
let images = [];
let needShowUri = this.props.navigation.state.params.clickUri;
for (let i = 0; i < this.props.navigation.state.params.data.length; i++) {
let image = new Image();
image.url = this.props.navigation.state.params.data[i];
if (this.props.navigation.state.params.data[i] == needShowUri) {
this.setState((prevState) => ({index: i}), () => {
});
}
images.push(image);
}
// images1 = images
this.setState((prevState) => ({showImages: images}), () => {
console.log("传递过来的数据" + JSON.stringify(this.state.showImages));
});
}
render() {
return (
<View style={{flex: 1}}>
<ImageViewer
loadingRender={() => {
return (<Text style={{color: 'red'}}>拼命加载中....</Text>)
}} onClick={() => {
this.props.navigation.goBack();
}} imageUrls={this.state.showImages} index={this.state.index}/>
</View>
)
}
}
4.二维码扫描
https://blog.csdn.net/shb2058/article/details/80663122
5.日期选择器
https://github.com/beefe/react-native-picker
//时间选择器
_showTimePicker(isStart) {
let years = [],
months = [],
days = [],
hours = [],
minutes = [];
for (let i = 0; i < 10; i++) {
years.push(i + 2018);
}
for (let i = 1; i < 13; i++) {
months.push(i);
}
for (let i = 1; i < 32; i++) {
days.push(i);
}
for (let i = 1; i < 60; i++) {
minutes.push(i);
}
for (let i = 1; i < 24; i++) {
hours.push(i);
}
// let pickerData = [years, months, days, ['am', 'pm'], hours, minutes];
let pickerData = [years, months, days, hours, minutes];
let date = new Date();
let selectedValue = [
date.getFullYear(),
date.getMonth() + 1,
date.getDate(),
date.getHours(),
date.getMinutes()
];
Picker.init({
pickerConfirmBtnText: '确认',
pickerCancelBtnText: '取消',
pickerData,
selectedValue,
pickerTitleText: '选择时间',
wheelFlex: [2, 1, 1, 1, 1],
onPickerConfirm: pickedValue => {
console.log('area', pickedValue);
if (isStart) {
//
this.setState((prevState) => ({startTime: pickedValue[0] + '-' +this.changeNum(pickedValue[1]) + '-' + this.changeNum(pickedValue[2]) + ' ' + this.changeNum(pickedValue[3]) + ':' + this.changeNum(pickedValue[4])}));
// this.setState((prevState) => ({startTime: pickedValue[0] + '-' + pickedValue[1] + '-' + pickedValue[2] + ' ' + pickedValue[3] + ':' + pickedValue[4]}));
} else {
//结束时间必须必当前大
let date = new Date();
if (date.getMonth() + 1 > pickedValue[1]) {
Alert.alert('请选择正确的结束时间');
return;
}else {
if (date.getDate() > pickedValue[2]) {
Alert.alert('请选择正确的结束时间');
return;
}else {
if (date.getHours() > pickedValue[3]) {
Alert.alert('请选择正确的结束时间');
return;
}else {
if (date.getMinutes() > pickedValue[4]) {
Alert.alert('请选择正确的结束时间');
return;
}
}
}
}
this.setState((prevState) => ({stopTime: pickedValue[0] + '-' + this.changeNum(pickedValue[1])+ '-' + this.changeNum(pickedValue[2]) + ' ' + this.changeNum(pickedValue[3]) + ':' + this.changeNum(pickedValue[4])}));
}
},
onPickerCancel: pickedValue => {
console.log('area', pickedValue);
},
onPickerSelect: pickedValue => {
let targetValue = [...pickedValue];
if (parseInt(targetValue[1]) === 2) {
if (targetValue[0] % 4 === 0 && targetValue[2] > 29) {
targetValue[2] = 29;
}
else if (targetValue[0] % 4 !== 0 && targetValue[2] > 28) {
targetValue[2] = 28;
}
}
else if (targetValue[1] in {4: 1, 6: 1, 9: 1, 11: 1} && targetValue[2] > 30) {
targetValue[2] = 30;
}
// forbidden some value such as some 2.29, 4.31, 6.31...
if (JSON.stringify(targetValue) !== JSON.stringify(pickedValue)) {
// android will return String all the time,but we put Number into picker at first
// so we need to convert them to Number again
targetValue.map((v, k) => {
if (k !== 3) {
targetValue[k] = parseInt(v);
}
});
Picker.select(targetValue);
pickedValue = targetValue;
}
}
});
Picker.show();
}
6.支持中文
import React, {Component} from 'react';
import {Platform, TextInput, View} from 'react-native';
import PropTypes from 'prop-types';
export default class ChatInputView extends Component {
state={
fakeValue:this.props.value,//pure display here
refresh:false,//right clear
hadDefaultValue:true,
}
//无法通过state来设置textinput的显示,需做特殊处理
//设置有默认值==这是第一种手动设置textinput内容的方法
setHadDefaultVale(){
this.setState({hadDefaultValue:true});
}
componentDidUpdate(prevProps){//right clear
if(this.state.hadDefaultValue){
this.setState({hadDefaultValue:false},()=>{
this.setState({fakeValue:this.props.value, refresh:true}, ()=>this.setState({refresh: false}, ()=>this.input.blur()));//render null make blur perhaps, so do focus.
});
}else {
if(prevProps.value!==this.props.value&&this.props.value===''&&Platform.OS==='ios'){
this.setState({fakeValue:'', refresh:true}, ()=>this.setState({refresh: false}, ()=>this.input.focus()));//render null make blur perhaps, so do focus.
}
}
}
focus=()=>{
this.input.focus();
}
blur=()=>{
this.input.blur();
}
clear=()=>{
this.input.clear();
}
//设置有默认值==这是第二种手动设置textinput内容的方法
setFakeValue=fakeValue=>this.setState({fakeValue});//when parent setState({input}), call this too.
render(){
if(this.state.refresh){//right clear
return null;
}
return(
<TextInput
{...this.props}
ref={ref=>this.input=ref}
value={Platform.OS==='ios'?this.state.fakeValue:this.props.value}//only ios need this.
/>
);
}
// static propTypes = {
// ...View.propTypes,
// hadvalue: PropTypes.bool.isRequired,
// choosePersonFun: PropTypes.func,
// }
//
// constructor(props) {
// super(props);
// this.state = {hadvalue: false}
// }
//
// shouldComponentUpdate(nextProps) {
// console.log('shouldComponentUpdate前' + this.props.value + '后' + nextProps.value);
// if (nextProps.value.indexOf('@') != -1) {
// console.log('需要更新的数据中包含@');
// if (nextProps.value.lastIndexOf('@') === nextProps.value.length - 1) {
// console.log('新输入了@符号');
// try {
// this.props.choosePersonFun();
// // nextProps.value = '';
// }
// catch (e) {
// console.log(e);
// }
//
// // return false;
// } else {
// console.log('不是新输入的@' + nextProps.value);
// }
// }
// if (this.props.hadvalue) {
// this.props.hadvalue = false;
// //如果有初始值,则直接返回true,否则就去判断
// return true;
// } else {
// // console.log("现在输入的"+nextProps.value+"本来的value"+this.props.value);
// return Platform.OS !== 'ios'
// || (this.props.value === nextProps.value && (nextProps.defaultValue == undefined || nextProps.defaultValue == ''))
// || (this.props.defaultValue === nextProps.defaultValue && (nextProps.value == undefined || nextProps.value == ''));
// }
// }
//
// hadVlaue() {
// this.setState((prevState) => ({hadvalue: true}));
//
// }
//
// render() {
// return <TextInput {...this.props} />;
// }
}
这种支持中文在页面上没问题,但是当在modal里面会出现输入第一个字符后会自动关闭键盘失去焦点,点击第二次才能继续使用,解决如下:
<TextInput
multiline={true}
onEndEditing={(evt)=>{
if (Platform.OS === 'android') {
}else {
console.log("evt"+JSON.stringify(evt.nativeEvent));
let {text}=evt.nativeEvent;
console.log('提交工单结束解析出来的文字'+text);
this.setState((prevState) => ({resultRemark: text }))
}
}}
onChangeText={(text) => {
if (Platform.OS === 'android') {
this.setState((prevState) => ({resultRemark: text}))
}
}}
value={this.state.resultRemark} editable={true}
placeholder={'请输入备注'}
underlineColorAndroid='transparent' style={{
fontSize: 14,
marginLeft: 0.1 * ScreenWidth,
width: 0.7 * ScreenWidth,
height: 0.25 * ScreenHeight,
backgroundColor: 'white'
}}
/>