React Native:使用Animated API创建一个动画输入字段

大家好! 今天,我们与您分享认知材料,该材料是专门为“ ReactJS / React Native-developer”课程的学生准备的。



因此,让我们开始吧。


我们都看到了以下输入字段:



标题很大,看起来像一个占位符,直到您专注于输入。 它将变小并上升。

看起来很棒 顺利 无可挑剔。

似乎只有经验丰富的开发人员才能做到这一点,对吗?
好吧,也许这是在React Native出现之前的那个年代,那时人们生活在山洞中并制作各种游戏。 但这已成为过去。

您可以观看视频或继续阅读。 这完全取决于您的喜好。


我们要达到什么目标?


我们正在处理两种选择。
第一种是在没有关注输入字段时。



输入字段内部将显示一个题词,其大小等于文本字段的大小。 颜色暗淡。 这与placeholder属性非常相似。

第二种选择,当重点放在输入字段上时。



题词出现在输入字段上方,其大小较小,并且颜色与输入的文本的颜色不同。

最简单的实施


最后,我们可以开始工作了。 到目前为止,没有任何动画。
事实证明,我们有两种UI状态:

  1. 没有关注该字段以及该字段内的铭文。
  2. 重点放在字段上,输入字段上方有一个题词。



实际上,我们可以存储是否关注该领域的状态。 然后,根据这种状态,我们可以选择将铭文放置在何处以及要应用哪种样式。

由于铭文必须位于不同的位置,并且我们不希望其影响组件的放置,因此我们将对其进行绝对定位。 为了确保有足够的空间,您必须从上方将缩进添加到包装视图中。

 class FloatingLabelInput extends Component { state = { isFocused: false, }; handleFocus = () => this.setState({ isFocused: true }); handleBlur = () => this.setState({ isFocused: false }); render() { const { label, ...props } = this.props; const { isFocused } = this.state; const labelStyle = { position: 'absolute', left: 0, top: !isFocused ? 18 : 0, fontSize: !isFocused ? 20 : 14, color: !isFocused ? '#aaa' : '#000', }; return ( <View style={{ paddingTop: 18 }}> <Text style={labelStyle}> {label} </Text> <TextInput {...props} style={{ height: 26, fontSize: 20, color: '#000', borderBottomWidth: 1, borderBottomColor: '#555' }} onFocus={this.handleFocus} onBlur={this.handleBlur} /> </View> ); } } 

 <FloatingLabelInput label="Email" value={this.state.value} onChange={this.handleTextChange} /> 

完成上述步骤后,我们可以实现以下目标:

https://snack.expo.io/Sk006AbdW?session_id=snack-session-JRMksbYK3

这是一个很好的起点。 到目前为止,我们还没有动画,但是我们已经可以根据焦点所在的位置更改铭文的位置。

为什么不使用placeholder


当然,使用占位符的TextInput属性似乎很诱人。 但是,这将不起作用,因为我们要控制显示题词的方式,时间和位置。

相反,我们希望标签在焦点位于文本框内时位于文本框内。 并且,当焦点出现在输入字段上时,我们希望它向上移动,只有在使用相同的元素时才能实现。

动画怎么样?


实际上,最简单的部分仍然存在。

由于我们有两个可能有题字的状态,因此我们根据焦点选择一个,并且状态之间的这种过渡的动画非常琐碎。

从本指南中,我们可以重点介绍以下内容:

  • Animated.Value表示是否重点关注字段(1)(0);
  • 对焦时我们将逐渐将数字更改为(1),否则将更改为(0);
  • 以该数字的形式,我们将反映题字的样式:在(0)和(1)中,我们将定义样式,而React Native将自动计算并应用中间样式。 甚至颜色。

实现所有这些并不困难。

Animated.Value我们将需要在componentWillMount进行初始化。

 componentWillMount() { this._animatedIsFocused = new Animated.Value(0); } 

然后,由于此数字的值应基于是否集中在输入字段上,并且由于我们已经具有此状态信息,因此可以添加componentDidUpdate函数,该函数将根据this.state更改此数字:

 componentDidUpdate() { Animated.timing(this._animatedIsFocused, { toValue: this.state.isFocused ? 1 : 0, duration: 200, }).start(); } 

现在,为了以这种方式反映题词的样式,我们只需要进行两项更改:

更改为Animated.Text

而不是使用条件来定义样式,请按以下方式定义它们:

 const labelStyle = { position: 'absolute', left: 0, top: this._animatedIsFocused.interpolate({ inputRange: [0, 1], outputRange: [18, 0], }), fontSize: this._animatedIsFocused.interpolate({ inputRange: [0, 1], outputRange: [20, 14], }), color: this._animatedIsFocused.interpolate({ inputRange: [0, 1], outputRange: ['#aaa', '#000'], }), }; 

https://snack.expo.io/Hk8VCR-dZ?session_id=snack-session-AJ4vulSVw

还有一件事


如果在上面的演示中尝试输入某些内容,然后从输入字段中移出焦点,则会看到一些奇怪的内容。



幸运的是,这很容易解决。 我们只需要在代码中更改两行。

我们要检查输入字段是否为空,并且仅当以下两个条件都成立时,才将状态更改为“未聚焦”

  • 输入字段为空;
  • 没有专注于该领域。

否则,我们希望应用“重点突出”的样式,并增加替换标题。

现在我们正在跟踪输入字段的状态,我们可以使用this.props轻松访问其值。



https://snack.expo.io/ByZBAC-dZ?session_id=snack-session-YNZSqhqOC


仅此而已。 免费网络研讨会上见

Source: https://habr.com/ru/post/zh-CN467623/


All Articles