【问题标题】:React Native animated input textReact Native 动画输入文本
【发布时间】:2019-06-03 18:10:14
【问题描述】:

我想在焦点 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:当不聚焦和聚焦时

【问题讨论】:

    标签: react-native animation absolute


    【解决方案1】:

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

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

    【讨论】:

    • 请问1个问题:如何让文本占位符像动画一样移动?我们不会使用TextInput的placeholder吧?
    • 是的,使用占位符我们可能无法做很多事情。您可能必须使用绝对定位的 Text 组件
    【解决方案2】:

    只有在动画完成后才能设置 searchBarFocused。由于取消按钮是基于searchBarFocused有条件地渲染的,所以它只出现在动画的最后。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      • 2022-01-20
      相关资源
      最近更新 更多