动画无法在发布模式下工作

时间:2017-07-15 18:37:12

标签: reactjs react-native

我正在尝试使用react-native创建一个带有动画的自定义滑块,它有点工作,但仅在调试模式下。

一旦我尝试在iOS或Android上发布设备,动画就不再有用了。

import React, { PureComponent } from 'react'
import { PanResponder, Animated, View } from 'react-native'
import styled from 'styled-components/native'

import {
  PRIMARY_COLOR,
  SECONDARY_COLOR,
  BACKGROUND_COLOR,
  TEXT_COLOR,
} from '../../constants'

const DATA = [
  {
    title: 'Question 1',
    values: [
      { value: 3, label: "We gonna say a lot" },
      { value: 2, label: "Often" },
      { value: 1, label: "Once" },
      { value: 0, label: "Never" },
    ]
  },
  {
    title: 'Sed feugiat, est quis hendrerit condimentum, eros massa euismod purus.',
    values: [
      { value: 10, label: "Romerus is rulis" },
      { value: 7, label: "Phasellus bibendum blandit" },
      { value: 5, label: "This build could be faster" },
      { value: 4, label: "Nulla in felis non." },
      { value: 3, label: "Custom Phone" },
    ]
  }
]

const TOOLBAR_HEIGHT = 56
const SPACE_BOTTOM = 70
const SPACE_TOP = 120
const LABEL_HEIGHT = 22
const STROKE_LENGTH = 75

const MainView = styled.View`
  flex: 1;
  background-color: ${BACKGROUND_COLOR};
`
const Title = styled.Text`
  position: absolute;
  top: 40;
  right: 50;
  left: ${STROKE_LENGTH / 2};
  color: ${TEXT_COLOR};
`
const LabelsView = styled.View`
  position: absolute;
  left: 0;
  bottom: ${SPACE_BOTTOM};
  width: 100%;
`
const LabelView = styled.View`
  position: absolute;
  left: 0;
  top: ${({top}) => top};
`
const LabelMark = styled.View`
  width: ${STROKE_LENGTH};
  border-bottom-color: ${({ color }) => color};
  border-bottom-width: 2;
  position: absolute;
  left: 0;
  top: 0;
`
const LabelText = styled.Text`
  color: ${({ color }) => color};
  top: 5;
  left: ${STROKE_LENGTH - 10};
`
const KnobAnimated = Animated.createAnimatedComponent(styled.View`
  background-color: ${PRIMARY_COLOR};
  width: 100%;
  position: absolute;
  bottom: 0;
  left: 0;
  overflow: hidden;
`)
const ButtonView = styled.View`
  position: absolute;
  bottom: 40;
  right: 40;
  width: 60;
`
const Button = styled.Button.attrs({
  color: SECONDARY_COLOR,
})``


export default class SlidePicker extends PureComponent {

  constructor (...props) {
    super(...props)

    // Functions binding
    this.setLayout = this.setLayout.bind(this)
    this.goToNextStep = this.goToNextStep.bind(this)
  }

  state = {
    step: 0,
    viewHeight: null,
    knobHeight: new Animated.Value(0),
  }

  labelHeight = null

  panResponder = PanResponder.create({
    onStartShouldSetPanResponder: () => true,

    onPanResponderMove: Animated.event([null, {
      moveY: this.state.knobHeight,
    }]),

    onPanResponderGrant: (e, gestureState) => {
      Animated.timing(this.state.knobHeight, {
        toValue: gestureState.y0,
        duration: 100,
      }).start()
    },

    onPanResponderRelease: (e, gestureState) => {
      // Get end value
      const endValue = gestureState.moveY || gestureState.y0

      // Compute target value
      let val = Math.round((endValue - SPACE_TOP - TOOLBAR_HEIGHT) / this.labelHeight) * this.labelHeight + SPACE_TOP + TOOLBAR_HEIGHT

      // Check val is not after last one
      if (val >= this.labelHeight * DATA[this.state.step].values.length + SPACE_TOP + TOOLBAR_HEIGHT) {
        val = this.state.viewHeight + TOOLBAR_HEIGHT
      }

      Animated.timing(this.state.knobHeight, {
        toValue: val,
        duration: 500,
      }).start()

      // Extract value
    },
  })

  setLayout (event, init = true, step = this.state.step) {
    const height = event ? event.nativeEvent.layout.height : this.state.viewHeight

    if (init === true) {
      this.state.knobHeight.setValue(height + TOOLBAR_HEIGHT)
    } else {
      Animated.timing(this.state.knobHeight, {
        toValue: this.state.viewHeight + TOOLBAR_HEIGHT,
        duration: 100,
      }).start()
    }

    const spaceBetween = (height - SPACE_TOP - SPACE_BOTTOM - ( LABEL_HEIGHT * DATA[step].values.length )) / (DATA[step].values.length - 1)
    this.labelHeight = spaceBetween + LABEL_HEIGHT

    if (event) {
      this.setState({
        viewHeight: event.nativeEvent.layout.height,
      })
    }
  }

  goToNextStep () {
    const nextStep = this.state.step < DATA.length - 1 ? this.state.step + 1 : 0

    this.setState({
      step: nextStep,
    })

    this.setLayout(null, false, nextStep)
  }

  renderDraggable () {
    if ( ! this.state.viewHeight) {
      return false
    }

    return (
      <KnobAnimated
        style={{
          height: this.state.knobHeight.interpolate({
            inputRange: [
              0,
              SPACE_TOP + TOOLBAR_HEIGHT,
              this.state.viewHeight + TOOLBAR_HEIGHT - SPACE_BOTTOM,
              this.state.viewHeight + TOOLBAR_HEIGHT,
            ],
            outputRange: [
              this.state.viewHeight - SPACE_TOP,
              this.state.viewHeight - SPACE_TOP,
              SPACE_BOTTOM,
              0,
            ],
          }),
        }}
      >
        { this.renderScale({
          markColor: '#FFFFFF',
          textColor: '#FFFFFF',
        }) }
      </KnobAnimated>
    )
  }

  renderScale ({
    markColor = PRIMARY_COLOR,
    textColor = TEXT_COLOR,
  } = {}) {
    if ( ! this.state.viewHeight) {
      return false
    }

    const labels = DATA[this.state.step].values.map((step, index) => {
      return (
        <LabelView key={step.value} top={index * this.labelHeight}>
          <LabelMark color={markColor} />
          <LabelText color={textColor}>{step.label}</LabelText>
        </LabelView>
      )
    })

    return (
      <LabelsView height={this.state.viewHeight - SPACE_TOP - SPACE_BOTTOM}>
        { labels }
      </LabelsView>
    )
  }

  render () {
    return (
      <MainView {...this.panResponder.panHandlers} onLayout={ this.setLayout }>
        <Title>{ DATA[this.state.step].title }</Title>
        { this.renderScale() }
        { this.renderDraggable() }
        <ButtonView>
          <Button onPress={this.goToNextStep} title="Next" />
        </ButtonView>
      </MainView>
    )
  }
}

您可以找到代码here on gist

谢谢,

卢卡

1 个答案:

答案 0 :(得分:2)

好的,找到了解决方案。

问题是我的Animated.View使用了样式组件。

替换

const KnobAnimated = Animated.createAnimatedComponent(styled.View`
  background-color: ${PRIMARY_COLOR};
  width: 100%;
  position: absolute;
  bottom: 0;
  left: 0;
  overflow: hidden;
`)

更多&#34;传统&#34; Animated.View(并使用样式表来设置样式),它可以工作。