不积跬步无以至千里,不积小流无以成将海!
VIN扫码,传递的参数值被覆盖
- 解决方法:
在页面关闭前,将监听移除
DeviceEventEmitter.removeListener('SmartVisionResult',this.smartVisionResult);
DeviceEventEmitter.removeListener('EventReminder', this.smartVisionResultIos);
react-native-scrollable-tab-view使用问题
- 问题:设计需求,在tab的最右侧放置一个按钮
react-native-scrollable-tab-view 默认占据一整行,在右侧要放置一个按钮,我最开始的做法是在eact-native-scrollable-tab-view的最后一个放置一个空的标签,将按钮浮动在ScrollableTabView的右顶部,但是这个方法会导致滑动到最后一个位置时,此tab页面为空白页。类似以下布局:
tab内容区域
- 解决方案:
下载以下链接的JS文件,并修改成自己要的需求
初学者易入的坑
以下是自身从入门到实战,所遇到的坑的一个记录:
- 布局的适配
我们公司的设计是以iPhone6的尺寸设计的,例如有一个内容区域,设计稿是351pt的宽度,那么在代码中,可通过减去内容距离两遍的宽度,获取内容的宽度,例:width: (width-12-12)。如果直接写成width: 351,在小屏幕的设备中会有问题。
- Text的使用
文字需要放在Text标签中,否则会报错,Text的样式也要谨慎书写,不然在ios中样式与Android的不一致
<Text style={style.textStyle}>Text左边有绿色边框</Text>
textStyle: {
color: '#999';
fontSize: 14,
borderLeftWidth: 5,
borderLeftColor: 'green'
},
以上代码,在Android中,左边会有绿色的边框,但是在iOS中,绿色边框就消失了。 解决方法:在Text标签外面在包一层View标签,来写绿色边框的样式。
- Text多行显示(个人项目中,大于等于3行,就会有此问题),在某些手机(例:小米)中,最后一行会有显示不全的问题
通过网上查找和技术群里请教,有以下几种解决方法:
1、/n:在末尾加 ‘/n’,通过换行解决此问题。
2、paddingVertical: 给Text标签的样式设置paddingVertical属性
React-native 搜索高亮
- 代码示例
//搜索高亮--js
_searchHightColor(searchText,originText){
let reg1 = new RegExp(searchText, "g");
return (
<Text>
{
(''+originText+'').replace(reg1,' '+searchText+' ').split(' ').map((item,index)=>{ //将 ‘搜索的关键字’ 替换成,空格 + 关键字 + 空格 的字符串,在使用 ‘空格’ 将字符串分割成数组形式
if(reg1.test(item) && searchText!=''){
return (
<Text key={index} style={[styles.hightTextColor]}>{ item }</Text>
)
}else{
return (
<Text>{ item }</Text>
)
}
})
}
</Text>
);
}
//搜索高亮--页面
<Text>{this._searchHightColor(this.state.key,data.mobile)}</Text>
- 思路
将 ‘搜索的关键字’ 替换成,空格 + 关键字 + 空格 的字符串,在使用 ‘空格’ 将字符串分割成数组形式。。
备注:本项目中,使用 ‘空格’ 作为区分即可,大家可根据自己的项目需求进行分割。。如果有更好的方法,欢迎提供。
WebView的使用
-
项目中,由于配置的问题,导致使用
import { WebView } from 'react-native-webview'方式引入,一片红,运行会报错,最终使用以下形式引入WebView组件:import { WebView } from 'react-native'; -
使用方法:
//例: const BaseScript = ` const meta = document.createElement('meta'); meta.setAttribute('content', 'width=device-width,initial-scale=1.0, maximum-scale=1.0, user-scalable=0'); meta.setAttribute('name', 'viewport'); document.getElementsByTagName('head')[0].appendChild(meta); (function () { var height = null; function changeHeight() { if (document.body.scrollHeight != height) { height = document.body.scrollHeight; if (window.postMessage) { window.postMessage(JSON.stringify({ type: 'setHeight', height: height, })) } } } setTimeout(changeHeight, 300); } ()) ` export default class Page extends BasePage { constructor(props) { super(props); this.state = { content: '<p style='font-size:12px;'>哈哈哈哈哈</p>', //WebView要显示的内容【html标签字符串或地址】 }; } /** * web端发送过来的交互消息 */ onMessage(event) { try { const action = JSON.parse(event.nativeEvent.data) if (action.type === 'setHeight' && action.height > 0) { this.setState({ WebViewHeight: action.height }) } } catch (error) { // pass } } renderPage(){ return ( <View style={[styles.comContainer]}> <ScrollView style={[styles.serviceHelpScroll]}> <WebView style={{ marginBottom: 10, height: this.state.WebViewHeight, width: width }} injectedJavaScript={BaseScript} scalesPageToFit={false} scrollEnabled={false} // source={{ uri: global.Http.host + '/' + this.state.content }} //.html地址形式 originWhitelist={['*']} source={{ html: this.state.content,baseUrl:'' }} //即使没有baseUrl,也要加上这个属性,写上空串,解决中文乱码的问题! html标签形式 onMessage={this.onMessage.bind(this)} /> </ScrollView> </View> ) } }备注:直接使用 html 标签的字符串,若含有中文,会出现中文乱码的问题。。解决方法:
source={{ html: this.state.content,baseUrl:'' }}
baseUrl:''一定要写,就可以解决此问题。。
适配 ‘刘海屏’
//最外围的容器
commonWrap: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: global.gDevice.isIPhoneX ? 34 : 0, //重要
backgroundColor: '#f6f6f6',
flex: 1,
},
//底部tab栏
foot: {
width: width,
height: 49,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#FFFFFF',
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: '#EEEEEE',
},
//例:
<View style={[styles.commonWrap]}>
<ScrollView>
//页面内容
</ScrollView>
<View style={[styles.foot]}>
//底部tab栏
</View>
</View>
备注:
global.gDevice.isIPhoneX的来源。global.gDevice.isIPhoneX是全局变量。可以在设置全局变量的文件中,定义需要的变量。
const OS = Platform.OS;
const ios = (OS == 'ios');
const android = (OS == 'android');
const isIPhoneX = (ios && height == 812 && width == 375);
global.gDevice = {
ios: ios,
android: android,
isIPhoneX: isIPhoneX,
}
TextInput 表单在IOS的问题
- 输入框文字错位的问题:
解决方法:不能设置 height 和 lineheight ,否则,在IOS下会出现 输入值偏下(错位)的问题。
- Android和IOS输入框兼容问题:
解决方法:使用padding:0,使IOS和Android样式保持一致。
- IOS输入时,首个文字被遮挡的问题:
解决方法:给TextInput添加 paddingLeft:5 的属性值。
React-native Text首行缩进
解决方法的参考链接:blog.csdn.net/r122555/art…
项目启动时,提示找不到某些包
- 场景重现
例如:npm install --save react-native-webview
备注:react-native-webview会报错。问题是此组件没有安装。react-native link react-native-webview 也无效。 目前的解决方法: 使用 React-native 自带的 WebView 组件
复制
//引入
import {
Clipboard
} from 'react-native';
//使用
<TouchableOpacity onPress={()=>{
Clipboard.setString(this.state.authCode);
this.showInfo('复制成功')
}} style={[comStyles.centerCopyBtn]}>
<Text>复制</Text>
</TouchableOpacity>
备注:可以查一下 Clipboard 的使用
拨号
//引入
import {
Linking
} from 'react-native';
//使用
//js
/拨打电话
linking = (tel) => {
if(tel && tel.indexOf('tel:')<0){
tel='tel:' + tel;
}
Linking.canOpenURL(tel).then(supported => {
if (!supported) {
console.log('Can\'t handle url: ' + tel);
} else {
return Linking.openURL(tel);
}
}).catch(err => console.error('An error occurred', err));
}
//JSX
<TouchableOpacity style={{flex: 1,alignSelf: 'center',}} onPress={() => { this.linking('tel:' + 100100100) }}>
<Text selectable={true} dataDetectorType="phoneNumber">400-9933-139</Text>
</TouchableOpacity>
备注:
this.linking('tel:' + 100100100)中 tel 后面必须跟数字,不能包含非数字的字符
20200901更新
小米手机 边框线 StyleSheet.hairlineWidth 不显示的问题
解决方法:
import {
PixelRatio,
} from 'react-native';
borderBottomWidth:PixelRatio.get() >= 3 ? 0.5 : 1
react-native-swipe-list-view 组件 左滑删除的问题
- 问题:高度不一致时,删除后,会保留删除那个的高度,并把高度赋值给下一个,导致样式错乱的问题
- 解决方法:加上这个属性
recalculateHiddenLayout={true}缺点:消耗性能
例:
<SwipeRow ref={'packRowsItem_'+item.id} recalculateHiddenLayout={true} rightOpenValue={-64} stopRightSwipe={-64} disableRightSwipe={true} closeOnRowPress={true}></SwipeRow>
react-native-sectioned-multi-select 下拉框组件,修改成自己想要的样式
- 引入:
import SectionedMultiSelect from 'react-native-sectioned-multi-select';
- 样式修改:可参考以下
//下拉框 样式自定义
<SectionedMultiSelect
items={this.props.shopList}
...
//自己可修改 start
headerComponent={
<View style={{flexDirection:'row',alignItems:'center',justifyContent:'center',marginTop:15}}>
<Text style={{color: '#323232',fontSize: 16,fontWeight:'bold'}}>调入门店</Text>
</View>
}
cancelIconComponent={
<Text style={{color: '#777777',fontSize: 13,fontWeight:'bold'}}>取消</Text>
}
//下拉框右侧图标
selectToggleIconComponent={
<Image style={style.cMultiToggleIcon} source={require('../common/components/img/btn_erp_list_more.png')}/>
}
//搜索输入图标
searchIconComponent={
<Image style={style.cMultiSearchIcon} source={require('../common/components/img/btn_erp_search.png')}/>
}
//选中图标
selectedIconComponent={
<Image style={{width:15,height:15}} source={require('../../common/components/img/customer/btn_erp_list_s.png')}/>
}
//未选中图标
unselectedIconComponent={
<Image style={{width:15,height:15}} source={require('../../common/components/img/customer/btn_erp_list_nor.png')}/>
}
styles={{
//显示的input框的样式 start
selectToggleText: {
color: ((this.props.billDate && this.props.billDate.toShop && this.props.billDate.toShop.name)||this.state.toShopNames)?'#202020':'#999999',
fontSize: 12,
textAlign: 'left',
},
selectToggle:{
height: 25,
flexDirection: 'row',
justifyContent: 'flex-start',
},
//显示的input框的样式 end
//遮罩
backdrop: {
justifyContent:'center',
alignItems:'center'
},
//白色内容区域
container: {
maxHeight: (height-200),
width: width-105,
alignSelf:'center'
},
//搜索框-bar
searchBar: {
backgroundColor: '#F5F5F5',
width: width-131,
alignSelf:'center',
// height: 25,
borderRadius: 5,
padding: 0,
paddingTop: 0,
paddingBottom: 0,
paddingLeft: 0,
paddingRight: 0,
marginTop: 15,
marginBottom: 5,
flexDirection: 'row',
justifyContent:'center'
},
//搜索框-icon
center: {
marginLeft: -10,
flexDirection: 'row',
justifyContent:'center',
paddingRight: 0,
paddingLeft: 0,
alignItems:'center',
},
//搜索框-input
searchTextInput: {
// backgroundColor: 'yellow',
flex: 1,
textAlign:'left',
margin: 0,
padding: 0,
paddingRight: 0,
paddingTop:0,
paddingBottom: 0,
height: 25,
marginRight: 10,
marginLeft: 0,
textAlignVertical:'center',
fontSize: 12,
marginLeft: -10
},
//分割线
separator: {
backgroundColor: '#fff'
},
item: {
height: 34,
width: width-145,
alignSelf:'center',
},
itemText: {
color: '#777777',
fontSize: 12,
fontWeight:'normal'
},
selectedItemText: {
color: '#202020',
fontSize: 12,
fontWeight:'normal'
},
button: {
width: (width-155)/2,
height: 38,
borderRadius: 19,
justifyContent:'center',
alignItems:'center',
backgroundColor: '#FD9F01',
marginRight: 20,
marginTop: 20,
marginBottom: 15
},
confirmText: {
color: '#FFFFFF',
fontSize: 13,
},
//取消按钮
cancelButton: {
width: (width-155)/2,
height: 38,
borderRadius: 19,
backgroundColor: '#fff',
justifyContent:'center',
alignItems:'center',
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#CFCFCF',
marginLeft: 20,
marginRight: 10,
marginTop: 20,
marginBottom: 15
},
itemIconStyle: {
backgroundColor: 'pink'
},
}}
//自己可修改 end
/>
备注:备注:具体请参考 github 的API文档
需要修改下以下两个文件(原因:加了“取消”按钮)
机型:Redmi K30,由于刘海屏问题,导致顶部按钮无法点
- 图片
备注:由于公司没有此机型的测试机,此图来自于客户手机,图不清晰。此图红色标注部分是按钮
- 解决方法
import { Dimensions, Platform, StatusBar } from 'react-native';
const statusBarHeight = (ios ? (isIPhoneX ? 44 : 20) : StatusBar.currentHeight);
<View style={[{ width: width, height: statusBarHeight) }]}></View>
<View style={[{
width: width,
height: 44,
backgroundColor: this.props.navBarColor || '#fff',//背景色,默认白色
flexDirection: 'row',//横向排
justifyContent: 'space-between',//主轴对齐方式
alignItems: 'center',//次轴对齐方式(上下居中)
borderBottomWidth: this.props.borderBottomWidth || 0,//是否有下边框
borderColor: this.props.borderColor || '#a3a3a3',
}]}>
...
</View>
后续项目中遇到react-native相关的问题和知识点都会更新至此文!若有错误,欢迎指出!