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.
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.
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:
Long Answer:
Use a custom view which inherits the android.view.View
Here is the full project on github
With the Material Components Library you can use the CircularProgressIndicator:
Something like:
<com.google.android.material.progressindicator.CircularProgressIndicator
app:indicatorColor="#color/...."
app:trackColor="#color/...."
app:indicatorSize="64dp"/>
You can use these attributes:
indicatorSize: defines the radius of the circular progress indicator
trackColor: the color used for the progress track. If not defined, it will be set to the indicatorColor and apply the android:disabledAlpha from the theme.
indicatorColor: the single color used for the indicator in determinate/indeterminate mode. By default it uses theme primary color
Use progressIndicator.setProgressCompat((int) value, true); to update the value in the indicator.
Note: it requires at least the version 1.3.0-alpha04.
I have done with easy way:
Please check screen shot for the same.
CustomProgressBarActivity.java:
public class CustomProgressBarActivity extends AppCompatActivity {
private TextView txtProgress;
private ProgressBar progressBar;
private int pStatus = 0;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_progressbar);
txtProgress = (TextView) findViewById(R.id.txtProgress);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
new Thread(new Runnable() {
#Override
public void run() {
while (pStatus <= 100) {
handler.post(new Runnable() {
#Override
public void run() {
progressBar.setProgress(pStatus);
txtProgress.setText(pStatus + " %");
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
pStatus++;
}
}
}).start();
}
}
activity_custom_progressbar.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.skholingua.android.custom_progressbar_circular.MainActivity" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:layout_height="wrap_content">
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerInParent="true"
android:indeterminate="false"
android:max="100"
android:progress="0"
android:progressDrawable="#drawable/custom_progressbar_drawable"
android:secondaryProgress="0" />
<TextView
android:id="#+id/txtProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/progressBar"
android:layout_centerInParent="true"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</RelativeLayout>
custom_progressbar_drawable.xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="-90"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="270" >
<shape
android:shape="ring"
android:useLevel="false" >
<gradient
android:centerY="0.5"
android:endColor="#FA5858"
android:startColor="#0099CC"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
Hope this will help you.
I have written detailed example on circular progress bar in android here on my blog demonuts.com. You can also fond full source code and explanation there.
Here's how I made circular progressbar with percentage inside circle in pure code without any library.
first create a drawable file called circular.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/secondaryProgress">
<shape
android:innerRadiusRatio="6"
android:shape="ring"
android:thicknessRatio="20.0"
android:useLevel="true">
<gradient
android:centerColor="#999999"
android:endColor="#999999"
android:startColor="#999999"
android:type="sweep" />
</shape>
</item>
<item android:id="#android:id/progress">
<rotate
android:fromDegrees="270"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="270">
<shape
android:innerRadiusRatio="6"
android:shape="ring"
android:thicknessRatio="20.0"
android:useLevel="true">
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<gradient
android:centerColor="#00FF00"
android:endColor="#00FF00"
android:startColor="#00FF00"
android:type="sweep" />
</shape>
</rotate>
</item>
</layer-list>
Now in your activity_main.xml add following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/dialog"
tools:context="com.example.parsaniahardik.progressanimation.MainActivity">
<ProgressBar
android:id="#+id/circularProgressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="250dp"
android:layout_height="250dp"
android:indeterminate="false"
android:max="100"
android:progress="50"
android:layout_centerInParent="true"
android:progressDrawable="#drawable/circular"
android:secondaryProgress="100"
/>
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:background="#drawable/whitecircle"
android:layout_centerInParent="true"/>
<TextView
android:id="#+id/tv"
android:layout_width="250dp"
android:layout_height="250dp"
android:gravity="center"
android:text="25%"
android:layout_centerInParent="true"
android:textColor="#color/colorPrimaryDark"
android:textSize="20sp" />
</RelativeLayout>
In activity_main.xml I have used one circular image with white background to show white background around percentage. Here is the image:
You can change color of this image to set custom color around percentage text.
Now finally add following code to MainActivity.java :
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.DecelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int pStatus = 0;
private Handler handler = new Handler();
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.circular);
final ProgressBar mProgress = (ProgressBar) findViewById(R.id.circularProgressbar);
mProgress.setProgress(0); // Main Progress
mProgress.setSecondaryProgress(100); // Secondary Progress
mProgress.setMax(100); // Maximum Progress
mProgress.setProgressDrawable(drawable);
/* ObjectAnimator animation = ObjectAnimator.ofInt(mProgress, "progress", 0, 100);
animation.setDuration(50000);
animation.setInterpolator(new DecelerateInterpolator());
animation.start();*/
tv = (TextView) findViewById(R.id.tv);
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (pStatus < 100) {
pStatus += 1;
handler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
mProgress.setProgress(pStatus);
tv.setText(pStatus + "%");
}
});
try {
// Sleep for 200 milliseconds.
// Just to display the progress slowly
Thread.sleep(8); //thread will take approx 1.5 seconds to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
If you want to make horizontal progressbar, follow this link, it has many valuable examples with source code:
http://www.skholingua.com/android-basic/user-interface/form-widgets/progressbar
I realized a Open Source library on GitHub CircularProgressBar that does exactly what you want the simplest way possible:
USAGE
To make a circular ProgressBar add CircularProgressBar in your layout XML and add CircularProgressBar library in your projector or you can also grab it via Gradle:
compile 'com.mikhaellopez:circularprogressbar:1.0.0'
XML
<com.mikhaellopez.circularprogressbar.CircularProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:background_progressbar_color="#FFCDD2"
app:background_progressbar_width="5dp"
app:progressbar_color="#F44336"
app:progressbar_width="10dp" />
You must use the following properties in your XML to change your CircularProgressBar.
Properties:
app:progress (integer) >> default 0
app:progressbar_color (color) >> default BLACK
app:background_progressbar_color (color) >> default GRAY
app:progressbar_width (dimension) >> default 7dp
app:background_progressbar_width (dimension) >> default 3dp
JAVA
CircularProgressBar circularProgressBar = (CircularProgressBar)findViewById(R.id.yourCircularProgressbar);
circularProgressBar.setColor(ContextCompat.getColor(this, R.color.progressBarColor));
circularProgressBar.setBackgroundColor(ContextCompat.getColor(this, R.color.backgroundProgressBarColor));
circularProgressBar.setProgressBarWidth(getResources().getDimension(R.dimen.progressBarWidth));
circularProgressBar.setBackgroundProgressBarWidth(getResources().getDimension(R.dimen.backgroundProgressBarWidth));
int animationDuration = 2500; // 2500ms = 2,5s
circularProgressBar.setProgressWithAnimation(65, animationDuration); // Default duration = 1500ms
Fork or Download this library here >> https://github.com/lopspower/CircularProgressBar
Here is a simple customview for display circle progress. You can modify and optimize more to suitable for your project.
class CircleProgressBar #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val backgroundWidth = 10f
private val progressWidth = 20f
private val backgroundPaint = Paint().apply {
color = Color.LTGRAY
style = Paint.Style.STROKE
strokeWidth = backgroundWidth
isAntiAlias = true
}
private val progressPaint = Paint().apply {
color = Color.RED
style = Paint.Style.STROKE
strokeWidth = progressWidth
isAntiAlias = true
}
var progress: Float = 0f
set(value) {
field = value
invalidate()
}
private val oval = RectF()
private var centerX: Float = 0f
private var centerY: Float = 0f
private var radius: Float = 0f
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
centerX = w.toFloat() / 2
centerY = h.toFloat() / 2
radius = w.toFloat() / 2 - progressWidth
oval.set(centerX - radius,
centerY - radius,
centerX + radius,
centerY + radius)
super.onSizeChanged(w, h, oldw, oldh)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawCircle(centerX, centerY, radius, backgroundPaint)
canvas?.drawArc(oval, 270f, 360f * progress, false, progressPaint)
}
}
Example using
xml
<com.example.androidcircleprogressbar.CircleProgressBar
android:id="#+id/circle_progress"
android:layout_width="200dp"
android:layout_height="200dp" />
kotlin
class MainActivity : AppCompatActivity() {
val TOTAL_TIME = 10 * 1000L
override fun onCreate(savedInstanceState: Bundle?) {
...
timeOutRemoveTimer.start()
}
private var timeOutRemoveTimer = object : CountDownTimer(TOTAL_TIME, 10) {
override fun onFinish() {
circle_progress.progress = 1f
}
override fun onTick(millisUntilFinished: Long) {
circle_progress.progress = (TOTAL_TIME - millisUntilFinished).toFloat() / TOTAL_TIME
}
}
}
Result
I'm new so I can't comment but thought to share the lazy fix. I use Pedram's original approach as well, and just ran into the same Lollipop issue. But alanv over in another post had a one line fix. Its some kind of bug or oversight in API21. Literally just add android:useLevel="true" to your circle progress xml. Pedram's new approach is still the proper fix, but I just thought I share the lazy fix as well.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="#+id/progress_circular_id"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerInParent="true"
android:indeterminate="false"
android:progress="30"
android:progressDrawable="#drawable/circular_progress_bar"
android:background="#drawable/circle_shape"
style="?android:attr/progressBarStyleHorizontal"
android:max="100">
</ProgressBar>
<TextView
android:id="#+id/textview_progress_status_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50%"
android:layout_centerInParent="true"
android:textStyle="bold"
android:textColor="#color/blue"
android:textSize="35dp">
</TextView>
<Button
android:id="#+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="click me"
android:textColor="#color/white"
android:layout_below="#+id/progress_circular_id"
android:layout_centerHorizontal="true"
>
</Button>
</RelativeLayout>
Create a Drawable File with name 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="25dp"
android:useLevel="false">
<solid android:color="#CCC" />
</shape>
Create a file with 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="25dp"
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>
In java File For example purpose used fragmet.
public class FragmentRegistration extends BaseFragmentHelper {
View registrationFragmentView;
ProgressBar progressBar;
Button button;
int count=0;
#Override
public void onAttachFragment(#NonNull Fragment childFragment) {
super.onAttachFragment(childFragment);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
registrationFragmentView = inflater.inflate(R.layout.new_device_registration, container, false);
progressBar=(ProgressBar)registrationFragmentView.findViewById(R.id.progress_circular_id);
button=(Button) registrationFragmentView.findViewById(R.id.check);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
count=count+10;
progressBar.setProgress(count);
}
});
return registrationFragmentView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onDetach() {
super.onDetach();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
}
try this method to create a bitmap and set it to image view.
private void circularImageBar(ImageView iv2, int i) {
Bitmap b = Bitmap.createBitmap(300, 300,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
Paint paint = new Paint();
paint.setColor(Color.parseColor("#c4c4c4"));
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(150, 150, 140, paint);
paint.setColor(Color.parseColor("#FFDB4C"));
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.FILL);
final RectF oval = new RectF();
paint.setStyle(Paint.Style.STROKE);
oval.set(10,10,290,290);
canvas.drawArc(oval, 270, ((i*360)/100), false, paint);
paint.setStrokeWidth(0);
paint.setTextAlign(Align.CENTER);
paint.setColor(Color.parseColor("#8E8E93"));
paint.setTextSize(140);
canvas.drawText(""+i, 150, 150+(paint.getTextSize()/3), paint);
iv2.setImageBitmap(b);
}
#Pedram, your old solution works actually fine in lollipop too (and better than new one since it's usable everywhere, including in remote views) just change your circular_progress_bar.xml code to this:
<?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"> <!-- Just add this line -->
<gradient
android:angle="0"
android:endColor="#007DD6"
android:startColor="#007DD6"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
https://github.com/passsy/android-HoloCircularProgressBar is one example of a library that does this. As Tenfour04 stated, it will have to be somewhat custom, in that this is not supported directly out of the box. If this library doesn't behave as you wish, you can fork it and modify the details to make it work to your liking. If you implement something that others can then reuse, you could even submit a pull request to get that merged back in!
Change
android:useLevel="false"
to
android:useLevel="true"
for second sahpe with id="#android:id/progress
hope it works
package com.example.ankitrajpoot.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
public class MainActivity extends Activity {
private ProgressBar spinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner=(ProgressBar)findViewById(R.id.progressBar);
spinner.setVisibility(View.VISIBLE);
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/loadingPanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="48dp"
style="?android:attr/progressBarStyleLarge"
android:layout_height="48dp"
android:indeterminateDrawable="#drawable/circular_progress_bar"
android:indeterminate="true" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="1080">
<shape
android:shape="ring"
android:innerRadiusRatio="3"
android:thicknessRatio="8"
android:useLevel="false">
<size
android:width="56dip"
android:height="56dip" />
<gradient
android:type="sweep"
android:useLevel="false"
android:startColor="#android:color/transparent"
android:endColor="#1e9dff"
android:angle="0"
/>
</shape>
</rotate>
Good news is that now material design library supports determinate circular progress bars too:
<com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
For more info about this refer here.
if you want to set progress in an anti-clock direction then use below image for set fromDegree and toDegree's values in progressDrawble xml.
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="-90">
<shape
android:innerRadiusRatio="2"
android:shape="ring"
android:thickness="1dp">
<gradient
android:angle="0"
android:endColor="#007DD6"
android:startColor="#007DD6"
android:type="sweep" />
</shape>
</rotate>
This code will let your progress anti-clockwise and from the top.
Change the degrees as per the above image from where you want to rotate your progress bar.
You can use this library https://github.com/xYinKio/ArcCircleProgressBar
This is one of the most flexible circular progress bars
This picture is showing the lib powers
Related
I have a custom seekbar with drawable and it is working fine, i am trying to make tooltip text on user action over the seekbar, is there any way without using third party library, i have posted the code below which i am using for custom seekbar
i have also attached a sample progress tooltip that i would like to achieve below
any reference or solution would be appreciated
implementation "com.android.support:appcompat-v7:${android_support_version}"
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) {
seekBar.setThumb(getThumb(progressValue));
TooltipCompat.setTooltipText(seekBar, String.valueOf(progressValue));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
//Do nothing
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
//Do nothing
}
});
private Drawable getThumb(int progress) {
View thumbView = LayoutInflater.from(getActivity()).inflate(R.layout.seekbar_tv, null, false);
((TextView) thumbView.findViewById(R.id.tvProgress)).setText(progress + "");
thumbView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
Bitmap bitmap = Bitmap.createBitmap(thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
thumbView.layout(0, 0, thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight());
thumbView.draw(canvas);
return new BitmapDrawable(getResources(), bitmap);
}
<!--mySeekBarInLayout-->
<SeekBar
android:id="#+id/seekBar_Experience"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progressDrawable="#drawable/survey_seekbar_style"
android:splitTrack="false"
android:thumb="#drawable/survey_seekbar_thum" />
<!--survey_seekbar_thum-->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#color/circle_yellow"/>
<size
android:width="30dp"
android:height="30dp"/>
</shape>
</item>
</layer-list>
<!--survey_seekbar_style-->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#android:id/background"
android:drawable="#drawable/survey_border_shadow"
android:height="1dp"
android:gravity="center">
</item>
<item
android:id="#android:id/progress"
android:height="4dp"
android:gravity="center">
<clip android:drawable="#drawable/survey_seekbar_progress" />
</item>
</layer-list>
<!--survey_border_shadow-->
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:endColor="#color/thr_dark_blue"
android:startColor="#color/thr_dark_blue" />
</shape>
</item>
</layer-list>
<!--survey_seekbar_progress-->
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/progressshape" >
<clip>
<shape
android:shape="rectangle" >
<size android:height="3dp"/>
<corners
android:radius="5dp" />
<solid android:color="#color/thr_dark_blue"/>
</shape>
</clip>
</item>
</layer-list>
You should have your customized textview and change the text inside onProgressChanged.
Is that enough? ==> No
You need to change the x coordinate of the textview to change it's place to be compatible with seekbar place.
Code demonstrate that:
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
yourTextView.setText(progress + " miles");
// Get the thumb bound and get its left value
int x = seekBar.getThumb().getBounds().left;
// set the left value to textview x value
yourTextView.setX(x);
}
You can do the following:
1) MainActivity.class:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private SeekBar sb;
private RelativeLayout rlMarker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sb = (SeekBar) findViewById(R.id.sb);
rlMarker = (RelativeLayout) findViewById(R.id.rlMarker);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
updateMarker(sb, rlMarker, (i + " miles"));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
rlMarker.setVisibility(View.VISIBLE);
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
rlMarker.setVisibility(View.GONE);
}
});
//initialize
updateMarker(sb, rlMarker, "0 miles");
}
private void updateMarker(final SeekBar sb,
View rlMarker,
String message) {
final TextView tvProgress = (TextView) rlMarker.findViewById(R.id.tvProgress);
final View vArrow = (View) rlMarker.findViewById(R.id.vArrow);
/**
* According to this question:
* https://stackoverflow.com/questions/20493577/android-seekbar-thumb-position-in-pixel
* one can find the SeekBar thumb location in pixels using:
*/
int width = sb.getWidth()
- sb.getPaddingLeft()
- sb.getPaddingRight();
final int thumbPos = sb.getPaddingLeft()
+ width
* sb.getProgress()
/ sb.getMax() +
//take into consideration the margin added (in this case it is 10dp)
Math.round(convertDpToPixel(10, MainActivity.this));
tvProgress.setText(message);
tvProgress.post(new Runnable() {
#Override
public void run() {
final Display display = ((WindowManager) MainActivity.this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
final Point deviceDisplay = new Point();
display.getSize(deviceDisplay);
//vArrow always follow seekBar thumb location
vArrow.setX(thumbPos - sb.getThumbOffset());
//unlike vArrow, tvProgress will not always follow seekBar thumb location
if ((thumbPos - tvProgress.getWidth() / 2 - sb.getPaddingLeft()) < 0) {
//part of the tvProgress is to the left of 0 bound
tvProgress.setX(vArrow.getX() - 20);
} else if ((thumbPos + tvProgress.getWidth() / 2 + sb.getPaddingRight()) > deviceDisplay.x) {
//part of the tvProgress is to the right of screen width bound
tvProgress.setX(vArrow.getX() - tvProgress.getWidth() + 20 + vArrow.getWidth());
} else {
//tvProgress is between 0 and screen width bounds
tvProgress.setX(thumbPos - tvProgress.getWidth() / 2f);
}
}
});
}
/**
* According to this question:
* https://stackoverflow.com/questions/4605527/converting-pixels-to-dp
* one can convert dp to pixels using the following method:
*/
public static float convertDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return px;
}
}
2) activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimaryDark"
android:textSize="40sp"
android:layout_alignParentTop="true"
android:gravity="center"
android:text="Top"
android:layout_above="#id/v"
android:textColor="#android:color/white"/>
<include
layout="#layout/marker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_above="#id/v">
</include>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="#id/sb"
android:id="#+id/v">
</View>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/sb"
android:layout_centerInParent="true"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:max="100"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:textSize="40sp"
android:gravity="center"
android:text="Bottom"
android:layout_below="#id/sb"
android:layout_alignParentBottom="true"
android:textColor="#android:color/white"/>
</RelativeLayout>
3) marker.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:id="#+id/rlMarker">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvProgress"
android:gravity="center"
android:padding="10dp"
android:textColor="#android:color/white"
android:background="#drawable/marker_shape"
android:text="0 miles"/>
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:id="#+id/vArrow"
android:gravity="center"
android:rotation="180"
android:layout_below="#id/tvProgress"
android:background="#drawable/marker_arrow_shape"/>
</RelativeLayout>
4) marker_shape.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%">
<shape>
<solid
android:shape="rectangle"
android:color="#color/colorAccent" />
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="5dp"
android:topRightRadius="5dp"/>
</shape>
</rotate>
</item>
</layer-list>
5) marker_arrow_shape.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="-40%"
android:pivotY="87%">
<shape>
<solid
android:shape="rectangle"
android:color="#color/colorAccent" />
</shape>
</rotate>
</item>
</layer-list>
6) Result:
I have a custom progress bar that looks like this:
Here's the .xml code I've used to create it:
background_drawable.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="#dimen/progress_bar_radial_inner_radius"
android:thickness="#dimen/progress_bar_radial_thickness"
android:shape="ring"
android:useLevel="false" >
<solid android:color="#color/main_color_alpha"/>
</shape>
progress_drawable.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:innerRadius="#dimen/progress_bar_radial_inner_radius"
android:thickness="#dimen/progress_bar_radial_thickness"
android:shape="ring" >
<solid android:color="#color/main_color"/>
</shape>
</rotate>
What I want to get is a round corners for the ring that I use to show progress. Something that would look like this:
Does someone has any idea on how this can be achieved?
I was able to achieve this using a layer list, and adding a dot to each side of the line. The first one will be stuck at the top, while the second one will follow the progress as an inset is added inside a rotate element. You will have to adjust it according to the size of your progressbar layout though. Mine is 250dp x 250dp.
progress_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate android:fromDegrees="270" android:toDegrees="270">
<shape
android:innerRadiusRatio="2.55"
android:shape="ring"
android:thickness="15dp"
android:useLevel="true">
<solid android:color="#color/main_color" />
</shape>
</rotate>
</item>
<item android:bottom="211dp">
<shape
android:innerRadiusRatio="1000"
android:shape="ring"
android:thickness="7dp"
android:useLevel="false">
<solid android:color="#color/main_color" />
</shape>
</item>
<item>
<rotate>
<inset android:insetBottom="211dp">
<shape
android:innerRadiusRatio="1000"
android:shape="ring"
android:thickness="7dp"
android:useLevel="false">
<solid android:color="#color/main_color" />
</shape>
</inset>
</rotate>
</item>
</layer-list>
Well, I searched a lot about that before.
The only solution I found was a library on GitHub check here
Go through this code hope this will help you
>ProgressBarActivity.java
public class ProgressBarActivity extends AppCompatActivity {
private TextView txtProgress;
private ProgressBar progressBar;
private int pStatus = 0;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progress);
txtProgress = (TextView) findViewById(R.id.txtProgress);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
new Thread(new Runnable() {
#Override
public void run() {
while (pStatus <= 100) {
handler.post(new Runnable() {
#Override
public void run() {
progressBar.setProgress(pStatus);
txtProgress.setText(pStatus + " %");
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
pStatus++;
}
}
}).start();
}
}
> activity_progress.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.placio.android.custom_progressbar_circular.MainActivity" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:layout_height="wrap_content">
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerInParent="true"
android:indeterminate="false"
android:max="100"
android:progress="0"
android:progressDrawable="#drawable/progress_drawable"
android:secondaryProgress="0" />
<TextView
android:id="#+id/txtProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/progressBar"
android:layout_centerInParent="true"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</RelativeLayout>
> progress_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="-90"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="270" >
Ok, the easiest way I've found to do what I want is to draw progress arc on canvas instead of using progress_drawable.xml.
Here's my code in case someone has similar issue.
class RadialProgressBar : ProgressBar {
private val thickness = 28f
private val halfThickness = thickness / 2
private val startAngle = 270f
private var boundsF: RectF? = null
private lateinit var paint: Paint
constructor(context: Context?) : super(context) {
init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
init()
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
private fun init() {
paint = Paint()
paint.isAntiAlias = true
paint.style = Paint.Style.STROKE
paint.strokeWidth = thickness
paint.strokeCap = Paint.Cap.ROUND
paint.color = ContextCompat.getColor(context, R.color.main_color)
progressDrawable = null
}
override fun draw(canvas: Canvas?) {
super.draw(canvas)
if (boundsF == null) {
boundsF = RectF(background.bounds)
boundsF?.inset(halfThickness, halfThickness)
}
canvas?.drawArc(boundsF, startAngle, progress * 3.60f, false, paint)
}
}
I am working on an app in which I want to show a ProgressBar, but I want to replace the default Android ProgressBar.
So how can I customize the ProgressBar?
Do I need some graphics and animation for that?
I read the following post but could not get it to work:
Custom Progress bar Android
Customizing a ProgressBar requires defining the attribute or properties for the background and progress of your progress bar.
Create an XML file named customprogressbar.xml in your res->drawable folder:
custom_progressbar.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Define the background properties like color etc -->
<item android:id="#android:id/background">
<shape>
<gradient
android:startColor="#000001"
android:centerColor="#0b131e"
android:centerY="1.0"
android:endColor="#0d1522"
android:angle="270"
/>
</shape>
</item>
<!-- Define the progress properties like start color, end color etc -->
<item android:id="#android:id/progress">
<clip>
<shape>
<gradient
android:startColor="#007A00"
android:centerColor="#007A00"
android:centerY="1.0"
android:endColor="#06101d"
android:angle="270"
/>
</shape>
</clip>
</item>
</layer-list>
Now you need to set the progressDrawable property in customprogressbar.xml (drawable)
You can do this in the XML file or in the Activity (at run time).
Do the following in your XML:
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:progressDrawable="#drawable/custom_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
At run time do the following
// Get the Drawable custom_progressbar
Drawable draw=res.getDrawable(R.drawable.custom_progressbar);
// set the drawable as progress drawable
progressBar.setProgressDrawable(draw);
Edit: corrected xml layout
In case of complex ProgressBar like this,
use ClipDrawable.
NOTE : I've not used ProgressBar here in this example. I've achieved
this using ClipDrawable by clipping image with Animation.
A Drawable that clips another Drawable based on this Drawable's current level value. You can control how much the child Drawable gets clipped in width and height based on the level, as well as a gravity to control where it is placed in its overall container. Most often used to implement things like progress bars, by increasing the drawable's level with setLevel().
NOTE : The drawable is clipped completely and not visible when the level is 0
and fully revealed when the level is 10,000.
I've used this two images to make this CustomProgressBar.
scall.png
ballon_progress.png
MainActivity.java
public class MainActivity extends ActionBarActivity {
private EditText etPercent;
private ClipDrawable mImageDrawable;
// a field in your class
private int mLevel = 0;
private int fromLevel = 0;
private int toLevel = 0;
public static final int MAX_LEVEL = 10000;
public static final int LEVEL_DIFF = 100;
public static final int DELAY = 30;
private Handler mUpHandler = new Handler();
private Runnable animateUpImage = new Runnable() {
#Override
public void run() {
doTheUpAnimation(fromLevel, toLevel);
}
};
private Handler mDownHandler = new Handler();
private Runnable animateDownImage = new Runnable() {
#Override
public void run() {
doTheDownAnimation(fromLevel, toLevel);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etPercent = (EditText) findViewById(R.id.etPercent);
ImageView img = (ImageView) findViewById(R.id.imageView1);
mImageDrawable = (ClipDrawable) img.getDrawable();
mImageDrawable.setLevel(0);
}
private void doTheUpAnimation(int fromLevel, int toLevel) {
mLevel += LEVEL_DIFF;
mImageDrawable.setLevel(mLevel);
if (mLevel <= toLevel) {
mUpHandler.postDelayed(animateUpImage, DELAY);
} else {
mUpHandler.removeCallbacks(animateUpImage);
MainActivity.this.fromLevel = toLevel;
}
}
private void doTheDownAnimation(int fromLevel, int toLevel) {
mLevel -= LEVEL_DIFF;
mImageDrawable.setLevel(mLevel);
if (mLevel >= toLevel) {
mDownHandler.postDelayed(animateDownImage, DELAY);
} else {
mDownHandler.removeCallbacks(animateDownImage);
MainActivity.this.fromLevel = toLevel;
}
}
public void onClickOk(View v) {
int temp_level = ((Integer.parseInt(etPercent.getText().toString())) * MAX_LEVEL) / 100;
if (toLevel == temp_level || temp_level > MAX_LEVEL) {
return;
}
toLevel = (temp_level <= MAX_LEVEL) ? temp_level : toLevel;
if (toLevel > fromLevel) {
// cancel previous process first
mDownHandler.removeCallbacks(animateDownImage);
MainActivity.this.fromLevel = toLevel;
mUpHandler.post(animateUpImage);
} else {
// cancel previous process first
mUpHandler.removeCallbacks(animateUpImage);
MainActivity.this.fromLevel = toLevel;
mDownHandler.post(animateDownImage);
}
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="#+id/etPercent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number"
android:maxLength="3" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ok"
android:onClick="onClickOk" />
</LinearLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageView
android:id="#+id/imageView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/scall" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/clip_source" />
</FrameLayout>
clip_source.xml
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="#drawable/ballon_progress"
android:gravity="bottom" />
In case of complex HorizontalProgressBar just change cliporientation in clip_source.xml like this,
android:clipOrientation="horizontal"
You can download complete demo from here.
in your xml
<ProgressBar
android:id="#+id/progressBar1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="#style/CustomProgressBar"
android:layout_margin="5dip" />
And in res/values/styles.xml:
<resources>
<style name="CustomProgressBar" parent="android:Widget.ProgressBar.Horizontal">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">#drawable/custom_progress_bar_horizontal</item>
<item name="android:minHeight">10dip</item>
<item name="android:maxHeight">20dip</item>
</style>
<style name="AppTheme" parent="android:Theme.Light" />
</resources>
And custom_progress_bar_horizontal is a xml stored in drawable folder which defines your custom progress bar. For more detail see this blog.
I hope this will help you.
There are two types of progress bars called determinate progress bar (fixed duration) and indeterminate progress bar (unknown duration).
Drawables for both of types of progress bar can be customized by defining drawable as xml resource. You can find more information about progress bar styles and customization at http://www.zoftino.com/android-progressbar-and-custom-progressbar-examples.
Customizing fixed or horizontal progress bar :
Below xml is a drawable resource for horizontal progress bar customization.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background"
android:gravity="center_vertical|fill_horizontal">
<shape android:shape="rectangle"
android:tint="?attr/colorControlNormal">
<corners android:radius="8dp"/>
<size android:height="20dp" />
<solid android:color="#90caf9" />
</shape>
</item>
<item android:id="#android:id/progress"
android:gravity="center_vertical|fill_horizontal">
<scale android:scaleWidth="100%">
<shape android:shape="rectangle"
android:tint="?attr/colorControlActivated">
<corners android:radius="8dp"/>
<size android:height="20dp" />
<solid android:color="#b9f6ca" />
</shape>
</scale>
</item>
</layer-list>
Customizing indeterminate progress bar
Below xml is a drawable resource for circular progress bar customization.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/progress"
android:top="16dp"
android:bottom="16dp">
<rotate
android:fromDegrees="45"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="315">
<shape android:shape="rectangle">
<size
android:width="80dp"
android:height="80dp" />
<stroke
android:width="6dp"
android:color="#b71c1c" />
</shape>
</rotate>
</item>
</layer-list>
Customizing the color of progressbar namely in case of spinner type needs an xml file and initiating codes in their respective java files.
Create an xml file and name it as progressbar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
tools:context=".Radio_Activity" >
<LinearLayout
android:id="#+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ProgressBar
android:id="#+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ProgressBar>
</LinearLayout>
</LinearLayout>
Use the following code to get the spinner in various expected color.Here we use the hexcode to display spinner in blue color.
Progressbar spinner = (ProgressBar) progrees.findViewById(R.id.spinner);
spinner.getIndeterminateDrawable().setColorFilter(Color.parseColor("#80DAEB"),
android.graphics.PorterDuff.Mode.MULTIPLY);
For using custom drawable:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:drawable="#drawable/my_drawable"
android:pivotX="50%"
android:pivotY="50%" />
(add under res/drawable progress.xml). my_drawable may be xml, png
Then in your layout use
<ProgressBar
android:id="#+id/progressBar"
android:indeterminateDrawable="#drawable/progress_circle"
...
/>
Creating Custom ProgressBar like hotstar.
Add Progress bar on layout file and set the indeterminateDrawable with drawable file.
activity_main.xml
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:id="#+id/player_progressbar"
android:indeterminateDrawable="#drawable/custom_progress_bar"
/>
Create new xml file in res\drawable
custom_progress_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="1080" >
<shape
android:innerRadius="35dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false" >
<size
android:height="80dp"
android:width="80dp" />
<gradient
android:centerColor="#80b7b4b2"
android:centerY="0.5"
android:endColor="#f4eef0"
android:startColor="#00938c87"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
Simplest way to create customize a progress bar in Android:
Initialize and show dialog:
MyProgressDialog progressdialog = new MyProgressDialog(getActivity());
progressdialog.show();
Create method:
public class MyProgressDialog extends AlertDialog {
public MyProgressDialog(Context context) {
super(context);
getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
}
#Override
public void show() {
super.show();
setContentView(R.layout.dialog_progress);
}
}
Create layout XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:clickable="true">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<ProgressBar
android:id="#+id/progressbarr"
android:layout_width="#dimen/eightfive"
android:layout_height="#dimen/eightfive"
android:layout_centerInParent="true"
android:indeterminateDrawable="#drawable/progresscustombg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#+id/progressbarr"
android:layout_marginTop="#dimen/_3sdp"
android:textColor="#color/white"
android:text="Please wait"/>
</RelativeLayout>
</RelativeLayout>
Create shape progresscustombg.xml and put res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" >
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:thicknessRatio="20"
android:useLevel="false" >
<size
android:height="#dimen/eightfive"
android:width="#dimen/eightfive" />
<gradient
android:centerY="0.50"
android:endColor="#color/color_green_icash"
android:startColor="#FFFFFF"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
If you want to do this in code, here is a sample:
pd = new ProgressDialog(MainActivity.this);
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
pd.getWindow().setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);
TextView tv = new TextView(this);
tv.setTextColor(Color.WHITE);
tv.setTextSize(20);
tv.setText("Waiting...");
pd.setCustomTitle(tv);
pd.setIndeterminate(true);
pd.show();
Using TextView gives you an option to change color, size, and font of your text. Otherwise you can just call setMessage(), as usual.
<ProgressBar
android:indeterminateDrawable="#drawable/loading"
style="?android:attr/progressBarStyleLarge"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp"
android:scaleY="0.5"
android:scaleX="0.5"
android:id="#+id/progressBarGallery"/>
and #drawable/loading is src\main\res\drawable\loading.gif file, and its size is 200 by 200
How can I show shadow for my linear layout. I want white colored rounded background with shadow around the linearlayout. I have done this so far.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#xml/rounded_rect_shape"
android:orientation="vertical"
android:padding="10dp">
<-- My buttons, textviews, Imageviews go here -->
</LinearLayout>
And rounded_rect_shape.xml under xml directory
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#ffffff" />
<corners
android:bottomLeftRadius="3dp"
android:bottomRightRadius="3dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp" />
</shape>
There is also another solution to the problem by implementing a layer-list that will act as the background for the LinearLayoout.
Add background_with_shadow.xml file to res/drawable. Containing:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item >
<shape
android:shape="rectangle">
<solid android:color="#android:color/darker_gray" />
<corners android:radius="5dp"/>
</shape>
</item>
<item android:right="1dp" android:left="1dp" android:bottom="2dp">
<shape
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
Then add the the layer-list as background in your LinearLayout.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_with_shadow"/>
Well, this is easy to achieve .
Just build a GradientDrawable that comes from black and goes to a transparent color, than use parent relationship to place your shape close to the View that you want to have a shadow, then you just have to give any values to height or width .
Here is an example, this file have to be created inside res/drawable , I name it as shadow.xml :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#9444"
android:endColor="#0000"
android:type="linear"
android:angle="90"> <!-- Change this value to have the correct shadow angle, must be multiple from 45 -->
</gradient>
</shape>
Place the following code above from a LinearLayout , for example, set the android:layout_width and android:layout_height to fill_parent and 2.3dp, you'll have a nice shadow effect on your LinearLayout .
<View
android:id="#+id/shadow"
android:layout_width="fill_parent"
android:layout_height="2.3dp"
android:layout_above="#+id/id_from_your_LinearLayout"
android:background="#drawable/shadow">
</View>
Note 1: If you increase android:layout_height more shadow will be shown .
Note 2: Use android:layout_above="#+id/id_from_your_LinearLayout" attribute if you are placing this code inside a RelativeLayout, otherwise ignore it.
Hope it help someone.
There is no such attribute in Android, to show a shadow. But possible ways to do it are:
Add a plain LinearLayout with grey color, over which add your actual layout, with margin at bottom and right equal to 1 or 2 dp
Have a 9-patch image with a shadow and set it as the background to your Linear layout
For lollipop and above you can use elevation.
For older versions:
Here is a lazy hack from:
http://odedhb.blogspot.com/2013/05/android-layout-shadow-without-9-patch.html
(toast_frame does not work on KitKat, shadow was removed from toasts)
just use:
android:background="#android:drawable/toast_frame"
or:
android:background="#android:drawable/dialog_frame"
as a background
examples:
<TextView
android:layout_width="fill_parent"
android:text="I am a simple textview with a shadow"
android:layout_height="wrap_content"
android:textSize="18sp"
android:padding="16dp"
android:textColor="#fff"
android:background="#android:drawable/toast_frame"
/>
and with different bg color:
<LinearLayout
android:layout_height="64dp"
android:layout_width="fill_parent"
android:gravity="center"
android:background="#android:drawable/toast_frame"
android:padding="4dp"
>
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Button shadow"
android:background="#33b5e5"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#fff"
android:layout_gravity="center|bottom"
/>
</LinearLayout>
Try this.. layout_shadow.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#CABBBBBB"/>
<corners android:radius="2dp" />
</shape>
</item>
<item
android:left="0dp"
android:right="0dp"
android:top="0dp"
android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="2dp" />
</shape>
</item>
</layer-list>
Apply to your layout like this
android:background="#drawable/layout_shadow"
I know this is old, but most of these answers require a ton of extra code.
If you have a light colored background, you can simply use this:
android:elevation="25dp"
Actually I agree with #odedbreiner but I put the dialog_frame inside the first layer and hide the black background under the white layer.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#android:drawable/dialog_frame"
android:right="2dp" android:left="2dp" android:bottom="2dp" android:top="5dp" >
<shape android:shape="rectangle">
<corners android:radius="5dp"/>
</shape>
</item>
<item>
<shape
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
save this 9.png. (change name it to 9.png)
2.save it in your drawable.
3.set it to your layout.
4.set padding.
For example :
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/shadow"
android:paddingBottom="6dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingTop="6dp"
>
.
.
.
</LinearLayout>
Create a new XML by example named "shadow.xml" at DRAWABLE with the following code (you can modify it or find another better):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/middle_grey"/>
</shape>
</item>
<item android:left="2dp"
android:right="2dp"
android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#color/white"/>
</shape>
</item>
</layer-list>
After creating the XML in the LinearLayout or another Widget you want to create shade, you use the BACKGROUND property to see the efect. It would be something like :
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingRight="#dimen/margin_med"
android:background="#drawable/shadow"
android:minHeight="?attr/actionBarSize"
android:gravity="center_vertical">
You can use following class for xml tag:
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.FloatRange;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import com.webappmate.weeassure.R;
/**
* Created by GIGAMOLE on 13.04.2016.
*/
public class ShadowLayout extends FrameLayout {
// Default shadow values
private final static float DEFAULT_SHADOW_RADIUS = 30.0F;
private final static float DEFAULT_SHADOW_DISTANCE = 15.0F;
private final static float DEFAULT_SHADOW_ANGLE = 45.0F;
private final static int DEFAULT_SHADOW_COLOR = Color.DKGRAY;
// Shadow bounds values
private final static int MAX_ALPHA = 255;
private final static float MAX_ANGLE = 360.0F;
private final static float MIN_RADIUS = 0.1F;
private final static float MIN_ANGLE = 0.0F;
// Shadow paint
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setFilterBitmap(true);
}
};
// Shadow bitmap and canvas
private Bitmap mBitmap;
private final Canvas mCanvas = new Canvas();
// View bounds
private final Rect mBounds = new Rect();
// Check whether need to redraw shadow
private boolean mInvalidateShadow = true;
// Detect if shadow is visible
private boolean mIsShadowed;
// Shadow variables
private int mShadowColor;
private int mShadowAlpha;
private float mShadowRadius;
private float mShadowDistance;
private float mShadowAngle;
private float mShadowDx;
private float mShadowDy;
public ShadowLayout(final Context context) {
this(context, null);
}
public ShadowLayout(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public ShadowLayout(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
setLayerType(LAYER_TYPE_HARDWARE, mPaint);
// Retrieve attributes from xml
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadowLayout);
try {
setIsShadowed(typedArray.getBoolean(R.styleable.ShadowLayout_sl_shadowed, true));
setShadowRadius(
typedArray.getDimension(
R.styleable.ShadowLayout_sl_shadow_radius, DEFAULT_SHADOW_RADIUS
)
);
setShadowDistance(
typedArray.getDimension(
R.styleable.ShadowLayout_sl_shadow_distance, DEFAULT_SHADOW_DISTANCE
)
);
setShadowAngle(
typedArray.getInteger(
R.styleable.ShadowLayout_sl_shadow_angle, (int) DEFAULT_SHADOW_ANGLE
)
);
setShadowColor(
typedArray.getColor(
R.styleable.ShadowLayout_sl_shadow_color, DEFAULT_SHADOW_COLOR
)
);
} finally {
typedArray.recycle();
}
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
// Clear shadow bitmap
if (mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
}
}
public boolean isShadowed() {
return mIsShadowed;
}
public void setIsShadowed(final boolean isShadowed) {
mIsShadowed = isShadowed;
postInvalidate();
}
public float getShadowDistance() {
return mShadowDistance;
}
public void setShadowDistance(final float shadowDistance) {
mShadowDistance = shadowDistance;
resetShadow();
}
public float getShadowAngle() {
return mShadowAngle;
}
#SuppressLint("SupportAnnotationUsage")
#FloatRange
public void setShadowAngle(#FloatRange(from = MIN_ANGLE, to = MAX_ANGLE) final float shadowAngle) {
mShadowAngle = Math.max(MIN_ANGLE, Math.min(shadowAngle, MAX_ANGLE));
resetShadow();
}
public float getShadowRadius() {
return mShadowRadius;
}
public void setShadowRadius(final float shadowRadius) {
mShadowRadius = Math.max(MIN_RADIUS, shadowRadius);
if (isInEditMode()) return;
// Set blur filter to paint
mPaint.setMaskFilter(new BlurMaskFilter(mShadowRadius, BlurMaskFilter.Blur.NORMAL));
resetShadow();
}
public int getShadowColor() {
return mShadowColor;
}
public void setShadowColor(final int shadowColor) {
mShadowColor = shadowColor;
mShadowAlpha = Color.alpha(shadowColor);
resetShadow();
}
public float getShadowDx() {
return mShadowDx;
}
public float getShadowDy() {
return mShadowDy;
}
// Reset shadow layer
private void resetShadow() {
// Detect shadow axis offset
mShadowDx = (float) ((mShadowDistance) * Math.cos(mShadowAngle / 180.0F * Math.PI));
mShadowDy = (float) ((mShadowDistance) * Math.sin(mShadowAngle / 180.0F * Math.PI));
// Set padding for shadow bitmap
final int padding = (int) (mShadowDistance + mShadowRadius);
setPadding(padding, padding, padding, padding);
requestLayout();
}
private int adjustShadowAlpha(final boolean adjust) {
return Color.argb(
adjust ? MAX_ALPHA : mShadowAlpha,
Color.red(mShadowColor),
Color.green(mShadowColor),
Color.blue(mShadowColor)
);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Set ShadowLayout bounds
mBounds.set(
0, 0, MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)
);
}
#Override
public void requestLayout() {
// Redraw shadow
mInvalidateShadow = true;
super.requestLayout();
}
#Override
protected void dispatchDraw(final Canvas canvas) {
// If is not shadowed, skip
if (mIsShadowed) {
// If need to redraw shadow
if (mInvalidateShadow) {
// If bounds is zero
if (mBounds.width() != 0 && mBounds.height() != 0) {
// Reset bitmap to bounds
mBitmap = Bitmap.createBitmap(
mBounds.width(), mBounds.height(), Bitmap.Config.ARGB_8888
);
// Canvas reset
mCanvas.setBitmap(mBitmap);
// We just redraw
mInvalidateShadow = false;
// Main feature of this lib. We create the local copy of all content, so now
// we can draw bitmap as a bottom layer of natural canvas.
// We draw shadow like blur effect on bitmap, cause of setShadowLayer() method of
// paint does`t draw shadow, it draw another copy of bitmap
super.dispatchDraw(mCanvas);
// Get the alpha bounds of bitmap
final Bitmap extractedAlpha = mBitmap.extractAlpha();
// Clear past content content to draw shadow
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
// Draw extracted alpha bounds of our local canvas
mPaint.setColor(adjustShadowAlpha(false));
mCanvas.drawBitmap(extractedAlpha, mShadowDx, mShadowDy, mPaint);
// Recycle and clear extracted alpha
extractedAlpha.recycle();
} else {
// Create placeholder bitmap when size is zero and wait until new size coming up
mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
}
}
// Reset alpha to draw child with full alpha
mPaint.setColor(adjustShadowAlpha(true));
// Draw shadow bitmap
if (mCanvas != null && mBitmap != null && !mBitmap.isRecycled())
canvas.drawBitmap(mBitmap, 0.0F, 0.0F, mPaint);
}
// Draw child`s
super.dispatchDraw(canvas);
}
}
use Tag in xml like this:
<yourpackagename.ShadowLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
app:sl_shadow_color="#9e000000"
app:sl_shadow_radius="4dp">
<child views>
</yourpackagename.ShadowLayout>
UPDATE
put the below code in attrs.xml in resource>>values
<declare-styleable name="ShadowLayout">
<attr name="sl_shadowed" format="boolean"/>
<attr name="sl_shadow_distance" format="dimension"/>
<attr name="sl_shadow_angle" format="integer"/>
<attr name="sl_shadow_radius" format="dimension"/>
<attr name="sl_shadow_color" format="color"/>
</declare-styleable>
One possible solution is using nine patch image like this http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
OR
I have done this in the following way. This is my main layout in which round_corner.xml and drop_shadow.xml used as background resource. round_corner_two is same like round_corner.xml only the color attribute is different. copy the round_corner.xml,drop_shadow.xml and round_conere_two.xml into drawable folder.
<RelativeLayout
android:id="#+id/facebook_id"
android:layout_width="250dp"
android:layout_height="52dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="28dp"
android:background="#drawable/round_corner" >
<LinearLayout
android:id="#+id/shadow_id"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="1dp"
android:background="#drawable/drop_shadow" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginBottom="2dp"
android:background="#drawable/round_corner_two"
android:gravity="center"
android:text="#string/fb_butn_text"
android:textColor="#color/white" >
</TextView>
</LinearLayout>
</RelativeLayout>
round_corner.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- view background color -->
<solid
android:color="#ffffff" >
</solid>
<!-- view border color and width -->
<stroke
android:width="0dp"
android:color="#3b5998" >
</stroke>
<!-- If you want to add some padding -->
<padding
android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp" >
</padding>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
drop_shadow.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item >
<shape
android:shape="rectangle">
<solid android:color="#android:color/darker_gray" />
<corners android:radius="12dp"/>
</shape>
</item>
<item android:right="1dp" android:left="1dp" android:bottom="5dp">
<shape
android:shape="rectangle">
<solid android:color="#android:color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
i know this is way too late. but i had the same requirement. i solved like this
<android.support.v7.widget.CardView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardUseCompatPadding="true"
app:cardElevation="4dp"
app:cardCornerRadius="3dp" >
<!-- put whatever you want -->
</android.support.v7.widget.CardView>
you need to add dependency:
compile 'com.android.support:cardview-v7:25.0.1'
set this xml drwable as your background;---
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Bottom 2dp Shadow -->
<item>
<shape android:shape="rectangle" >
<solid android:color="#d8d8d8" />-->Your shadow color<--
<corners android:radius="15dp" />
</shape>
</item>
<!-- White Top color -->
<item android:bottom="3px" android:left="3px" android:right="3px" android:top="3px">-->here you can customize the shadow size<---
<shape android:shape="rectangle" >
<solid android:color="#FFFFFF" />
<corners android:radius="15dp" />
</shape>
</item>
</layer-list>
I want to create a Circluar Determinate ProgressBar, the kind which shows the Progress in the center of the Bar. Is there any default way to create this, or will i have to create my own custom one.
I have written detailed example on Android circular progress bar here on my blog demonuts.com You can also fond full source code and explanation there.
Here's how I made circular progressbar with percentage inside circle in pure code without any library.
first create a drawable file called circular.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/secondaryProgress">
<shape
android:innerRadiusRatio="6"
android:shape="ring"
android:thicknessRatio="20.0"
android:useLevel="true">
<gradient
android:centerColor="#999999"
android:endColor="#999999"
android:startColor="#999999"
android:type="sweep" />
</shape>
</item>
<item android:id="#android:id/progress">
<rotate
android:fromDegrees="270"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="270">
<shape
android:innerRadiusRatio="6"
android:shape="ring"
android:thicknessRatio="20.0"
android:useLevel="true">
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<gradient
android:centerColor="#00FF00"
android:endColor="#00FF00"
android:startColor="#00FF00"
android:type="sweep" />
</shape>
</rotate>
</item>
</layer-list>
Now in your activity_main.xml add following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/dialog"
tools:context="com.example.parsaniahardik.progressanimation.MainActivity">
<ProgressBar
android:id="#+id/circularProgressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="250dp"
android:layout_height="250dp"
android:indeterminate="false"
android:max="100"
android:progress="50"
android:layout_centerInParent="true"
android:progressDrawable="#drawable/circular"
android:secondaryProgress="100"
/>
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:background="#drawable/whitecircle"
android:layout_centerInParent="true"/>
<TextView
android:id="#+id/tv"
android:layout_width="250dp"
android:layout_height="250dp"
android:gravity="center"
android:text="25%"
android:layout_centerInParent="true"
android:textColor="#color/colorPrimaryDark"
android:textSize="20sp" />
</RelativeLayout>
In activity_main.xml I have used one circular image with white background to show white background around percentage. Here is the image:
You can change color of this image to set custom color around percentage text.
Now finally add following code to MainActivity.java :
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.DecelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int pStatus = 0;
private Handler handler = new Handler();
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.circular);
final ProgressBar mProgress = (ProgressBar) findViewById(R.id.circularProgressbar);
mProgress.setProgress(0); // Main Progress
mProgress.setSecondaryProgress(100); // Secondary Progress
mProgress.setMax(100); // Maximum Progress
mProgress.setProgressDrawable(drawable);
/* ObjectAnimator animation = ObjectAnimator.ofInt(mProgress, "progress", 0, 100);
animation.setDuration(50000);
animation.setInterpolator(new DecelerateInterpolator());
animation.start();*/
tv = (TextView) findViewById(R.id.tv);
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (pStatus < 100) {
pStatus += 1;
handler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
mProgress.setProgress(pStatus);
tv.setText(pStatus + "%");
}
});
try {
// Sleep for 200 milliseconds.
// Just to display the progress slowly
Thread.sleep(8); //thread will take approx 1.5 seconds to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
If you want to make horizontal progressbar, follow this link, it has many valuable examples with source code:
http://www.skholingua.com/android-basic/user-interface/form-widgets/progressbar
First add a progress_circle.xml to your res/drawable directory like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/progress_circular_background"/>
<item>
<shape
android:innerRadiusRatio="3.4"
android:shape="ring"
android:thicknessRatio="6.0" >
<gradient
android:endColor="#ffffffff"
android:startColor="#ffffff"
android:type="sweep"
android:useLevel="true" />
</shape>
</item>
<item>
<rotate
android:drawable="#drawable/progress_particle"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
</item>
</layer-list>
I Googled image searched both "progress_particle.png" and "progress_circular_background.png" (with quotes) since the android default drawables for those were missing. You'll probably want to customize those but they'll do to get you started.
Then in your xml layout:
<ProgressBar
android:id="#+id/timer_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="200dp"
android:layout_height="200dp"
android:indeterminate="false"
android:max="60"
android:progressDrawable="#drawable/progress_circle" />
My max is 60, since I'm using it for a seconds timer, but you might have something different.
The trick is that you need to use style="?android:attr/progressBarStyleHorizontal" even though it's a circular progress.
For the determinate part of your question, material design library now supports determinate circular progress bars:
<com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
For more info refer here.
Other answers may help on how to insert the progress label in the center.
An example of a determinate circular progress indicator
<com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:progress="75"
app:indicatorColor="#FF0000"
app:indicatorSize="100dp"
app:trackColor="#D3D3D3"
app:trackThickness="10dp" />
References
https://material.io/components/progress-indicators/android
https://developer.android.com/reference/com/google/android/material/progressindicator/CircularProgressIndicator
https://github.com/material-components/material-components-android