反应本地动画输入文本

时间:2019-01-09 01:38:35

标签: react-native animation absolute

我想在焦点TextInput动画上显示一个取消按钮。 我执行了以下代码,但是在显示焦点时,取消按钮不显示并跟随该框。仅在动画结束后显示。

当显示取消按钮时,它与textinput不在同一行。 我该如何解决?

const { width } = Dimensions.get('window');
const PADDING = 16;
const SEARCH_FULL_WIDTH = width - PADDING * 2;  //search_width when unfocused
const SEARCH_SHRINK_WIDTH = width - PADDING - 90;  //search_width when focused

class Search extends React.Component {

constructor(props: IProps) {
  super(props);
  this.state = {
    inputLength: new Animated.Value(SEARCH_FULL_WIDTH),
    searchBarFocused: false,
  }
}

private onFocus = () => {
  Animated.timing(this.state.inputLength, {
    toValue: SEARCH_SHRINK_WIDTH,
    duration: 250,
  }).start(() => this.setState({ searchBarFocused: true }));
}

private onBlur = () => {
  Animated.timing(this.state.inputLength, {
    toValue: SEARCH_FULL_WIDTH,
    duration: 250,
  }).start(() => this.setState({ searchBarFocused: false }));
}


<View style={styles.searchContainer}>
<Animated.View style={[
  styles.search,
  {
    width: this.state.inputLength,
    position: 'absolute',
    left: 16,
    alignSelf: 'center'
  },
  searchBarFocused === true ? undefined : { justifyContent: 'center' }
]}>
  <Image source={searchIcon} style={styles.image} />
  <TextInput
    style={styles.searchInput}
    ....
    onBlur={this.onBlur}
    onFocus={this.onFocus}
  />
</Animated.View>

{searchBarFocused &&
  <Touchable style={styles.cancelSearch} onPress={this.cancelSearch}>
    <Text style={styles.cancelSearchText}>Cancel</Text>
  </Touchable>
}
</View>

const styles = StyleSheet.create({
  searchContainer: {
    flexDirection: 'row',
    height: 72,
    borderBottomColor: SOLITUDE_COLOR,
  },
  search: {
    flex: 1,
    flexDirection: 'row',
    height: 40,
    borderRadius: 6,
  },
  cancelSearch: {
    marginHorizontal: 16,
    textAlign: 'center',
    justifyContent: 'center'
  }
});

gif:当不专心和专注时 vqhdHj

2 个答案:

答案 0 :(得分:2)

这是您代码的稍作修改的版本。

import React from "react";
import {
  Dimensions,
  View,
  Animated,
  TextInput,
  TouchableOpacity,
  StyleSheet,
} from "react-native";

const { width } = Dimensions.get("window");
const PADDING = 16;
const SEARCH_FULL_WIDTH = width - PADDING * 2; //search_width when unfocused
const SEARCH_SHRINK_WIDTH = width - PADDING - 90; //search_width when focused

const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity);

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputLength: new Animated.Value(SEARCH_FULL_WIDTH),
      cancelPosition: new Animated.Value(0),
      opacity: new Animated.Value(0),
      searchBarFocused: false
    };
  }

  onFocus = () => {
    Animated.parallel([
      Animated.timing(this.state.inputLength, {
        toValue: SEARCH_SHRINK_WIDTH,
        duration: 250
      }),
      Animated.timing(this.state.cancelPosition, {
        toValue: 16,
        duration: 400
      }),
      Animated.timing(this.state.opacity, {
        toValue: 1,
        duration: 250
      })
    ]).start();
  };

  onBlur = () => {
    Animated.parallel([
      Animated.timing(this.state.inputLength, {
        toValue: SEARCH_FULL_WIDTH,
        duration: 250
      }),
      Animated.timing(this.state.cancelPosition, {
        toValue: 0,
        duration: 250
      }),
      Animated.timing(this.state.opacity, {
        toValue: 0,
        duration: 250
      })
    ]).start();
  };

  render() {
    const { searchBarFocused } = this.state;

    return (
      <View style={styles.searchContainer}>
        <Animated.View
          style={[
            styles.search,
            {
              width: this.state.inputLength,
              position: "absolute",
              left: 16,
              alignSelf: "center"
            },
            searchBarFocused === true ? undefined : { justifyContent: "center" }
          ]}
        >
          <TextInput
            style={styles.searchInput}
            onBlur={this.onBlur}
            onFocus={this.onFocus}
            placeholder="Type something"
          />
        </Animated.View>

        <AnimatedTouchable
          style={[styles.cancelSearch, { right: this.state.cancelPosition }]}
          onPress={() => null}
        >
          <Animated.Text
            style={[styles.cancelSearchText, { opacity: this.state.opacity }]}
          >
            Cancel
          </Animated.Text>
        </AnimatedTouchable>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  searchContainer: {
    flexDirection: "row",
    height: 72,
    borderBottomColor: "#00000033",
    paddingTop: 100
  },
  search: {
    flex: 1,
    flexDirection: "row",
    height: 40,
    borderRadius: 6,
    backgroundColor: "red"
  },
  cancelSearch: {
    position: "absolute",
    marginHorizontal: 16,
    textAlign: "center",
    justifyContent: "center",
    alignSelf: "center"
  }
});

textinput-animation

答案 1 :(得分:0)

仅在动画完成后才设置searchBarFocused。由于取消按钮是根据searchBarFocused有条件渲染的,因此它仅出现在动画的结尾。