2017-07-15 59 views
0

我想在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

好了,找到了解決辦法。

問題是我的Animated.View使用了樣式化組件。

有更多的 「傳統」 Animated.View更換

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

(和使用樣式表的風格吧),它的工作原理。

+0

我花了太多時間在這個,很好找:) :) – chris

+0

這解決了我的問題,謝謝 – Tommy

相關問題