Android - Set a Progressbar to Be a Vertical Bar Instead of Horizontal

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

Sample Image

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
Sample Image

How to create a horizontal loading progress bar?

It is Widget.ProgressBar.Horizontal on my phone, if I set android:indeterminate="true"



Related Topics



Leave a reply



Submit