Issue
I have this ProgressBar
xml:
<ProgressBar
android:id="@+id/progressBar"
style="?android:progressBarStyleHorizontal"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginBottom="32dp"
android:progress="0"
android:progressDrawable="@drawable/bg_circular_progress_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:elevation="11dp"/>
As can be seen, the style="?android:progressBarStyleHorizontal"
specifies that it is a horizontal bar. However, with progressDrawable
property, I can somehow change its shape to circular with the following drawable file:
<?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="4dp"
android:useLevel="true">
<solid android:color="@color/colorPrimary" />
</shape>
- How does that drawable file change a horizontal thing into a circular thing and how does it decide how to animate the progress bar from 0degrees to 360degress forming a full ring when the progress is 100%? Also, is there a way to manipulate the start of the animation (like from 90degrees from the positive x-axis)?
- How do I make another custom shape, like a rectangle being filled from bottom to top with a background color (to signify the rectangle shape before being filled) that doesn't change?
Solution
- How does that drawable file change a horizontal thing into a circular thing and how does it decide how to animate the progress bar from 0degrees to 360degress forming a full ring when the progress is 100%?
When you specify style="?android:progressBarStyleHorizontal"
what you are really saying is that the ProgressBar will be deteminate. From the documentation for ProgressBar:
To indicate determinate progress, you set the style of the progress bar to
R.style.Widget_ProgressBar_Horizontal
and set the amount of progress.
By default, the ProgressBar will be horizontal but, as you noted, it can be changed to circular with your drawable file.
<shape
android:shape="ring"
android:innerRadiusRatio="2.5"
android:thickness="4dp"
android:useLevel="true">
<solid android:color="@color/colorPrimary" />
</shape>
Notice the line android:useLevel="true"
. This specifies that the drawable can accept a level that can range from 0 to 100. The drawable knows how much of itself to draw based upon the level set: 0 is to draw nothing and 100 is to draw 100%. By changing the progress, you are changing the level set for the drawable. Try setting android:useLevel="false"
to see what happens.
- Also, is there a way to manipulate the start of the animation (like from 90degrees from the positive x-axis)?
In the XML, set android:rotation="90"
to have the ring start at the bottom.
- How do I make another custom shape, like a rectangle being filled from bottom to top with a background color (to signify the rectangle shape before being filled) that doesn't change?
There are a couple (maybe more) ways to do this. One way is to define a layer-list drawable that defines the background rectangle and the progress rectangle that is a scale drawable. The ids must be as specified since ProgressBar relies upon them.
<layer-list>
<item
android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@android:color/darker_gray" />
</shape>
</item>
<item
android:id="@android:id/progress">
<scale
android:scaleHeight="100%"
android:scaleGravity="bottom">
<shape android:shape="rectangle">
<solid android:color="@android:color/holo_red_light" />
</shape>
</scale>
</item>
You could also use a clip drawable in a layer list:
<layer-list>
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@android:color/darker_gray" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip
android:clipOrientation="vertical"
android:gravity="bottom">
<shape android:shape="rectangle">
<solid android:color="@android:color/holo_red_light" />
</shape>
</clip>
</item>
</layer-list>
Here is a sample layout that puts this all together:
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progressBar"
style="?android:progressBarStyleHorizontal"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_marginTop="16dp"
android:progress="0"
android:progressDrawable="@drawable/bg_circular_progress_bar"
android:rotation="90"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintBottom_toTopOf="@+id/progressBar2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/progressBar2"
style="?android:progressBarStyleHorizontal"
android:layout_width="20dp"
android:layout_height="80dp"
android:layout_marginTop="16dp"
android:progress="0"
android:progressDrawable="@drawable/rectangular_progress_with_scale_drawable"
app:layout_constraintBottom_toTopOf="@+id/progressBar3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressBar" />
<ProgressBar
android:id="@+id/progressBar3"
style="?android:progressBarStyleHorizontal"
android:layout_width="20dp"
android:layout_height="80dp"
android:layout_marginTop="16dp"
android:progress="0"
android:progressDrawable="@drawable/rectangular_progress_with_clip_drawable"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressBar2" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="0/ 100"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressBar3" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:onClick="onClick"
android:text="Start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun onClick(view: View) {
view.isEnabled = false
var progress = 0
val handler = Handler()
Thread(Runnable {
while (progress < 100) {
progress += 5
handler.post {
progressBar.progress = progress
progressBar2.progress = progress
progressBar3.progress = progress
textView.text = "$progress/ ${progressBar.max}"
}
try {
Thread.sleep(100)
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
runOnUiThread { view.isEnabled = true }
}).start()
}
}
Answered By - Cheticamp
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.