ConstraintLayout 1.0.2 is released on May 7, 2017. ConstraintLayout 1.1.0 was released on April 12, 2018, nearly a year later. ConstraintLayout developers at Google say that after so much time, Not only are there so many new features in 1.1.0, but they also take the time to do things like ConstraintLayout preview on AndroidStudio. For our development, 1.1.0 has a lot of useful features, nuggets actually have a lot of articles in the introduction. Such as:

Explain the new features of ConstraintLayout 1.1

ConstraintLayout is new in 1.1.0

ConstraintLayout 1.1.1 Most detailed use

Today is mainly about Circle Position layout in 1.1.x.

1. If I had to write a circular layout before…

It used to be a lot of trouble to write a circular layout, you had to calculate sines, cosines. And those of you who are experienced remember that math.sin (num) is in radians, not angles. So we have to convert angles into radians, such as 90 degrees into π/2.

On top of that, if you have a circular layout and you have to animate it, it’s more complicated, and you have to deal with radii and orbits and so on.

For example, Hongyang wrote an article in early 2015 to create a dazzling circular menu in Android second second high imitation of the CIRCULAR menu of CCB, in order to achieve a circular menu, with a lot of mathematical calculation, I will excerpted part, we feel at will.


left = layoutRadius
		/ 2
		+ (int) Math.round(tmp
				* Math.cos(Math.toRadians(mStartAngle)) - 1 / 2f
				* cWidth);


return (float) (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);


Copy the code

2. Now there’s ConstraintLayout

Fortunately, we now have ConstraintLayout 1.1.0, making circular layouts super easy.

Now we can add the following three attributes to any child View in ConstraintLayout:

  • App :layout_constraintCircle – value is an ID. It’s a book View with this View id as the center
  • App :layout_constraintCircleAngle – Angle. It’s in degrees, not radians. That’s a lot more convenient.
  • App: layout_constraintCircleRadius – radius

For example: I now want the alarm button to be right of the Hamburger button, as shown below:

All we need to do is add three sentences to the fabAlarm FloatingActionBar:

<FloatingActionBar android:id="@+id/fabAlarm"
    app:layout_constraintCircle="@+id/fabHamburger"
    app:layout_constraintCircleRadius="100dp"
    app:layout_constraintCircleAngle="90"
    />
Copy the code

Also note that, in my tests, -45 degrees is not in the upper left corner of the center, and circleAngle only accepts positive numbers. So if you want a -45 degree effect, you should use 315 degrees.

3. Now make a circular menu animation

In the early days, there was an app called Path, which had a circular menu, which was relatively new at the time. Something like this:

(figure from making/saurabharora90 / MaterialArcMenu)

After that, the animation should be easy. Let’s analyze, several menus are 270 degrees, 300 degrees, 330 degrees, 360 degrees effect. And the whole pop-up effect is actually radius has been increasing the effect.

4. The XML layout

With this analysis done, let’s lay out the XML

<?xml version="1.0" encoding="utf-8"? >
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
                                             android:layout_width="match_parent" android:layout_height="match_parent"
                                             >

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabTotal"
        android:layout_width="55dp" android:layout_height="55dp"
        android:layout_margin="16dp"
        app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent"
        android:src="@drawable/ic_menu" android:tint="#fff"
        />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabMenuAlarm"
        android:layout_width="50dp" android:layout_height="50dp"
        app:layout_constraintCircle="@+id/fabTotal"
        app:layout_constraintCircleRadius="0dp"
        app:layout_constraintCircleAngle="0"
        android:src="@drawable/ic_alarm"  android:tint="#fff"
        android:visibility="invisible"
        />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabMenuAutorenew"
        android:layout_width="50dp" android:layout_height="50dp"
        app:layout_constraintCircle="@+id/fabTotal"
        app:layout_constraintCircleRadius="0dp"
        app:layout_constraintCircleAngle="315"
        android:src="@drawable/ic_autorenew"  android:tint="#fff"
        android:visibility="invisible"
        />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabMenuBuild"
        android:layout_width="50dp" android:layout_height="50dp"
        app:layout_constraintCircle="@+id/fabTotal"
        app:layout_constraintCircleRadius="0dp"
        app:layout_constraintCircleAngle="270"
        android:src="@drawable/ic_build"  android:tint="#fff"
        android:visibility="invisible"
        />

</android.support.constraint.ConstraintLayout>
Copy the code

5. Do the animation

Each time we click on the Fab in the center of the circle, we start the animation

    fun open(a) {
        startAnim(0.135.true)}private fun startAnim(start: Int, end: Int, isVisible: Boolean) {
        val endRadius = end.dp2px(this)  // An extension method to convert int to dp
        val anim = ValueAnimator.ofInt(start, endRadius)
        anim.duration = 1000
        anim.interpolator = BounceInterpolator()
        anim.addUpdateListener { valueAnimator ->
            val radius: Int = valueAnimator.animatedValue as Int
            menuViews.forEach { view ->
                val lp = view.layoutParams as ConstraintLayout.LayoutParams
                lp.circleRadius = radius
                view.layoutParams = lp
            }
        }
        anim.start()
    }


Copy the code

The key points are:

  1. The LayoutParams circleRadius do animation, from zero to the final end position.
  2. Interpolator to have a BounceInterpolator() effect at the end, we interpolator BounceInterpolator()

In the meantime, close the menu to use:

    fun close(a) {
        startAnim(135.0.false)}Copy the code

6. End result

The overall effect is a rough one because it is only a demo. ConstraintLayout is an example of how to animate a circle. Similar techniques can be used to create layouts and animations of solar system planets, for example.

ConstraintLayout, which is my point, in addition to reducing your layout size (which improves performance), is also very easy to animate. If cooperate ConstraintSet, ConstraintLayout LayoutParams, the Transition of these, it can use very little code to accomplish complex animation. I will continue to explain ConstraintLayout animation cases in this section, so stay tuned.