Javascript 反应本机-设置宽度收缩动画
在我的React原生应用程序的标题中,我有一个条件图标和一个图标Javascript 反应本机-设置宽度收缩动画,javascript,react-native,animation,transition,Javascript,React Native,Animation,Transition,在我的React原生应用程序的标题中,我有一个条件图标和一个图标 静态导航选项=({navigation})=>{ const{params={}}=navigation.state; 返回{ 标题:( {params.isIconTriggered&&} ), 头型:{ 背景颜色:“#e54b4d”, }, }; }; 通常,搜索栏将采用标题的全宽,这是我想要的。如果条件IsInContrigured为真,则搜索栏前面会出现一个图标,搜索栏的宽度会缩小到足够大,以便在旁边可以看到该图标 但是
静态导航选项=({navigation})=>{
const{params={}}=navigation.state;
返回{
标题:(
{params.isIconTriggered&&}
),
头型:{
背景颜色:“#e54b4d”,
},
};
};
通常,搜索栏将采用标题的全宽,这是我想要的。如果条件IsInContrigured为真,则搜索栏前面会出现一个图标,搜索栏的宽度会缩小到足够大,以便在旁边可以看到该图标
但是,发生这种情况时没有过渡或动画,感觉也不好。我想给搜索栏添加一个动画,这样当条件被触发并且图标出现时,宽度会逐渐平滑地缩小
这有可能实现吗?我如何实现这一点?您可以使用React Native的API实现这一点
您可以查看此项,了解如何使用动画更改元素的大小 尝试学习react native的动画API 下面是我如何使用按钮触发器完成的
import React,{Component}来自'React';
从“react native”导入{样式表、视图、文本输入、按钮、安全区域视图、动画};
从“反应本机矢量图标/FontAwesome5”导入FA
const AnimatedIcon=Animated.createAnimatedComponent(FA)
//使用createAnimatedComponent方法使图标可设置动画
导出默认类应用程序扩展组件{
animVal=新的动画值(0);
//初始化动画值以用于动画,而初始值为零
interpolateIcon=this.animVal.interpolate({inputRange:[0,1],outputRange:[0,1]})
interpolateBar=this.animVal.interpolate({inputRange:[0,1],outputRange:['100%,'90%']})
//初始化插值以控制将传递给样式的输出值
//因为我们将动画搜索栏和图标。我们需要初始化这两个
//在图标上,我们将为比例设置动画,而outputRange从0开始,在1结束
//在搜索栏上,我们将设置宽度的动画。而输出范围从100%开始,到90%结束
animatedTransition=Animated.spring(this.animVal,{toValue:1})
//我们使用弹簧使动画有弹性,它的动画值为1
单击动画=()=>{
this.animatedTransition.start()
}
//动画按钮触发器
//将用于动画的组件必须设置动画,例如动画化视图
render(){
返回(
{/*我们的图标*/}
React Native Animable超级酷!
试试这个:
创建自定义动画对象
在视图中用作动画值或在函数调用中用作引用
在视图中:
您是否正在使用任何样式库,如样式化组件
?@SergioEscudero我不使用任何样式库。哇。感谢您为这个答案付出的所有时间和精力。我认为这可能是我需要的解决方案,但我无法让它工作。搜索栏()我正在使用needsflex:1
以充分显示和正常工作,我想可能是有问题或其他原因。这样做会把一切都搞砸,动画也不会工作。您可以尝试使用示例中React Native Elements的搜索栏吗?我整晚都在努力,到目前为止还没有成功。我已经尝试过了尚未尝试使用react native elements library。是否可以使用width/height属性而不是flex?我尝试同时使用height
和width
。但是,它不起作用。如果是这样的话。我只能想到的解决方案是将搜索栏组件包装在Animated.View中。这样它就可以在不修改道具的情况下显式设置动画搜索栏组件的惯性。我更新了我的答案。我在实现了与之完全相同的东西后发现了这一点,但对我来说,动画非常滞后,因为我无法将本机驱动程序用于布局道具。你是如何让它如此流畅的?
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
headerTitle: (
<View
style={{
flex: 1,
backgroundColor: Platform.OS === 'ios' ? '#e54b4d' : '',
alignItems: 'center',
flexDirection: 'row',
paddingHorizontal: 10,
height: StatusBar.currentHeight,
}}>
{params.isIconTriggered && <Icon name="chevron-left" size={28} />}
<SearchBar
round
platform={'default'}
placeholder="Search"
containerStyle={{
flex: 1,
backgroundColor: 'transparent',
}}
/>
</View>
),
headerStyle: {
backgroundColor: '#e54b4d',
},
};
};
import React, {Component} from 'react';
import {StyleSheet, View, TextInput , Button, SafeAreaView, Animated} from 'react-native';
import FA from 'react-native-vector-icons/FontAwesome5'
const AnimatedIcon = Animated.createAnimatedComponent(FA)
// make your icon animatable using createAnimatedComponent method
export default class Application extends Component {
animVal = new Animated.Value(0);
// initialize animated value to use for animation, whereas initial value is zero
interpolateIcon = this.animVal.interpolate({inputRange:[0,1], outputRange:[0,1]})
interpolateBar = this.animVal.interpolate({inputRange:[0,1],outputRange:['100%','90%']})
// initialize interpolation to control the output value that will be passed on styles
// since we will animate both search bar and icon. we need to initialize both
// on icon we will animate the scale whereas outputRange starts at 0 end in 1
// on search bar we will animate width. whereas outputRange starts at 100% end in 90%
animatedTransition = Animated.spring(this.animVal,{toValue:1})
// we use spring to make the animation bouncy . and it will animate to Value 1
clickAnimate = () => {
this.animatedTransition.start()
}
// button trigger for animation
//Components that will use on Animation must be Animated eg. Animted.View
render() {
return (
<SafeAreaView>
<View style={styles.container}>
<View style={styles.search}>
{/* our icon */}
<Animated.View style={{width: this.interpolateBar}}>
<TextInput placeholder='search here' style={styles.input}/>
</Animated.View>
<AnimatedIcon name='search' size={28} style={{paddingLeft: 10,paddingRight:10, transform:[{scale: this.interpolateIcon}]}}/>
</View>
<Button title='animate icon' onPress={this.clickAnimate}/>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor:'#F79D42',
// flex: 1,
height:'100%',
paddingTop:20,
flexDirection: 'column',
// justifyContent: 'center',
alignItems:'center'
},
input:{
width: '100%',
height:40,
backgroundColor:'gray',
textAlign:'center'
},
search:{
flexDirection:'row-reverse',
width:'90%',
height:40,
alignItems:'center'
}
});
<Animated.View style={{width: this.interpolateBar}}>
<SearchBar
placeholder="Type Here..."
containerStyle={{width: '100%'}}
/>
</Animated.View>
import * as Animatable from 'react-native-animatable';
Animatable.initializeRegistryWithDefinitions({
const myAnimation = {
from: {
width: 200
},
to: {
width: 100
}
}
})
<Animatable.View useNativeDriver animation={myAnimation}/>
<Animatable.View useNativeDriver ref={ref=>(this.testAnimation = ref)}/>
testMethod = () => {
this.testAnimation.myAnimation();
}