1. 程式人生 > >React Native 摺疊功能的實現及安卓踩坑筆記

React Native 摺疊功能的實現及安卓踩坑筆記

市面上有相應的外掛 react-native-collapsible, 但它在摺疊狀態底部有莫名其妙的空白,且有很多bug未解決, 於是自己試著實現了一個簡版。

基礎結構

<View style={S.container}>
  <View style={{flex: 1}}>
    <View style={S.content}
      onLayout={this.onContentLayout}>
      { this.props.children }
    </View>
  </View>
</View>

const S = StyleSheet.create({
  container: {
    overflow: 'hidden'
  },
  content: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0
  }
})

我們需要能動態控制顯示高度,會用到overflow:hidden,而預設狀態是摺疊的,因此,為了獲取實際內容的真實高度(不固定),需加兩層巢狀,以便通過onLayout方法提前得到展開後的高度。

這是開啟動畫的前提。

動畫的實現

這裡介紹兩種方式

Animated Component

這是我常用的技巧。首先把container裡面的元素用Animated.View封裝:

<Animated.View style={{ height: this.state.height }}>
  <View style={{flex: 1}}>
    ...
  </View>
</Animated.View>

其中height初值為new Animated.Value(0),數值0表示完全摺疊。

然後當展開時,給height應用動畫即可:

Animated.timing(
  this.state.height,
  {
    toValue: newHeight,
    duration: this.props.duration || 300,
    easing: this.props.easing || Easing.linear
  }
).start()

這裡newHeight為新的高度值,比如第一步中通過onLayout得到的真實高度。

反之亦然,摺疊時,再設為0即可。

LayoutAnimation

這是從reactnativecode.com上學到的技巧,原作者不詳。

這種方法不需要再次封裝,程式碼相對簡潔得多。這回我們直接在container上設定height

<View style={[ S.container, { height: this.state.height } ]}>
  ...
</View>

然後當摺疊或展開時,設定動畫並更新高度值:

LayoutAnimation.configureNext( LayoutAnimation.Presets.easeInEaseOut )

this.setState({ height: newHeight })

注意事項

在安卓機上,需要手動開啟動畫:

if ( Platform.OS === 'android' ) {
  UIManager.setLayoutAnimationEnabledExperimental(true)
}

踩坑

安卓下內容溢位

儘管設定了overflow:hidden,安卓下內容仍然會溢位一部分,然後和下方的內容層疊了,醜爆。

不能說overflow無效,但又不完全符合預期,試了多種方法包括改結構,均無效,太認人沮喪了。

為了方便除錯,就加了背景色,居然好了。莫名其妙的就好了!

所以解決方法是——設定背景色。

over