A horizontal progress bar adds circle indicators

I am trying to create a custom horizontal progressBar in which there will be a certain number of circle indicators, for example: enter image description here

Can someone tell me how I can achieve this effect (adding circle indicators)?

+5
source share
4 answers

Assuming your circle indicators are at a given interval (at the same distance from each other), it seems to me that the most logical solution is

  • Create custom view
  • Extend the ProgressBar to inherit all current functions and do not need to create your own setProgress methods (etc.).
  • Create a custom property called "tickInterval" (which I would suggest as% value points, not in dp views, but you could use them)
  • Create an XML file for custom attr if you want to use your view from xml
  • When the image is drawn, draw your indicator on each interval

You may need to customize your residence registration to make sure there is room for your circles. The following is a brief idea of ​​what you need:

public class TickedProgressBarView extends ProgressBar { private static final float DEFAULT_INTERVAL = 25f; private float INDICATOR_RADIUS; private Paint mTickPaint; private float mInterval; //% public TickedProgressBarView(Context context) { super(context); initPainters(context, null); //because draw is called a lot of times, don't want to do loads of allocations in onDraw } public TickedProgressBarView(Context context, AttributeSet attrs) { super(context, attrs); initPainters(context, attrs); } public TickedProgressBarView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initPainters(context, attrs); } private void initPainters(Context context, @Nullable AttributeSet attrs) { if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TickedProgressBarView, 0, 0); mInterval = a.getFloat(R.styleable.TickedProgressBarView_tickInterval, DEFAULT_INTERVAL); } else { mInterval = DEFAULT_INTERVAL; } //5 on the line below is HALF how many Dp wide you want the circles - ie a 10 Dp circle results from this INDICATOR_RADIUS = 5 * getResources().getDisplayMetrics().density + 0.5f; mTickPaint = new Paint(); mTickPaint.setColor(ContextCompat.getColor(getContext(), R.color.my_color)); mTickPaint.setStyle(Paint.Style.FILL); mTickPaint.setStrokeCap(Paint.Cap.ROUND); } public void setTickInterval(float intervalPercentage) { mInterval = intervalPercentage; invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mInterval > 0f) { final float midHeight = canvas.getHeight() / 2f; final int end = canvas.getWidth(); final int intervalPx = (int) ((end / 100f) * mInterval); int nextInterval = intervalPx; while (nextInterval <= end) { canvas.drawCircle(nextInterval, midHeight, INDICATOR_RADIUS, mTickPaint); nextInterval += intervalPx; } } } } 

attrs.xml

 <declare-styleable name="TickedProgressBarView"> <attr name="tickInterval" format="float" /> </declare-styleable> 

The attr declaration allows you to use your view from xml

 <!-- draw a circle every 10% along the bar --> <com.my.packge.TickedProgressBarView xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" app:tickInterval="10.0" /> 
+1
source

You need to create your own xml layout for your progress panel and perform calculations in Runnable or using AsyncTask

0
source

This is probably best done using a custom view . To establish progress, you must define the setter as shown below, which invalidates the view and calls onDraw ().

 public class CustomProgressBar extends View { // constructors etc... void setProgress(int progress) { if (progress < 0 || progress > 100) { throw new IllegalArgumentException("Progress must be between 0-100!"); } this.progress = progress. invalidate(); // tell view to redraw itself } } 

The next step is to draw a part of the view that indicates progress, and a part that indicates the remaining work.

 final Paint progressPaint = new Paint(); progressPaint.setColor(Color.RED); // could draw a bitmap or whatever, this is a simple example @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); // clear previous contents float progressW = getWidth() * (progress / 100); float remainingW = getWidth() - progressPortion; canvas.drawRect(0, 0, progressW, getHeight(), progressPaint); canvas.drawRect(progressW, 0, remainingW, getHeight(), remainingPaint); } 

Finally, you can calculate the positions of your circle indicators, inside onDraw () draw them on the canvas.

 final float radius = 5; final float circleCount = 6; float unit = getWidth() / circleCount; float offset = 0; for (int i=0; i<6; i++) { canvas.drawCircle(offset + (radius / 2), getHeight() / 2, radius, circlePaint); } 

If you need to conditionally display indicators, you can simply add a check during the onDraw () method to see if progress has passed a certain threshold.

0
source

Try it -

Your xml with progress bar -

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/progress_frame" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingEnd="16dp" android:layout_marginTop="10dp" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingStart="16dp"> <ProgressBar android:id="@+id/flight_progress" style="@style/flght.progress.style" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginBottom="10dp" android:layout_marginTop="10dp" android:max="100" android:visibility="visible"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:orientation="horizontal"> <LinearLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|end" android:src="@drawable/blue_circle"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|end" android:src="@drawable/blue_circle"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|end" android:src="@drawable/blue_circle"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|end" android:src="@drawable/blue_circle"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|end" android:src="@drawable/blue_circle"/> </LinearLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right|end" android:src="@drawable/blue_circle"/> </LinearLayout> </RelativeLayout> 

Add this to styles.xml -

 <style name="flght.progress.style" parent="android:Widget.ProgressBar.Horizontal"> <item name="android:indeterminateOnly">false</item> <item name="android:progressDrawable">@drawable/flight_cylinder_progress_bar</item> <item name="android:minHeight">8dip</item> <item name="android:maxHeight">24dip</item> <item name="android:minWidth">20dip</item> <item name="android:maxWidth">80dip</item> </style> 

Then add this flight_cylinder_progress_bar to the drawable folder -

 <?xml version="1.0" encoding="UTF-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background"> <shape> <corners android:radius="5dip"/> <gradient android:angle="270" android:centerColor="#ffdddddd" android:centerY="0.50" android:endColor="#ffdddddd" android:startColor="#ffdddddd"/> </shape> </item> <item android:id="@android:id/secondaryProgress"> <clip> <shape> <corners android:radius="5dip"/> <gradient android:angle="90" android:endColor="@color/orange_dark" android:startColor="@color/my_orange"/> </shape> </clip> </item> <item android:id="@android:id/progress"> <clip> <shape> <corners android:radius="5dip"/> <gradient android:angle="90" android:endColor="@color/my_orange" android:startColor="@color/orange_dark"/> </shape> </clip> </item> </layer-list> 

And finally, blue_circle.xml in the drawable folder -

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@color/goibibo_blue"/> <size android:width="10dp" android:height="10dp"/> </shape> 

Now you can just use the progressbar for setprogress. Output above code

The above result. Now you can just adjust the colors.

0
source

Source: https://habr.com/ru/post/1247931/


All Articles