In this lesson we'll create a notify button that expands from the middle to show a
TextInput with a send button and once sent will hide the
TextInput and show a thank you message. We'll use the helper method
StyleSheet.absoluteFill to position our input inside of our wrapping
View. This allows us to animate our
TextInput and our messages in and out without effecting layout of each other.
When pressed to show the
TextInput and when we show the thank you message a combination of animating the width and
justifyContent: "center" to make it appear as if we're animating the view from the center. We'll use
Animated.timing and a
success boolean on state to control what is rendered, and what is animating.
interpolate will be used heavily to scale in and out views when they are needed.
Let's dive in and check the state of our application before we start styling it and making it look nice. We have an animated value, as well as a Boolean for success of true and false, we have a handlePress, and we have a handleSend.
Additionally, we have a few conditional inputs. If we're not successful, we'll render a text input, we'll also render the notifyMe text. However, if we are successful, we'll render a thank you message.
The first thing we'll need to do is create an interpolation on the width so that we can control it expanding. We'll set up a const widthInterpolate, set this.state.animate.interpolate().
Our input range will a few values, 0, .5, and 1. This will give us three steps. We have an output range of 150, 150, and 300. We'll then also add an extrapolate:'clamp'. We'll then do const buttonWrapStyleWidth, then add our widthInterpolate.
We can go ahead and apply that to our buttonWrap, refresh, and now we have a default of 150 width on our button. The input is currently visible, so we need to adjust it so it is scaled out of the way.
Say const inputScaleInterpolate = this.state.animate.interpolate(). We'll set our input range to 0, .5, and .6, so a three step, and our output range of 0, 0, and 1. We'll then set up inputScaleStyle which we have a transform of an array with a scale, and we'll put our inputScaleInterpolate in here.
Now we can apply that to our interpolation, or to our input, and now when we refresh, we can see that it has scaled all of our stuff out of the way. Now we not only need to scale our input, but we also need to scale in our send button.
We come up here and create a const sendButtonInterpolate = this.state.animate.interpolate(), and our input range will be slightly shifted, because we want it to animate in after our input has scaled in.
We'll say input range, and we'll set it to 0, .6, and 1, and our output range will be 0, 0, and then 1, so it will come in late. Now we can go in and set up our const sendButtonStyle, and do scale as well. Then we'll apply that to our sendButton.
Finally, before we can actually see this in action, we need to create a scale for our notifyMe button. We'll say const notifyTextScaleInterpolate, we'll set up this.state.animate.interpolate(), and this we need to scale out quickly before we scale in anything else.
We'll say our input range is a two-step of 0 to .5, our output range is 1 to 0, and we don't want to scale any further, so let's say extrapolate:'clamp'. Now we'll go ahead and set up const notifyTextStyle and this will also be a scale.
We'll say transform scale and pass in this, and then we can apply this to our animated view that surrounds our text, so equals notifyTextStyle. Let's go up to our inputScaleInterpolate and we will add an extrapolate:'clamp' so it does not scale beyond 1.
Now we'll go up here and say animated.timing, say this.state.animate to a value of 1, a duration of 300ms, and then we'll call start. Now when we press this button, our input expanded, focused, and our button scaled in.
The final scale we'll need is for our thank you message. We want it to scale in as everything else is scaling out. What we'll do is set up a const thankyouScaleInterpolate = this.state.animate.interpolate(). With our input range we'll go from 0 to 1, and our output range, we'll flip that around and go 1 to 0.
This will cause a revers effect, so once this is animating backwards from 1 to 0 to reset, our scale will go from 0 to 1 and it will look like our thank you is animating in. We'll say const thankyouTextStyle, do transform with a scale, and our thankyouScaleInterpolate, and well go apply this to our thankyouText.
Now when we press the sendButton, handleSend will be called, so let's implement handleSend. We need to call this.setState, and say success is true, this will allow our thank you message to be shown, however it will be scaled out to 0 because our animated value is all the way to 1 at the moment.
Then, to scale everything out, we'll do an animated.sequence and in there, we'll say animated.timing = this.state.animate to value of 0, duration of 300. We'll also do a delay of animated.delay of 1500 before we toggle everything back.
We call start, start takes a function that we call once this animation is over, and at that point we're going to say this.setState success false to reset everything back to the beginning. Now if we refresh, click notify, type in an email, click send, everything expands back to nothing and then resets back to the notifyMe.