【问题标题】:How to get a simple right slide animation working with React Native如何使用 React Native 获得简单的右滑动画
【发布时间】:2018-11-18 09:11:24
【问题描述】:

我在使用 React Native 中的动画时遇到问题。我已经完成了一些工作,但它们都与教程非常相似,我无法将它们应用于我自己的东西。

为了让我朝着正确的方向前进。我怎样才能让这个动作从左到右动画化?

期望的结果

当点击“向右滑动”按钮时,主容器 (MainPosition) 平滑地向左移动 (marginLeft -screenWidth) 以将“窗格”(paneDimensions) 显示到右侧 (Right Pane)

(以下代码按预期工作,但没有滑动动画效果)

App.js

import React from 'react';
import { StatusBar, StyleSheet, Text, View, TouchableOpacity, Animated, Easing, Dimensions } from 'react-native';
import styles from './AppStyleSheet'

export default class App extends React.Component {

  constructor (props) {
    super(props);
    let screenWidth = Dimensions.get('window').width,
        screenHeight = Dimensions.get('window').height;
    this.state = {
      MainPosition: [styles.main, {width: screenWidth * 2}, {height: screenHeight}, {marginTop: 0}, {marginLeft: 0}],
      paneDimensions: [styles.pane, {width: screenWidth}, {height: screenHeight}]
    }
  }
  SlidePane =(direction)=> {
    let screenHeight = Dimensions.get('window').height,
        screenWidth = Dimensions.get('window').width,
        theTopMargin,
        theLeftMargin;
    if (direction === 'right') {
      theLeftMargin = parseInt('-' + screenWidth)
    }
    this.setState({
      MainPosition: [styles.main, {width: screenWidth * 2}, {height: screenHeight}, {marginTop: 0}, {marginLeft: theLeftMargin}]
    })
  }

  render() {
    return (
        <View style={this.state.MainPosition}>
          <StatusBar hidden />
          <View style={this.state.paneDimensions}>
            <View style={styles.buttonsContainer}>
              <TouchableOpacity style={styles.button} onPress={() => this.SlidePane('right')}>
                  <Text style={styles.buttonText}>Slide Right</Text>
              </TouchableOpacity>
            </View>
          </View>
          <View style={this.state.paneDimensions}>
            <Text style={styles.paneText}>Right Pane</Text>
          </View>
        </View>

    ); // end return
  } // end render
} // end export

AppStyleSheet.js

module.exports = {
    "main": {
      flexDirection: 'row',
      flexWrap: 'wrap',
      backgroundColor: 'hsla(0, 0%, 0%, 1)',
    },
    "row": {
      flexDirection: 'row',
      width: '100%',
      height: '100%',
    },
    "pane": {
      justifyContent: 'center',
      alignItems: 'center',
      borderTopWidth: 50,
      borderTopColor: 'transparent',
      backgroundColor: 'hsla(38, 100%, 73%, 1)',
    },
    "paneText": {
      fontSize: 20,
      color: 'black'
    },
    "buttonsContainer": {
      flex: 1,
      flexDirection: 'column',
      justifyContent: 'center',
      alignItems: 'center',
      width: '100%',
      height: '100%',
      paddingTop: 0,
      paddingBottom: 3,
    },
    "button": {
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
      width: '94%',
      marginBottom: 3,
      padding: 10,
      backgroundColor: 'hsla(38, 100%, 50%, 1)'
    },
    "buttonText": {
      fontSize: 20,
      color: '#FFF'
    },
}

【问题讨论】:

  • 我现在正在尝试解决类似的问题,但我需要在渲染后从右下角滑入视图。所以我试图像你一样为 marginTop 值而不是 marginLeft 设置动画。由于我收到错误“本机动画模块不支持样式属性'marginTop'”,因此对您如何使其工作感到困惑。我在网上看到很多人说这是有效且唯一的方法是为 translateY 设置动画。自从您发布此内容以来已经有一段时间了,但如果您能提供一些见解,我将不胜感激!
  • @MichaelK.Thai 嗨,Michael,我最近没有使用 react native,但 translateY 应该是更好、更顺畅的方法。 (正如我在这里所做的那样,动画位置或边距在动力不足的移动设备和平板电脑上可能非常笨拙)在我的示例中,您可以尝试transform: [{translateY: Math.abs(screenHeight)}], check this stack answer 以查看变换属性是如何写入数组的。抱歉,我现在没有任何反应原生的东西来测试它,但如果它有效,请告诉我。

标签: react-native


【解决方案1】:

我终于得到了这个工作(我不确定这是正确的方法,我确信这不是最好的方法,但这是我目前知道的唯一方法)

它基于来自 Tutorials Point 的 React Native animations tutorial 中的第二个示例(这是迄今为止我最容易理解的 RN 教程)

APP.js

import React from 'react';
import { StatusBar, StyleSheet, Text, View, TouchableOpacity, Animated, Easing, Dimensions } from 'react-native';
import styles from './AppStyleSheet'

export default class App extends React.Component {

  constructor (props) {
    super(props);
    let screenWidth = Dimensions.get('window').width,
        screenHeight = Dimensions.get('window').height;
    this.state = {
      MainPosition: [styles.main, {width: screenWidth * 2}, {height: screenHeight}, {marginTop: 0}, {marginLeft: 0}],
      paneDimensions: [styles.pane, {width: screenWidth}, {height: screenHeight}]
    }
  }
  componentWillMount() {
    this.animatedLeftMargin = new Animated.Value(0)
  }
  SlidePane =(direction)=> {
    let screenHeight = Dimensions.get('window').height,
        screenWidth = Dimensions.get('window').width,
        theLeftMargin;
    if (direction === 'right') {
      theLeftMargin = parseInt('-' + screenWidth);
      Animated.timing(this.animatedLeftMargin, {
        toValue: theLeftMargin,
        duration: 300
      }).start()
    }
    this.setState({
      MainPosition: [styles.main, {width: screenWidth * 2}, {height: screenHeight}, {marginTop: 0}]
    })
  }

  render() {
    return (
        <Animated.View style={[this.state.MainPosition, {marginLeft: this.animatedLeftMargin}]}>
          <StatusBar hidden />
          <View style={this.state.paneDimensions}>
            <View style={styles.buttonsContainer}>
              <TouchableOpacity style={styles.button} onPress={() => this.SlidePane('right')}>
                  <Text style={styles.buttonText}>Slide Right</Text>
              </TouchableOpacity>
            </View>
          </View>
          <View style={this.state.paneDimensions}>
            <Text style={styles.paneText}>Right Pane</Text>
          </View>
        </Animated.View>
    ); // end return
  } // end render
} // end export

附言

如果有人想了解更多关于我是如何做到的,请回复此问题,希望届时我能有更好的理解,以便能够通过解释更新此答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多