动画在发布模式下不起作用 [英] Animation not working on release mode

查看:47
本文介绍了动画在发布模式下不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create a custom slider with animation in react-native, and it kinda works, but only in debug mode.

一旦我尝试在 iOS 或 Android 上发布设备,动画就不再起作用.

As soon as I try a device release, either on iOS or Android, animation is not working anymore.

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>
    )
  }
}

您可以在 此处找到代码要点

谢谢,

卢卡

推荐答案

好的,找到解决方案了.

Ok, found the solution.

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

Problem was using styled-components for my Animated.View.

替换

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

使用更传统"的 Animated.View(并使用样式表对其进行样式设置),它可以工作.

with a more "conventional" Animated.View (and using a Stylesheet to style it), it works.

这篇关于动画在发布模式下不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆