Vertical progress bar in android
It's a bit hard to tell the transition you are trying to attempt between those two images. So you want to start with the B/W image, but does it transition from B/W to Color by cross-fading, or do you slowly want to apply pieces of the color image from the bottom up over the B/W piece?
If the latter is your choice, then your actual image will comprise of two drawables together inside a <layer-list>
. One static, and the other representing a ClipDrawable
that will reveal a portion of the color image based on its level value. For example, create an XML file:
res/drawable/progress_background.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<bitmap android:src="@drawable/ic_launcher_bw"/>
</item>
<item>
<clip
android:clipOrientation="vertical"
android:gravity="bottom"
android:drawable="@drawable/ic_launcher"/>
</item>
</layer-list>
Then set that Drawable
on something like an ImageView
to display the progress, and change the value with calls to setLevel()
, i.e.
//This is any view subclass that you have chosen to do this
ImageView progress;
progress.setImageResource(R.drawable.progress_background);
//Adjust the progress by adjusting the drawable's level
progress.setImageLevel(500);
// -- OR --
progress.getDrawable().setLevel(500);
Drawable levels are set by default from 0 to 10,000 to represent fully clipped to fully revealed.
HTH
Adding vertical line to ProgressBar
You need to extend the ProgressBar
class and override the onDraw()
method that will provide you a canvas to draw on. Then you can do your painting logic, e.g.:
class MyProgressBar extends ProgressBar {
...
@Override
public void onDraw(Canvas canvas) {
Paint linePaint = new Paint();
linePaint.setColor(getResources().getColor(android.R.color.black));
final float lineWidth = 5f;
linePaint.setStrokeWidth(lineWidth);
canvas.drawLine(getWidth() * m100 / 100, 0,
getWidth() * m100 / 100, getHeight(),
linePaint);
}
}
Finally, replace the ProgressBar
added to the XML file with your custom MyProgressBar
.
Additional improvement: move paint initialization outside of the draw method so you don't reinitialize the same object on every onDraw()
call. Do the same for the lineWidth
.
Vertical line in android progress bar
I found a solution... I removed the line item from the code above and added the following code to the onDraw()
method:
Paint linePaint = new Paint();
linePaint.setColor(getResources().getColor(android.R.color.black));
final float lineWidth = 5f;
linePaint.setStrokeWidth(lineWidth);
canvas.drawLine(getWidth() * m100 / 100, 0,
getWidth() * m100 / 100, getHeight(),
linePaint);
In the code, m100
is the position of the line as integer. For example, it is 80 if the 100% like mark should be positioned at 80% of the bar length.
vertical progress bar cannot be assigned to end of the layout
Ok one thing you can do is wrap it.
<FrameLayout
android:layout_width="20dp"
android:layout_height="300dp"
android:layout_marginEnd="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" // for left
// app:layout_constraintStart_toStartOf="parent" // for right
app:layout_constraintTop_toTopOf="parent">
<ProgressBar
android:id="@+id/idVolumeControl"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="290dp"
android:layout_height="match_parent"
android:max="100"
android:progress="50"
android:rotation="270" />
</FrameLayout>
Center a progress bar vertically
Try this way,hope this will help you to solve your problem.
If you dont wan to set RelativeLayout layout_height to match_parent then take FrameLayout as parent layout of your ScrollView and put you ProgressBar out-side RelativeLayout like below.
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:id="@+id/swipe">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_vertical_margin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Random number:"
android:id="@+id/lbl"
android:visibility="gone" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/rndNum"
android:layout_toRightOf="@id/lbl"
android:visibility="gone" />
</RelativeLayout>
</ScrollView>
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleLarge"
android:visibility="visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true" />
</FrameLayout>
</android.support.v4.widget.SwipeRefreshLayout>
Is there a way to put a separator line in the progress bar?
Hello hanjiman
I will suggest you with two example
First One
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.widget.ProgressBar;
public class MainLayout extends Activity {
int progress=1;
ProgressBar progressBar;
@SuppressLint("ResourceType")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar= (ProgressBar)findViewById(R.id.progress_bar_test);
SeperatedProgressbar bgProgress= new SeperatedProgressbar(ContextCompat.getColor(this,R.color.color_progress),ContextCompat.getColor(this,R.color.color_normal),this);
progressBar.setProgressDrawable(bgProgress);
progressBar.setMax(100);
progressBar.setProgress(50);
new CountDownTimer(100000, 1000) {
public void onTick(long millisUntilFinished) {
progress=progress+1;
progressBar.setProgress(progress);
}
public void onFinish() {
}
}.start();
}
}
activity_main.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:paddingLeft="10dp"
android:layout_height="match_parent"
>
<ProgressBar
android:id="@+id/progress_bar_test"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_centerInParent="true"
style="?android:attr/progressBarStyleHorizontal"
android:max="100"
android:progress="10"
/>
</RelativeLayout>
SeperatedProgressbar.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
public class SeperatedProgressbar extends Drawable {
private static final int NUM_SEGMENTS = 8;
private int mForeground;
private int mBackground;
private final Paint mPaint = new Paint();
private final RectF mSegment = new RectF();
Context context;
public SeperatedProgressbar(int fgColor, int bgColor, Context context) {
mForeground = fgColor;
this.context=context;
mBackground = bgColor;
}
@Override
protected boolean onLevelChange(int level) {
invalidateSelf();
return true;
}
@Override
public void draw(Canvas canvas) {
float level = getLevel() / 1000f;
Rect b = getBounds();
float gapWidth = b.height() / 8f;
float segmentWidth = (b.width() - (NUM_SEGMENTS - 1) * gapWidth) / NUM_SEGMENTS;
mSegment.set(0, 0, segmentWidth, b.height());
mPaint.setColor(mForeground);
for (int i = 0; i < NUM_SEGMENTS; i++) {
float loLevel = i / (float) NUM_SEGMENTS;
float hiLevel = (i + 1) / (float) NUM_SEGMENTS;
if (loLevel <= level && level <= hiLevel) {
float middle = mSegment.left + NUM_SEGMENTS * segmentWidth * (level - loLevel);
canvas.drawRect(mSegment.left, mSegment.top, middle, mSegment.bottom, mPaint);
mPaint.setColor(mBackground);
canvas.drawRect(middle, mSegment.top, mSegment.right, mSegment.bottom, mPaint);
} else {
canvas.drawRect(mSegment, mPaint);
}
mSegment.offset(mSegment.width() + gapWidth, 0);
}
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
Result
Second Answer
MainActivity.Java
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import com.rachitgoyal.segmented.SegmentedProgressBar;
import java.util.ArrayList;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
SegmentedProgressBar mSegmentedProgressBar;
ArrayList<Integer> arrayList=new ArrayList<>();;
int progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSegmentedProgressBar = findViewById(R.id.segmented_pb_1);
arrayList.add(progress);
new CountDownTimer(200000, 2000) {
public void onTick(long millisUntilFinished) {
if(progress==0)
{
arrayList.add(progress);
}
else
{
arrayList.add(progress);
}
progress=progress+1;
mSegmentedProgressBar.setEnabledDivisions(arrayList);
}
public void onFinish() {
}
}.start();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.test.package.SegmentedProgressBar
android:id="@+id/segmented_pb_1"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_centerHorizontal="true"
android:layout_margin="10dp"
android:layout_centerInParent="true"
app:cornerRadius="20dp"
app:dividerColor="@color/white"
app:dividerWidth="2dp"
app:divisions="10"
app:isDividerEnabled="true"
app:progressBarBackgroundColor="#dadada"
app:progressBarColor="#ff2d2d" />
</RelativeLayout>
SegmentedProgressBar.java
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import com.test.package.segmentedprogressbar.R;
import java.util.ArrayList;
import java.util.List;
public class SegmentedProgressBar extends View {
private static final String TAG = "SegmentedProgressBar";
RectF bgRect;
private Paint progressBarBackgroundPaint = new Paint();
private Paint progressBarPaint = new Paint();
private Paint dividerPaint = new Paint();
private int progressBarWidth;
private float percentCompleted;
private float dividerWidth = 1;
private boolean isDividerEnabled = true;
private int divisions = 1;
private List<Integer> enabledDivisions = new ArrayList<>();
private List<Float> dividerPositions;
private float cornerRadius = 20f;
public SegmentedProgressBar(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
dividerPositions = new ArrayList<>();
cornerRadius = 0;
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.SegmentedProgressBar, 0, 0);
try {
dividerPaint.setColor(typedArray.getColor(R.styleable.SegmentedProgressBar_dividerColor,
ContextCompat.getColor(getContext(), R.color.white)));
progressBarBackgroundPaint.setColor(typedArray.getColor(R.styleable.SegmentedProgressBar_progressBarBackgroundColor,
ContextCompat.getColor(getContext(), R.color.grey_light)));
progressBarPaint.setColor(typedArray.getColor(R.styleable.SegmentedProgressBar_progressBarColor,
ContextCompat.getColor(getContext(), R.color.progress_bar)));
dividerWidth = typedArray.getDimension(R.styleable.SegmentedProgressBar_dividerWidth, dividerWidth);
isDividerEnabled = typedArray.getBoolean(R.styleable.SegmentedProgressBar_isDividerEnabled, true);
divisions = typedArray.getInteger(R.styleable.SegmentedProgressBar_divisions, divisions);
cornerRadius = typedArray.getDimension(R.styleable.SegmentedProgressBar_cornerRadius, 2f);
} finally {
typedArray.recycle();
}
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getWidth() > 0) {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
progressBarWidth = getWidth();
dividerPositions.clear();
if (divisions > 1) {
for (int i = 1; i < divisions; i++) {
dividerPositions.add(((float) (progressBarWidth * i) / divisions));
}
}
bgRect = new RectF(0, 0, getWidth(), getHeight());
updateProgress();
}
}
});
}
}
/**
* Updates the progress bar based on manually passed percent value.
*/
private void updateProgress() {
invalidate();
}
public SegmentedProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public SegmentedProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SegmentedProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (bgRect != null) {
canvas.drawRoundRect(bgRect, cornerRadius, cornerRadius, progressBarBackgroundPaint);
for (Integer enabledDivision : enabledDivisions) {
if (enabledDivision < divisions) {
float left = 0;
if (enabledDivision != 0) {
left = dividerPositions.get(enabledDivision - 1) + dividerWidth;
}
float right = enabledDivision >= dividerPositions.size() ? progressBarWidth : dividerPositions.get(enabledDivision);
RectF rect = new RectF(left, 0, right, getHeight());
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, progressBarPaint);
if (enabledDivision == 0) {
canvas.drawRect(left + cornerRadius, 0, right, getHeight(), progressBarPaint);
} else if (enabledDivision == divisions - 1) {
canvas.drawRect(left, 0, right - cornerRadius, getHeight(), progressBarPaint);
} else {
canvas.drawRect(rect, progressBarPaint);
}
}
if (divisions > 1 && isDividerEnabled) {
for (int i = 1; i < divisions; i++) {
float leftPosition = dividerPositions.get(i - 1);
canvas.drawRect(leftPosition, 0, leftPosition + dividerWidth, getHeight(), dividerPaint);
}
}
}
}
}
/**
* Set the color for the progress bar background
*
* @param color
*/
public void setBackgroundColor(int color) {
progressBarBackgroundPaint.setColor(color);
}
public void reset() {
dividerPositions.clear();
percentCompleted = 0;
updateProgress();
}
/**
* Set the color for the progress bar
*
* @param color
*/
public void setProgressBarColor(int color) {
progressBarPaint.setColor(color);
}
/**
* Set the color for the divider bar
*
* @param color
*/
public void setDividerColor(int color) {
dividerPaint.setColor(color);
}
/**
* set the width of the divider
*
* @param width
*/
public void setDividerWidth(float width) {
if (width < 0) {
Log.w(TAG, "setDividerWidth: Divider width can not be negative");
return;
}
dividerWidth = width;
}
/**
* Set whether the dividers are enabled or not.
*
* @param value true or false
*/
public void setDividerEnabled(boolean value) {
isDividerEnabled = value;
}
/**
* Sets the number of divisions in the ProgressBar.
*
* @param divisions number of divisions
*/
public void setDivisions(int divisions) {
if (divisions < 1) {
Log.w(TAG, "setDivisions: Number of Divisions cannot be less than 1");
return;
}
this.divisions = divisions;
dividerPositions.clear();
if (divisions > 1) {
for (int i = 1; i < divisions; i++) {
dividerPositions.add(((float) (progressBarWidth * i) / divisions));
}
}
updateProgress();
}
/**
* Set the enabled divisions to specified value.
*
* @param enabledDivisions number of divisions to be enabled
*/
public void setEnabledDivisions(List<Integer> enabledDivisions) {
this.enabledDivisions = enabledDivisions;
updateProgress();
}
public void setCornerRadius(float cornerRadius) {
this.cornerRadius = cornerRadius;
}
}
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SegmentedProgressBar">
<attr name="dividerColor" format="color" />
<attr name="progressBarBackgroundColor" format="color" />
<attr name="progressBarColor" format="color" />
<attr name="dividerWidth" format="dimension" />
<attr name="isDividerEnabled" format="boolean" />
<attr name="divisions" format="integer" />
<attr name="cornerRadius" format="dimension" />
</declare-styleable>
</resources>
response
How to create a horizontal loading progress bar?
It is Widget.ProgressBar.Horizontal
on my phone, if I set android:indeterminate="true"
Related Topics
How to Get Results from an Intentservice Back into an Activity
Should I Use Getapplicationcontext or Activity.This in a Long Running Asynctask
Designing Android Apps for Tablets
Detecting Outgoing Call and Call Hangup Event in Android
Exception When Opening Parse Push Notification
Gradle Sync Failed: Failed to Find Build Tools Revision 24.0.0 Rc1
Access The Sim Card with an Android Application
Android Build Gradle Is Too Slow (Dependency Resolution)
Findbugs Idea - Classnotfoundexception Com.Google.Wireless.Android.Sdk.Stats.Intellijindexingstats
How to Save Data from Camera to Disk Using Mediastore on Android
Help with a Custom View Attributes Inside a Android Library Project
How to Replace The Activity's Fragment from The Fragment Itself
Failed to Find Build Tools Revision 21.1.1 - Sdk Up to Date
Service Intent Must Be Explicit: Intent
Android Gcm Sender_Id, How to Get It