Progress bar with rounded corners?

I am trying to achieve this progress bar design: enter image description here

The current code that I have produces this: enter image description here

This is the code:

<item android:id="@android:id/background">
    <shape>
        <corners android:radius="8dp"/>
        <solid android:color="@color/dirtyWhite"/>
    </shape>
</item>

<item android:id="@android:id/progress">
    <clip>
        <shape>
            <corners android:radius="8dp"/>
            <solid android:color="@color/colorPrimaryDark"/>
        </shape>
    </clip>
</item>

My progress bar:

 <ProgressBar
            android:id="@+id/activeProgress"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:progress="10"
            android:progressDrawable="@drawable/rounded_corners_progress_bar"/>

I tried adding <size> attribute on the <shape> in <clip to make the progress shape a bit smaller but it did not work. Also, the progress bar is flat and I want to be curved as per design. What I need to change in order to achieve the design?


Solution 1:

How to make the progress shape a bit smaller?

You need to give the progress item a little padding, like so:

<item android:id="@android:id/progress"
    android:top="2dp"
    android:bottom="2dp"
    android:left="2dp"
    android:right="2dp">

How to make the progress bar to be curved as per design?

Replace the <clip></clip> element, with <scale android:scaleWidth="100%"></scale>. That will make the shape keep its form as it grows - and not cut off. Unfortunately, it will have a little unwanted visual effect at the beginning - as the shape corners don't have enough space to draw. But it might be good enough for most cases.

Full code:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
 <item android:id="@android:id/background">
    <shape>
        <corners android:radius="8dp"/>
        <solid android:color="@color/dirtyWhite"/>
    </shape>
 </item>

 <item android:id="@android:id/progress"
    android:top="1dp"
    android:bottom="1dp"
    android:left="1dp"
    android:right="1dp">

    <scale android:scaleWidth="100%">
        <shape>
            <corners android:radius="8dp"/>
            <solid android:color="@color/colorPrimaryDark"/>
        </shape>
    </scale>
 </item>
</layer-list>

Solution 2:

With the Material Components Library you can use the LinearProgressIndicator and the app:trackCornerRadius attribute.
Something like:

    <com.google.android.material.progressindicator.LinearProgressIndicator
        android:indeterminate="true"
        app:trackThickness="xxdp"
        app:trackCornerRadius="xdp"/>

enter image description here

It works also for the determinate progress indicator removing the android:indeterminate="true" or using android:indeterminate="false"

Note: it requires at least the version 1.3.0.

Solution 3:

Thanks to Georgi Koemdzhiev for a nice question and images. For those who want to make similar to his, do the following.

1) Create a background for a ProgressBar.

progress_bar_background.xml:

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

2) Create a scale for the ProgressBar.

curved_progress_bar.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="2dp" />
            <solid android:color="@color/transparent" />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="2dp" />
                <solid android:color="#ffff00" />
            </shape>
        </clip>
    </item>
</layer-list>

3) In layout file add the ProgressBar.

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="6dp"
    android:layout_marginStart="20dp"
    android:layout_marginTop="10dp"
    android:layout_marginEnd="20dp"
    android:background="@drawable/progress_bar_background"
    >

    <ProgressBar
        android:id="@+id/progress_bar"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="4dp"
        android:layout_margin="1dp"
        android:indeterminate="false"
        android:progressDrawable="@drawable/curved_progress_bar"
        />

</FrameLayout>

Solution 4:

The code produce following progress bar
You can achieve progress bar with both inner progress color ,border color,empty progress with transparent color.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
    <shape>
        <corners android:radius="15dip" />
        <stroke android:width="1dp" android:color="@color/black" />
    </shape>
</item>

<item android:id="@android:id/secondaryProgress">
    <clip>
        <shape>
            <corners android:radius="5dip" />
            <gradient
                android:startColor="@color/black"
                android:centerColor="@color/trans"
                android:centerY="0.75"
                android:endColor="@color/black"
                android:angle="270"

                />
        </shape>
    </clip>
 </item>


 <item
    android:id="@android:id/progress"
    >
    <clip>
        <shape>
            <corners
                android:radius="5dip" />
            <gradient
                android:startColor="@color/black"
                android:endColor="@color/black"
                android:angle="270" />
        </shape>
    </clip>
 </item>
 </layer-list>

Solution 5:

<com.google.android.material.progressindicator.LinearProgressIndicator
                android:id="@+id/pb_team2"
                android:layout_width="0dp"
                android:layout_height="8dp"
                android:layout_marginStart="55dp"
                android:layout_marginEnd="15dp"
                app:trackColor="#E0E0E0"
                app:trackCornerRadius="6dp"
                app:trackThickness="8dp"
                android:progress="2"
                app:indicatorColor="@color/red"
                android:scaleX="-1"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@id/tv_versus"
                app:layout_constraintTop_toBottomOf="@id/tv_team2_score" />