preface

In this article we implement a simple animation effect to familiarize and deepen the use of Android property animation. In addition, this time we use Kotlin to develop, students who are not familiar with Kotlin can simply understand kotlin syntax, basic should be able to understand

As we know, Android View Animation can move, enlarge and other effects, but cannot change the actual properties of the layout. For example, scaleAnimation is used to scale the layout, but the actual size of the layout does not change, so it covers the adjacent layout, rather than spreading the layout out and squeezing other layouts.

Results show

Now we want to achieve an effect as follows:

Using ViewAnimation is a bit more cumbersome, so ObjectAnimator is used.

Animation analysis

This effect has three states:

(State 1)

(State 2)

(State 3)

The effect consists of two stages:

Inundation – from state 1 to state 2. The entire pink area inundated the page upward

Expand — from state 2 to state 3. When the entire page is flooded, expand from the middle to the entire page

The overall layout

These two stages are actually implemented by executing two parts of the animation in sequence. Let’s look at the layout first:


      
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width= "match_parent"
             android:layout_height= "match_parent" >
    <RelativeLayout
        android:id="@+id/animation_content"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_gravity="bottom"
        >
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/girl1"/>
        <FrameLayout
            android:id="@+id/spread_view"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_centerInParent="true" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@id/spread_view"
            android:drawableBottom="@drawable/camera_top"
            android:background="#e07468" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/spread_view"
            android:drawableTop="@drawable/camera_bottom"
            android:background="#e07468" />
    </RelativeLayout >
</FrameLayout>
Copy the code

The whole layout is mainly composed of four parts:

  • Animation_content — This is part of the entire pink area.
  • Spread_view — This is the part of the black area that starts with a height of 0
  • The two TextViews — the circular button in the middle — are actually made up of two separate sections with spread_view in between. (This is for stage 2 animation, more on this below)

Note here that we use textView instead of ImageView for the button layout, because if we use imageView, when the second stage expands beyond the top and bottom of the screen, the imageView area compression causes the image to shrink rather than overflow. The difference is as follows

Use the ImageView effect

Use the TextView effect

So we’re going to use TextView here. And set the image with properties like drawableBottom so that the image size does not change when the area shrinks.

The source code parsing

Here is the code:

class FloodAndSpreadActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.flood_and_spread_activity)
        init()}fun init(a){
        val height: Int = window.windowManager.defaultDisplay.height
        var floodWrapper = ViewWrapper(animation_content)
        var spreadWrapper = ViewWrapper(spread_view)
        var floodAnimation = ObjectAnimator.ofInt(floodWrapper, "height", height)
        floodAnimation.duration = 1000
        floodAnimation.start()
        floodAnimation.addListener(object: Animator.AnimatorListener{
            override fun onAnimationRepeat(p0: Animator?).{}override fun onAnimationCancel(p0: Animator?).{}override fun onAnimationStart(p0: Animator?).{}override fun onAnimationEnd(p0: Animator?). {
                ObjectAnimator.ofInt(spreadWrapper, "height", height).setDuration(1000).start()
            }
        })
    }

    class ViewWrapper (var mTarget: View){
        fun getHeight(a):Int{
            return mTarget.layoutParams.height
        }

        fun setHeight(height: Int){
            mTarget.layoutParams.height = height
            mTarget.requestLayout()
        }
    }
}
Copy the code

One of Kotlin’s strengths is its ability to simplify code massively, as you can see in just a dozen lines.

Going back to the code itself, we know from the above analysis that the entire process consists of two parts of the animation: submerged and unfolded.

In the code, you can see a floodAnimation, which dynamically changes the height of the animation_content to the height of the screen via floodWrapper. And since spread_view is set to centerInParent, and the two parts of the button are associated with spread_view, the button moves along during the animation and remains at the center of the animation_Content.

Knowledge summary

ObjectAnimator

Here’s a brief description of the method we use: ofInt(floodWrapper, “height”, height). This method applies primarily to arguments of type int. The first parameter is the class whose property is to be changed, which could be a proxy class, as we’ll see below; The second argument is the name of the property to change, which actually calls the corresponding getter and setter methods of the class; The third parameter is the final value of the property, which gradually changes from the current value to the final value over the course of the animation.

ObjectAnimator has many more methods that you can learn on your own.

ViewWrapper

We’re going to talk about floodWrapper, which is a ViewWrapper object. ObjectAnimator uses getter and setter methods to change the value of a property of the class, but if there are no corresponding methods or more operations are needed, we can use the proxy form. ViewWrapper is a proxy class. Since the View only has getHeight functions and no setHeight functions, we proxy it with ViewWrapper and implement getHeight and setHeight functions.

conclusion

Going back to floodAnimation, we see that there’s a listener that starts another animation when the animation ends. Another way to do this is with animatorSets. Animatorsets allow multiple animations to be executed in different sequences, which is very useful for dealing with complex animation effects. Since this article is only a simple sequential execution, the use of AnimatorSet is relatively simple, you can refer to the official documentation.

While floodAnimation is complete, we perform another animation, which is the second phase: unwrap. This time we changed the height of the “spread_view”. Since the two parts of the button are associated with spread_view, when the height of the “spread_view” changes, the two parts of the button move apart, creating an unfolding effect. Until spread_view spreads to the entire screen.

The effect is now complete, and the actual use of the effect is a transition or cut scene. The main point of knowledge is the use of property animation.

If you are interested, you can implement it manually and have a deeper understanding of these two functions.

Pay attention to the public number: BennuCTech, get more dry goods!