Android, Aligning Views In a Circle Shape

Mert Çalışkanyürek
4 min readMay 20, 2022

I was creating a Passaparola game for android mobile. Aligning the views in a circle was harder than I thought. First, I tried to align views based on circle drawing algorithms but didn’t work well. Then I thought about manually aligning the views but that seemed too painful and didn’t feel right. After doing some deeper research, I found that the answer is much easier. Constraint Layout Circular Positioning was added in 1.1 and it saves your life when you want to align your views like this.

Let’s create a circle of circles for practice.

First, create a circle shape under the drawable folder. Right-click on drawable folder -> New -> Drawable Resource File. Choose any file name and change the Root element as shape.

Add to shape element android:shape=”oval” attribute. Then add a stroke with 1dp width and any color. The final XML code should look like this.

<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="1dp"
android:color="@color/purple_200"/>
</shape>

Create a dimen.xml file under the values folder to hold our circle radius and view size constants. Right-click on values folder -> New -> Values Resource File.

Add two dimen element; circle_radius and view_size. You can play with these parameters later. Dimens file should look like this;

<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="circle_radius">110dp</dimen>
<dimen name="view_size">32dp</dimen>
</resources>

Then we need a layout for our circle. Right-click on layout folder -> New -> Layout Resource File. Make sure the root element is ConstraintLayout.

Add a view to the center of this ConstraingLayout and give 1dp width and height. This is going to be the center point of our circle. Giving id attribute is a must.

<View
android:id="@+id/center"
android:layout_width="1dp"
android:layout_height="1dp"
android:layout_centerHorizontal="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Now, we need to calculate the angle between views. First, decide how many views will be positioned in our circle. To keep it simple we choose 8 views, therefore 360/8 = 45 is our angle.

Now we have an angle between views. We have to add each view by its angle. Add another view to the layout file. Give our background drawable. To position this view, we need three attributes. app:layout_constraintCircle to give the circle’s center, app:layout_constraintCircleAngle to indicate the view’s angle, app:layout_constraintCircleRadius to indicate the view’s distance from the center. The top middle view should look like this

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="0"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

Then we can add our other views with the same method by increasing the angle. Our second view’s angle should be 0+45 = 45, the thirds should be 45+45=90, the fourth’s should be 90+45=135, etc. and that’s it.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

<View
android:id="@+id/center"
android:layout_width="1dp"
android:layout_height="1dp"
android:layout_centerHorizontal="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="0"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="135"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="180"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="225"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="270"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

<View
android:layout_width="32dp"
android:layout_height="32dp"
android:background="@drawable/circle_background"
app:layout_constraintCircle="@id/center"
app:layout_constraintCircleAngle="315"
app:layout_constraintCircleRadius="@dimen/circle_radius"
/>

</androidx.constraintlayout.widget.ConstraintLayout>

Maybe we can create nice loading animation by changing the view’s angle and radius programmatically. Write a comment if it’s possible. I hope it helps, see you in the next article.

--

--