🚀 UllrichLumina

How to Create a circular progressbar in Android which rotates on it

How to Create a circular progressbar in Android which rotates on it

📅 | 📂 Category: Programming

In the dynamic world of mobile application development, user experience (UX) is paramount. A crucial element in maintaining user engagement during data loading or intensive operations is the progress indicator. While Android offers standard progress bars, developers often seek more distinctive and visually appealing solutions. Learning how to create a circular progressbar in Android which rotates on it not only enhances your app’s aesthetic but also provides a clear, intuitive visual cue that operations are ongoing, preventing user frustration and improving perceived performance. This guide will walk you through the process of crafting such a custom component, ensuring your application stands out.

Understanding Android’s Progress Indicators and Their Limitations

Android provides built-in ProgressBar widgets that can be styled as either linear or circular. For indeterminate operations—where the duration is unknown—a spinning circular progress bar is typically used. While these default options are functional, they are often generic and lack the unique branding or visual flair many modern applications require. Relying solely on the default can lead to a less polished user interface, failing to capture user attention or align with a specific app’s design language.

The standard ProgressBar is sufficient for basic needs, but for applications aiming for a premium feel or specific aesthetic, a custom solution becomes essential. This is particularly true when you want to create a circular progressbar in Android which rotates with a unique animation, color scheme, or integrated branding. Customizing allows for finer control over the animation speed, the path of the progress, and the visual elements that make up the indicator. This level of detail directly impacts user perception, making waiting times feel shorter and more engaging.

Moreover, default components sometimes lack the flexibility to handle complex progress animations or integrate seamlessly with intricate Material Design specifications beyond basic styling. Developers often turn to custom views to achieve specific visual effects, such as a progress bar that animates along a complex path or changes appearance based on specific states. This deeper level of customization is where the true power of Android’s UI toolkit shines, allowing for highly tailored Android UI elements.

Designing Your Custom Circular ProgressBar Layout

To create a truly custom circular progressbar in Android which rotates, you’ll typically start by defining its visual characteristics within an XML drawable or by extending Android’s View class directly. While a custom View offers the most flexibility, a drawable-based approach can be simpler for purely visual animations. For a rotating circular progress bar, a combination of a custom drawable and an animated background can be very effective. This involves defining the shape, colors, and stroke properties of the circle.

When designing the XML layout, consider creating a shape drawable that serves as the base of your circular progress bar. This drawable can define the thickness of the line, its color, and whether it’s a full circle or an arc. For instance, a <shape> tag with a <solid> or <gradient> and a <stroke> can form the visual foundation. You might also incorporate a <rotate> tag within an <animation-list> or use a <layer-list> to combine multiple elements that will rotate independently or together. This modular approach allows for complex visual effects that go beyond a simple spinning circle.

Key attributes to consider in your drawable include android:shape="oval" for the circle, android:thicknessRatio or android:thickness for the line width, and android:useLevel="false" if you’re creating an indeterminate progress bar that just spins continuously. For a determinate bar, android:useLevel="true" would be crucial. Defining these attributes carefully in your XML ensures that the visual representation of your progress indicator is precise and scalable across different device densities. This foundational work in XML is critical before delving into the animation logic.

  • Define base circle shape using <shape android:shape="oval">.
  • Specify stroke properties like color and width with <stroke>.
  • Utilize <gradient> for multi-color or animated segments.
  • Consider using a <layer-list> for complex multi-layered visuals.

Implementing the Rotation Logic in Kotlin/Java

To make a circular progressbar in Android which rotates dynamically, you’ll need to leverage Android’s animation framework, typically within a custom View or by applying an animation to a Drawable. The most robust approach for complex and smooth progress animation is to extend the View class and handle the drawing and animation logic programmatically. This gives you full control over the drawing canvas and the animation properties.

To create a rotating circular progress bar that is highly customizable, you can extend Android’s View class, override its onDraw() method to render the circular arc, and use a ValueAnimator to continuously update a rotation angle. By calling invalidate() after each animation step, you force the view to redraw itself with the new angle, creating a smooth, continuous spinning effect. This method provides superior control over the animation’s timing, interpolation, and visual properties, making it ideal for unique UI elements.

Within your custom View class (e.g., RotatingProgressBar), you’ll need a Paint object to draw the arc and a variable to store the current rotation angle. The onDraw(Canvas canvas) method is where you’ll perform the actual drawing. Before drawing Question & Answer :

I am trying to create a rounded progressbar. This is what I want to achieve

There is a grey color background ring. On top of it, a blue color progressbar appears which moves in a circular path from 0 to 360 in 60 or whatever amount of seconds.

enter image description here

Here is my example code.

<ProgressBar android:id="@+id/ProgressBar" android:layout_width="match_parent" android:layout_height="match_parent" style="?android:attr/progressBarStyleLarge" android:indeterminateDrawable="@drawable/progressBarBG" android:progress="50" /> 

To do this, in the drawable “progressBarBG”, I am creating a layerlist and inside that layer list I am giving two items as shown.

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <shape android:shape="ring" android:innerRadius="64dp" android:thickness="8dp" android:useLevel="false"> <solid android:color="@color/grey" /> </shape> </item> <item android:id="@android:id/progress"> <clip> <shape android:shape="ring" android:innerRadius="64dp" android:thickness="8dp" android:useLevel="false"> <solid android:color="@color/blue" /> </shape> </clip> </item> 

Now, the first grey ring is generated fine. The blue ring however starts from the left of the drawable and goes to the right just like how a linear progressbar works. This is how it shows at 50% progress with the red color arrow showing direction.

enter image description here

I want to move the blue progressbar in circular path as expected.

Here are my two solutions.

Short answer:

Instead of creating a layer-list, I separated it into two files. One for ProgressBar and one for its background.

This is the ProgressDrawable file (@drawable folder): circular_progress_bar.xml

<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="270" android:toDegrees="270"> <shape android:innerRadiusRatio="2.5" android:shape="ring" android:thickness="1dp" android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 --> <gradient android:angle="0" android:endColor="#007DD6" android:startColor="#007DD6" android:type="sweep" android:useLevel="false" /> </shape> </rotate> 

And this is for its background(@drawable folder): circle_shape.xml

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring" android:innerRadiusRatio="2.5" android:thickness="1dp" android:useLevel="false"> <solid android:color="#CCC" /> </shape> 

And at the end, inside the layout that you’re working:

<ProgressBar android:id="@+id/progressBar" android:layout_width="200dp" android:layout_height="200dp" android:indeterminate="false" android:progressDrawable="@drawable/circular_progress_bar" android:background="@drawable/circle_shape" style="?android:attr/progressBarStyleHorizontal" android:max="100" android:progress="65" /> 

Here’s the result:

result 1

Long Answer:

Use a custom view which inherits the android.view.View

result 2

Here is the full project on github