iOS开发React Native开发Android知识

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不会马上清空显示的内容,而是加载成功后才替换,所以在加载过程中依然显示旧图片。
解决:

  1. 从Image加载的角度不好解决,所以要让Image重新创建,就要从ListView下手,而ListView更新已存在的row只是刷新,不是重新创建
  2. react为组件提供了key属性,用于同级别的组件根据key的不同来优化渲染,原理就是如果key相同就刷新,key不同就重新创建
  3. 在ListView的renderRow的最外层component添加key属性,设置为当然数据的唯一id,就可以在更新时重新创建Image,(不可以设置为row的索引,没有任何对优化的帮助而且会造成不可预料的问题)
  4. 进一步优化,重新创建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"]
}
上一篇下一篇

猜你喜欢

热点阅读