[React Native] 動畫 · LayoutAnimatd 和 setNativeProps

LayoutAnimation

對於一些既定的界面元素,圖片、文字、滾動視圖等動畫效果,咱們會優先選擇 Animated 來進行處理。可是若是你的動畫效果須要改變佈局,涉及到其餘的 View 或者節點元素。那麼就應該優先考慮 LayoutAnimation 來實現了。spring

較之於 Animated,LayoutAnimation 的使用要更簡單。 若是你用 state 記錄並改變過某一 View 的高度,那麼在此基礎上只須要調用一下LayoutAnimation 的動畫函數,並保證父節點是 flex 佈局的,就能夠實現這一高度變化的動畫。函數

動畫類型:

  • easeInEaseOut() 先加速至全速,再逐漸減速漸停
  • linear() 線性動畫,保持均速
  • spring() 彈性模型,有一個反覆回彈的效果

注意:在Android 上使用 LayoutAnimation 須要導入 UIManager 並啓用:工具

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

[動畫1 - 改變佈局高度,將同級 View 往下推]性能

效果:flex

layout

實現:動畫

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

export default class LayoutAnimated extends Component {
  state = {
    moreHeight: 0,					//動態高度
  };
  _onPress = () => {
    LayoutAnimation.spring();   	//調用 LayoutAnimation 動畫
    this.setState({moreHeight: this.state.moreHeight === 0 ? 100 : 0})
  }

  render() {
    return (
      <View style={{flex: 1, paddingHorizontal: 20}}>
        <View style={styles.card_view}>
          <TouchableOpacity onPress={this._onPress}>	// 爲看到點擊效果,不在 Text中實現 onPress
            <Text style={styles.more_text}>查看更多</Text>
          </TouchableOpacity>
          <View style={{height: this.state.moreHeight}}/>  //變量直接設定給 View
        </View>
        <View style={{backgroundColor: '#e29fae', height: 100}}/>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  card_view: {backgroundColor: '#ebde5d', marginTop: 20},
  more_text: {textAlign: 'right', paddingVertical: 8, borderBottomColor: '#ccc', borderBottomWidth: 1},
});
複製代碼

可見,外部佈局是彈性佈局的時候,在 setState 的基礎上調用一次 LayoutAnimation.spring() ,就能夠實現佈局改變的動畫。this

setNativeProps

若是使用的動畫,須要頻繁地刷新,進行 setState,就一定會影響到性能。 此時能夠嘗試使用 setNativeProps 來進行修改 ,該方法直接修改基於原生視圖的組件的屬性來達到效果。spa

這種直接操做組件的操做並非應該常常使用的工具。 通常只是用來建立連續的動畫,同時避免渲染組件結構和同步太多視圖變化所帶來的大量開銷。 setNativeProps 是一個「簡單粗暴」的方法,它直接在底層(DOM、UIView 等)而不是 Rea ct 組件中記錄 state,這樣會使代碼邏輯難以理清。因此在使用這個方法以前,請儘可能先嚐試用 setState 和 shouldComponentUpdate 方法來解決問題。 (引用自官方文檔)code

因此, setNativeProps 是一個強大但也是不得已而爲之的選擇。

[動畫2 - setNativeProps 實現頭部欄透明度漸變 ]

有時咱們會須要在列表視圖滾動的時候,頭部欄有一個透明度漸變的效果。在滑動到必定的距離以後,頭部欄再也不透明。

header

通常思路是這樣,重寫 ScrollView 的 onScroll 方法,判斷當前所處的 y 值,並經過當前 y 值所處範圍計算出應該設置的透明度。可是若是此時用 state 記錄透明度,setState 完成設置刷新的話,開銷的巨大的,甚至致使必定的卡頓 [onScroll 的觸發十分頻繁 (scrollEventThro 能夠改變 onScroll 調用頻率但不推薦)]。因此這裏咱們應該選擇的是 setNativeProps。

實現:

<View										//頭部view ,設定 ref
    ref={head => this.headerView = head}
	...
  </View>
複製代碼

在滑動的 y 值在(50,100] 之間的時候,設置透明度爲 y/100 。這樣在 50 如下都是 0.5 半透明, 100 日後透明度都是 1,即不透明。

//ScrollView 的 onScroll 方法
  onScroll = ({nativeEvent, contentOffset}) => {
    // console.info('nativeEvent', nativeEvent);
    const currentY = nativeEvent.contentOffset.y;
    if (currentY > 50 && currentY <= 100) {
      this.headerView.setNativeProps({
        style: {opacity: currentY / 100}
      })
    }
  }
複製代碼

能夠看到,setNativeProps 在這個場景中仍是很是適用的,若是你體驗過 setState,就能很明顯的感覺到它的優點了。

相關文章
相關標籤/搜索