React Native小技巧
2017-10-23 本文已影响174人
阳光下慵懒的驴
ListView 标签流式布局
contentContainerStyle={styles.listContainer}
listContainer:{
flexDirection:'row',
flexWrap:'wrap',
},
这种方式只能实现类似标签的高度相等,宽度不同的布局,不能实现高度不同,宽度相同的瀑布流布局
row的最外层需要设置确定的高度
ListView 瀑布流
row设置为绝对布局,计算位置
renderRow执行的次数比dataSource的数量少
如果出现renderRow执行的次数比dataSource的数量少的情况,
需要设置:
initialListSize={20} // 可以把值改为dataSource的length
如果不设置,renderRow只能执行前几条数据, 想显示其他数据, 只能通过改变任意state来实现
得到text的高度
<Text onLayout={(event)=>this._textOnLayout(event)} />
_textOnLayout(event){
console.log(event.nativeEvent.layout.height,'onLayout');
}
ListView从下向上排列
<ListView contentContainerStyle={styles.listViewContent}/>
listViewContent:{
flex:1,
//从下向上排列
justifyContent:'flex-end'
}
得到组件宽高
this.refs.row.measure(function(ox,oy,width,height,px,py){
cellHeight=height;
});
<View style={styles.row} ref="row"/>
row:{
flex:1,
backgroundColor:'#FFFFFF',
borderTopWidth:1/2,
borderBottomWidth:1/2,
borderColor:'#dddddd',
marginTop:10/2,
marginBottom:10/2
},
指定某个组件
var _listView: ListView;
<ListView ref={(listView)=>{_listView=listView;}}/>
版本更新
openAppStore: ()=> {
var url = '';
if (Platform.OS === 'ios') {
url = 'itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&id=1156814163';
} else {
url = 'http://a.app.qq.com/o/simple.jsp?pkgname=com.girtu.girtu'
}
Linking.openURL(url).catch(err => console.error('An error occurred', err));
},
checkoutUpdate: ()=> {
let setLaterUpdateTime = (time) => {
AsyncStorage.setItem('update_time', time);
}
let getLaterUpdateTime = () => {
return AsyncStorage.getItem('update_time')
}
// 点击了稍后更新, 保存当前时间
let laterUpdate = ()=> {
setLaterUpdateTime(new Date().toString())
}
// 点击立即下载只是跳转到商店,本地不做处理,如果没有更新,下次进入依然提醒
// 点击稍后下载,本地记录时间,10天后再次提醒
let showAlert = ()=> {
Alert.alert('有新版本发布, 是否更新', '', [
{text: '马上下载', onPress: ()=>module.exports.openAppStore()},
{text: '稍后更新', onPress: ()=>laterUpdate()}
])
}
// 计算时间差, 如果大于10天就显示alert, 否则什么都不做
let calculateDateDiff = (oldDate)=> {
oldDate = new Date(oldDate)
let newDate = new Date(); //结束时间
let differDate = newDate.getTime() - oldDate.getTime(); //时间差的毫秒数
let days = Math.floor(differDate / (24 * 3600 * 1000)); ////计算出相差天数
if(days >= 10) {
showAlert()
}
}
setTimeout(()=> {
// 假设获取到版本号后
let newVersion = '2.3.3';
let oldVersion = DeviceInfo.getVersion();
if (newVersion > oldVersion) {
getLaterUpdateTime()
.then((oldDate)=> {
// 如果有时间就计算时间差, 没有时间就直接显示
if (oldDate) {
calculateDateDiff(oldDate)
// calculateDateDiff(1489075200000)
} else {
showAlert()
}
})
.catch((e)=> {
showAlert()
})
}
}, 2000)
},
navigationBar颜色渐变
// 参数格式为#ffffff 或者 #ffffff00
function hexToRGBA(hex) {
var a = 1
if (hex.length == 9) {
a = parseInt(hex.substr(7, 2), 16) / parseInt('ff', 16)
}
let r = parseInt(hex.substr(1, 2), 16)
let g = parseInt(hex.substr(3, 2), 16)
let b = parseInt(hex.substr(5, 2), 16)
let rgba = `rgba(${r}, ${g}, ${b}, ${a})`
return {
string: rgba,
r,
g,
b,
a
}
}
updateProgress(progress, fromIndex, toIndex) {
var routes = this.props.navState.routeStack
var fromRoute = routes[fromIndex]
var toRoute = routes[toIndex]
let {navColor} = fromRoute
if (fromRoute.navColor != toRoute.navColor) {
let fromRGBA = utils.hexToRGBA(fromRoute.navColor)
let toRGBA = utils.hexToRGBA(toRoute.navColor)
const {r: toR, g: toG, b: toB, a: toA} = toRGBA
const {r: fromR, g: fromG, b: fromB, a: fromA} = fromRGBA
let minusR = toR - fromR
let minusG = toG - fromG
let minusB = toB - fromB
let minusA = toA - fromA
let r = toR - minusR * (1 - progress)
let g = toG - minusG * (1 - progress)
let b = toB - minusB * (1 - progress)
let a = toA - minusA * (1 - progress)
navColor = `rgba(${r}, ${g}, ${b}, ${a})`
this.setState({
progressStyle: {
...this.state.progressStyle,
backgroundColor: navColor,
}
})
}
this._nav && this._nav.updateProgress(progress, fromIndex, toIndex)
}
旋转rotate
let iwidth = util.size.width;
let iheight = iwidth / mediaInfo.width * mediaInfo.height
// 如果是旋转过的图片,重新计算
let rotate = ??; // 角度 字符串
if (rotate == '90' || rotate == '270') {
iheight = util.size.width
iwidth = iheight * (mediaInfo.width / mediaInfo.height)
let translateXY = (iwidth > iheight ? 1 : -1 ) * (Math.abs(iwidth - iheight) / 2)
translateXY *= (rotate == '90' ? 1 : -1 )
return (
<View style={{
position: 'absolute',
left: 0,
top: 0,
width: iwidth, // 如果90度或者270度,宽高需要反过来,因为是先旋转再设置宽高
height: iheight,
transform: [
{rotate: `${rotate}deg`},
{translateX: translateXY},
{translateY: translateXY}
]}}
/>
);
} else {
return (
<View style={{
position: 'absolute',
left: 0,
top: 0,
width: iwidth,
height: iheight,
transform: [
{rotate: `${rotate}deg`},
]
}]}
/>
)
}
子view上下拉伸
justifyContent: 'space-between',
alignSelf: 'stretch'
WebView自动获取高度
在html中监听高度的变化,把title设置为高度,当title变化时,会触发WebView的onNavigationStateChange
方法,获取到高度。
<WebView
{...this.props}
source={{html: `<!DOCTYPE html><html><body>${this.props.htmlBody}<script>window.onload=function(){window.location.hash = 1;document.title = document.body.clientHeight;}</script></body></html>`}}
javaScriptEnabled={true}
style={[{height: this.state.height}, this.props.style]}
scrollEnabled={false}
automaticallyAdjustContentInsets={true}
contentInset={{top:0,left:0}}
onNavigationStateChange={(info)=>{
if (info.title) {
this.setState({
height: parseInt(info.title) + 20
})
}
}}
/>
画三角
// 画三角。style:
triangle: {
width: 0,
height: 0,
borderStyle: 'solid',
borderWidth: 8,
marginTop: -8,
borderTopColor: 'transparent',//下箭头颜色
borderLeftColor: 'transparent',//右箭头颜色
borderBottomColor: Colors.BACKGROUND_GRAY,//上箭头颜色
borderRightColor: 'transparent'//左箭头颜色
},
iOS图片更新不及时显示新图片的解决办法
bug产生的原因:iOS的Image更换uri不会马上清空显示的内容,而是加载成功后才替换,所以在加载过程中依然显示旧图片。
解决:
- 从Image加载的角度不好解决,所以要让Image重新创建,就要从ListView下手,而ListView更新已存在的row只是刷新,不是重新创建
- react为组件提供了key属性,用于同级别的组件根据key的不同来优化渲染,原理就是如果key相同就刷新,key不同就重新创建
- 在ListView的renderRow的最外层component添加key属性,设置为当然数据的唯一id,就可以在更新时重新创建Image,(不可以设置为row的索引,没有任何对优化的帮助而且会造成不可预料的问题)
- 进一步优化,重新创建item会造成多余的开销,而现在只需要更新Image,所以renderRow的component去掉key属性,给Image添加key属性,设置为url,解决。
RN iOS图片缓存位置
APP路径/Library/Caches/[Bundle ID]/fsCachedData
引入装饰器
npm i --save-dev babel-plugin-transform-decorators-legacy
修改.babelrc
{
"presets": ["react-native"],
"plugins": ["transform-decorators-legacy"]
}