1

I need to create circular shape with gaps.

I'm creating a Progress Bar which will represent clock. 12 gaps each assigned to hours.

enter image description here

this is exactly the thing I want to achieve. (Outer ring on Death Star)

here is my code so far:

in activity.xml

<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="500"
    android:progress="65"
    android:layout_marginBottom="165dp"
    android:layout_above="@+id/button5"
    android:layout_centerHorizontal="true" />

in circular_progress_bar

<?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="4dp"
        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 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="4dp"
    android:useLevel="false">

    <solid android:color="#CCC" />
    <stroke
        android:dashGap="10px"
        android:dashWidth="10px"
        android:width="1dp"
        android:color="#ababb2" />
</shape>

How do I separate my shape so it will look like this? Am I on correct path?

CBeTJlu4ok
  • 1,072
  • 4
  • 18
  • 51

1 Answers1

2

I had to create a custom progress bar in the past. I'm not sure about your solution so I won't comment on it. This is how I approached the issue:

I created a custom class overriding LinearLayout (I needed to add some more views to but you can override any other view)

Then I override onDraw and just draw an Arch over the canvas:

ArchProgressBar.java

public class ArchProgressBar extends LinearLayout {

private static final float START_ANGLE = 130;
private static final float ARCH_LENGTH = 50;

public ArchProgressBar(Context context) {
    super(context);
    init(context);
}

public ArchProgressBar(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

private void init(Context context) {
    this.setWillNotDraw(false);

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.arch_progress_bar, this, true);

    this.postInvalidate();
}

@Override
public void onDraw(Canvas canvas) {

    float middleWidth = canvas.getWidth() / 2;
    float middleHeight = canvas.getHeight() / 2;
    float left = middleWidth - 105 * getResources().getDisplayMetrics().density;
    float top = middleHeight - 90 * getResources().getDisplayMetrics().density;
    float right = middleWidth + 105 * getResources().getDisplayMetrics().density;
    float bottom = middleHeight + 120 * getResources().getDisplayMetrics().density;

    Paint mPaintBackground = new Paint();
    mPaintBackground.setAntiAlias(true);
    mPaintBackground.setStyle(Paint.Style.STROKE);
    mPaintBackground.setStrokeWidth(35);
    mPaintBackground.setColor(Color.BLACK);

    RectF mRectF = new RectF(left, top, right, bottom);

    // draw background line
    canvas.drawArc(mRectF, START_ANGLE, ARCH_LENGTH, false, mPaintBackground);

    canvas.drawArc(mRectF, START_ANGLE + ARCH_LENGTH + 10, ARCH_LENGTH, false, mPaintBackground);

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = View.MeasureSpec.getSize(widthMeasureSpec);
    setMeasuredDimension(width, Math.max(800, heightMeasureSpec));
}

}

arch_progress_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</LinearLayout>

then you can just add it to any xml you want like this:

<com.training.archprogress.ArchProgressBar
    android:id="@+id/result_result"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true" />

You can just draw 12 different segments and make the arch slightly smaller then the the size of a segment. Then just draw the number of segments you require with while the progress update.

I put a project with this solution for you in github: https://github.com/nevoroee/ArchProgress

Roee N
  • 502
  • 2
  • 4
  • 17
  • can you elaborate this more. what goes where. Im completly new to android. just decided to learn it through some small projects and this is my first one recreating zooper widget. – CBeTJlu4ok Oct 23 '16 at 12:52
  • I added a more detailed explanation with the full classes and a github link for an example app Not really sure why someone downvoted me... but maybe there's a better solution for this problem – Roee N Oct 23 '16 at 13:44
  • This custom view is not working properly... I attached it to the layout exactly as you described and it is not drawing anything. Will try seeing what's wrong with it. – Felipe Ribeiro R. Magalhaes Apr 24 '20 at 21:07
  • Now I see, it only works if it is match_parent for both width and height... – Felipe Ribeiro R. Magalhaes Apr 24 '20 at 21:10