【React Native】進階指南之一(特定平臺、圖片加載、動畫使用)

1、特定平臺代碼

  React Native提供了兩種方法來區分平臺:react

  • 使用Platform模塊;
  • 使用特定平臺擴展名;

  一、Platform模塊

  React Native提供了一個檢測當前運行平臺的模塊;Platform適用於對一小部分代碼須要按照平臺定製的狀況;android

import { Platform, StyleSheet } from "react-native";

const styles = StyleSheet.create({
  height: Platform.OS === "ios" ? 200 : 100
});

  Platform.OS 在iOS上會返回iOS,而在安卓設備或模擬器上則返回android;還要一個實用的方法是Platform.select()ios

import { Platform, StyleSheet } from "react-native";

const styles = StyleSheet.create({
  container: {
    flex: 1,
    ...Platform.select({
      ios: {
        backgroundColor: "red"
      },
      android: {
        backgroundColor: "blue"
      }
    })
  }
});

  1.1 檢測Android版本

  在Android上,Version屬性是一個數字,標識Andorid的api level;git

import { Platform } from "react-native";

if (Platform.Version === 25) {
  console.log("Running on Nougat!");
}

  1.2 檢測iOS版本

  在iOS上,Version屬性是-[UIDevice systemVersion]的返回值,具體形式爲一個表示當前系統版本的字符串。如:「10.3」github

import { Platform } from "react-native";

const majorVersionIOS = parseInt(Platform.Version, 10);
if (majorVersionIOS <= 9) {
  console.log("Work around a change in behavior");
}

  二、特定平臺擴展名spring

  當不一樣平臺的代碼邏輯較爲複雜時,最好是放到不一樣的文件裏,這時候咱們可使用特定平臺擴展名。React Native 會檢測某個文件是否具備.ios.或是.android.的擴展名,而後根據當前運行的平臺自動加載正確對應的文件。react-native

***.ios.js
***.android.js

2、React Native中使用圖片

  一、靜態圖片資源

  React Native提供了一個統一的方式來管理iOS和Android應用中的圖片。要往App中添加一個靜態圖片,只須要把圖片放到代碼文件夾某處,就能夠直接引用。api

<Image source={require('./my-icon.png')} />

  若是你有my-icon.ios.pngmy-icon.android.png,Packager 就會根據平臺而選擇不一樣的文件。緩存

  並且還可使用@2x,@3x這樣的文件名後綴,來爲不一樣的屏幕精度提供圖片。安全

.
├── button.js
└── img
    ├── check.png
    ├── check@2x.png
    └── check@3x.png

  Packager會打包全部的圖片而且依據屏幕精度提供對應的資源。譬如:iPhone 7 會使用check@2x.png,而 iPhone 7 plus 或是 Nexus 5 上則會使用check@3x.png。若是沒有圖片剛好知足屏幕分辨率,則會自動選中最接近的一個圖片。

  這樣會帶來以下的一些好處:

  (1)iOS和Android一致的文件系統;

  (2)圖片和JS代碼處在相同的文件夾,這樣組件就能夠包含本身所用的圖片而不用單獨去設置;

  (3)不須要全局命名。不用擔憂圖片名字衝突問題。

  (4)只有實際被用到(即require)的圖片纔會被打包到app。

  注意:爲了使新的圖片資源機制正常工做,require中的圖片名字必須是一個靜態字符串(不能使用變量,由於require是在編譯時期執行,而非運行時期執行)。經過require方式引用的圖片包含圖片尺寸信息,不須要從新設置width和height.

  二、使用混合App的圖片資源

  若是你在編寫一個混合 App(一部分 UI 使用 React Native,而另外一部分使用平臺原生代碼),也可使用已經打包到 App 中的圖片資源(以拖拽的方式放置在 Xcode 的 asset 類目中,或是放置在 Android 的 drawable 目錄裏)。注意此時只使用文件名,不帶路徑也不帶後綴:

<Image source={{uri: 'app_icon'}} style={{width: 40, height: 40}} />

  對於放置在 Android 的 assets 目錄中的圖片,還可使用asset:/ 前綴來引用:

<Image source={{uri: 'asset:/app_icon.png'}} style={{width: 40, height: 40}} />

  注意:這些作法並無任何安全檢查。你須要本身確保圖片在應用中確實存在,並且還須要指定尺寸。

  三、Uri數據圖片  

  有時候你可能拿到的是圖片的 base64 數據,此時可使用'data:'格式來顯示圖片。請注意,你須要手動指定圖片的尺寸

// 請記得指定寬高!
<Image
  style={{
    width: 51,
    height: 51,
    resizeMode: 'contain',
  }}
  source={{
    uri:
      'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
  }}
/>

  四、緩存控制(僅iOS)

  緩存資源屬性提供了控制網絡層與緩存交互的方式。

  • default:使用原平生臺默認策略;
  • reload:URL的數據將從原始地址加載。不使用現有的緩存數據。
  • force-cache:現有的緩存數據將用於知足請求,忽略其期限或到期日。若是緩存中沒有對應請求的數據,則從原始地址加載。
  • only-if-cached:現有的緩存數據將用於知足請求,忽略其期限或到期日。若是緩存中沒有對應請求的數據,則不嘗試從原始地址加載,而且認爲請求是失敗的。
<Image
  source={{
    uri: 'https://facebook.github.io/react/logo-og.png',
    cache: 'only-if-cached',
  }}
  style={{width: 400, height: 400}}
/>

 3、動畫效果的使用

  React Native 提供了兩個互補的動畫系統:用於建立精細的交互控制的動畫Animated和用於全局的佈局動畫LayoutAnimation

  一、Animated

  Animated使得開發者能夠很是容易地實現各類各樣的動畫和交互方式,而且具有極高的性能。Animated旨在以聲明的形式來定義動畫的輸入與輸出,在其中創建一個可配置的變化函數,而後使用簡單的start/stop方法來控制動畫按順序執行。 Animated僅封裝了四個能夠動畫化的組件:ViewTextImageScrollView,不過你也可使用Animated.createAnimatedComponent()來封裝你本身的組件。下面是一個在加載時帶有淡入動畫效果的視圖:  

import React from 'react';
import { Animated, Text, View } from 'react-native';

class FadeInView extends React.Component {
  state = {
    fadeAnim: new Animated.Value(0),  // 透明度初始值設爲0
  }

  componentDidMount() {
    Animated.timing(                  // 隨時間變化而執行動畫
      this.state.fadeAnim,            // 動畫中的變量值
      {
        toValue: 1,                   // 透明度最終變爲1,即徹底不透明
        duration: 10000,              // 讓動畫持續一段時間
      }
    ).start();                        // 開始執行動畫
  }

  render() {
    let { fadeAnim } = this.state;

    return (
      <Animated.View                 // 使用專門的可動畫化的View組件
        style={{
          ...this.props.style,
          opacity: fadeAnim,         // 將透明度指定爲動畫變量值
        }}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}

// 而後你就能夠在組件中像使用`View`那樣去使用`FadeInView`了
export default class App extends React.Component {
  render() {
    return (
      <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
        <FadeInView style={{width: 250, height: 50, backgroundColor: 'powderblue'}}>
          <Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
        </FadeInView>
      </View>
    )
  }
}

  二、LayoutAnimation API

  LayoutAnimation容許你在全局範圍內建立更新動畫,這些動畫會在下一次渲染或佈局週期運行。它經常使用來更新 flexbox 佈局,由於它能夠無需測量或者計算特定屬性就能直接產生動畫。尤爲是當佈局變化可能影響到父節點(譬如「查看更多」展開動畫既增長父節點的尺寸又會將位於本行之下的全部行向下推進)時,若是不使用LayoutAnimation,可能就須要顯式聲明組件的座標,才能使得全部受影響的組件可以同步運行動畫。  

   儘管LayoutAnimation很是強大且有用,但它對動畫自己的控制沒有Animated或者其它動畫庫那樣方便,因此若是你使用LayoutAnimation沒法實現一個效果,那可能仍是要考慮其餘的方案。

  要在Android上使用 LayoutAnimation,那麼目前還須要在UIManager中啓用:

// 在執行任何動畫代碼以前,好比在入口文件App.js中執行
UIManager.setLayoutAnimationEnabledExperimental &&
  UIManager.setLayoutAnimationEnabledExperimental(true);
import React from 'react';
import {
  NativeModules,
  LayoutAnimation,
  Text,
  TouchableOpacity,
  StyleSheet,
  View,
} from 'react-native';

const { UIManager } = NativeModules;

UIManager.setLayoutAnimationEnabledExperimental &&
  UIManager.setLayoutAnimationEnabledExperimental(true);

export default class App extends React.Component {
  state = {
    w: 100,
    h: 100,
  };

  _onPress = () => {
    // Animate the update
    LayoutAnimation.spring();
    this.setState({w: this.state.w + 15, h: this.state.h + 15})
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={[styles.box, {width: this.state.w, height: this.state.h}]} />
        <TouchableOpacity onPress={this._onPress}>
          <View style={styles.button}>
            <Text style={styles.buttonText}>Press me!</Text>
          </View>
        </TouchableOpacity>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  box: {
    width: 200,
    height: 200,
    backgroundColor: 'red',
  },
  button: {
    backgroundColor: 'black',
    paddingHorizontal: 20,
    paddingVertical: 15,
    marginTop: 15,
  },
  buttonText: {
    color: '#fff',
    fontWeight: 'bold',
  },
});
相關文章
相關標籤/搜索