roundcornerprogressbar progressbar akexorcist android widget progress-bar drawable cornerradius

progressbar - Android bordes redondos en barra de progreso en forma de anillo



progressbar android github (2)

Estoy tratando de hacer una barra de progreso circular en Android y parece una tarea bastante sencilla, pero me cuesta redondear los bordes del progreso y el progreso secundario.

¿Hay una manera de hacerlo sin hacer una vista personalizada? ¿Usando un radio de esquinas? o nueve parche dibujable?

Para esta vista (ver adjunto) estoy usando un archivo xml simple

<item android:id="@android:id/progress"> <shape android:useLevel="true" android:innerRadius="@dimen/sixty_dp" android:shape="ring" android:thickness="@dimen/seven_dp"> <solid android:color="#477C5B"/> <stroke android:width="1dip" android:color="#FFFF"/> </shape> </item>


Simplemente cree una clase llamada MyProgress en su paquete ... y pegue el siguiente código ...

import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.text.TextPaint; import android.util.AttributeSet; import android.view.View; public class MyProgress extends View { private Paint mPrimaryPaint; private Paint mSecondaryPaint; private RectF mRectF; private TextPaint mTextPaint; private Paint mBackgroundPaint; private boolean mDrawText = false; private int mSecondaryProgressColor; private int mPrimaryProgressColor; private int mBackgroundColor; private int mStrokeWidth; private int mProgress; private int mSecodaryProgress; private int mTextColor; private int mPrimaryCapSize; private int mSecondaryCapSize; private boolean mIsPrimaryCapVisible; private boolean mIsSecondaryCapVisible; private int x; private int y; private int mWidth = 0, mHeight = 0; public MyProgress(Context context) { super(context); init(context, null); } public MyProgress(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public MyProgress(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } void init(Context context, AttributeSet attrs) { TypedArray a; if (attrs != null) { a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.MyProgress, 0, 0); } else { throw new IllegalArgumentException("Must have to pass the attributes"); } try { mDrawText = a.getBoolean(R.styleable.MyProgress_showProgressText, false); mBackgroundColor = a.getColor(R.styleable.MyProgress_backgroundColor, android.R.color.darker_gray); mPrimaryProgressColor = a.getColor(R.styleable.MyProgress_progressColor, android.R.color.darker_gray); mSecondaryProgressColor = a.getColor(R.styleable.MyProgress_secondaryProgressColor, android.R.color.black); mProgress = a.getInt(R.styleable.MyProgress_progress, 0); mSecodaryProgress = a.getInt(R.styleable.MyProgress_secondaryProgress, 0); mStrokeWidth = a.getDimensionPixelSize(R.styleable.MyProgress_strokeWidth, 20); mTextColor = a.getColor(R.styleable.MyProgress_textColor, android.R.color.black); mPrimaryCapSize = a.getInt(R.styleable.MyProgress_primaryCapSize, 20); mSecondaryCapSize = a.getInt(R.styleable.MyProgress_secodaryCapSize, 20); mIsPrimaryCapVisible = a.getBoolean(R.styleable.MyProgress_primaryCapVisibility, true); mIsSecondaryCapVisible = a.getBoolean(R.styleable.MyProgress_secodaryCapVisibility, true); } finally { a.recycle(); } mBackgroundPaint = new Paint(); mBackgroundPaint.setAntiAlias(true); mBackgroundPaint.setStyle(Paint.Style.STROKE); mBackgroundPaint.setStrokeWidth(mStrokeWidth); mBackgroundPaint.setColor(mBackgroundColor); mPrimaryPaint = new Paint(); mPrimaryPaint.setAntiAlias(true); mPrimaryPaint.setStyle(Paint.Style.STROKE); mPrimaryPaint.setStrokeWidth(mStrokeWidth); mPrimaryPaint.setColor(mPrimaryProgressColor); mSecondaryPaint = new Paint(); mSecondaryPaint.setAntiAlias(true); mSecondaryPaint.setStyle(Paint.Style.STROKE); mSecondaryPaint.setStrokeWidth(mStrokeWidth - 2); mSecondaryPaint.setColor(mSecondaryProgressColor); mTextPaint = new TextPaint(); mTextPaint.setColor(mTextColor); mRectF = new RectF(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mRectF.set(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom()); mTextPaint.setTextSize(w / 5); x = (w / 2) - ((int) (mTextPaint.measureText(mProgress + "%") / 2)); y = (int) ((h / 2) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2)); mWidth = w; mHeight = h; invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPrimaryPaint.setStyle(Paint.Style.STROKE); mSecondaryPaint.setStyle(Paint.Style.STROKE); // for drawing a full progress .. The background circle canvas.drawArc(mRectF, 0, 360, false, mBackgroundPaint); // for drawing a secondary progress circle int secondarySwipeangle = (mSecodaryProgress * 360) / 100; canvas.drawArc(mRectF, 270, secondarySwipeangle, false, mSecondaryPaint); // for drawing a main progress circle int primarySwipeangle = (mProgress * 360) / 100; canvas.drawArc(mRectF, 270, primarySwipeangle, false, mPrimaryPaint); // for cap of secondary progress int r = (getHeight() - getPaddingLeft() * 2) / 2; // Calculated from canvas width double trad = (secondarySwipeangle - 90) * (Math.PI / 180d); // = 5.1051 int x = (int) (r * Math.cos(trad)); int y = (int) (r * Math.sin(trad)); mSecondaryPaint.setStyle(Paint.Style.FILL); if (mIsSecondaryCapVisible) canvas.drawCircle(x + (mWidth / 2), y + (mHeight / 2), mSecondaryCapSize, mSecondaryPaint); // for cap of primary progress trad = (primarySwipeangle - 90) * (Math.PI / 180d); // = 5.1051 x = (int) (r * Math.cos(trad)); y = (int) (r * Math.sin(trad)); mPrimaryPaint.setStyle(Paint.Style.FILL); if (mIsPrimaryCapVisible) canvas.drawCircle(x + (mWidth / 2), y + (mHeight / 2), mPrimaryCapSize, mPrimaryPaint); if (mDrawText) canvas.drawText(mProgress + "%", x, y, mTextPaint); } public void setDrawText(boolean mDrawText) { this.mDrawText = mDrawText; invalidate(); } public void setBackgroundColor(int mBackgroundColor) { this.mBackgroundColor = mBackgroundColor; invalidate(); } public void setSecondaryProgressColor(int mSecondaryProgressColor) { this.mSecondaryProgressColor = mSecondaryProgressColor; invalidate(); } public void setPrimaryProgressColor(int mPrimaryProgressColor) { this.mPrimaryProgressColor = mPrimaryProgressColor; invalidate(); } public void setStrokeWidth(int mStrokeWidth) { this.mStrokeWidth = mStrokeWidth; invalidate(); } public void setProgress(int mProgress) { this.mProgress = mProgress; invalidate(); } public void setSecondaryProgress(int mSecondaryProgress) { this.mSecodaryProgress = mSecondaryProgress; invalidate(); } public void setTextColor(int mTextColor) { this.mTextColor = mTextColor; invalidate(); } public void setPrimaryCapSize(int mPrimaryCapSize) { this.mPrimaryCapSize = mPrimaryCapSize; invalidate(); } public void setSecondaryCapSize(int mSecondaryCapSize) { this.mSecondaryCapSize = mSecondaryCapSize; invalidate(); } public boolean isPrimaryCapVisible() { return mIsPrimaryCapVisible; } public void setIsPrimaryCapVisible(boolean mIsPrimaryCapVisible) { this.mIsPrimaryCapVisible = mIsPrimaryCapVisible; } public boolean isSecondaryCapVisible() { return mIsSecondaryCapVisible; } public void setIsSecondaryCapVisible(boolean mIsSecondaryCapVisible) { this.mIsSecondaryCapVisible = mIsSecondaryCapVisible; } public int getSecondaryProgressColor() { return mSecondaryProgressColor; } public int getPrimaryProgressColor() { return mPrimaryProgressColor; } public int getProgress() { return mProgress; } public int getBackgroundColor() { return mBackgroundColor; } public int getSecodaryProgress() { return mSecodaryProgress; } public int getPrimaryCapSize() { return mPrimaryCapSize; } public int getSecondaryCapSize() { return mSecondaryCapSize; } }

y agregue la siguiente línea en res-> values-> attr.xml debajo de una etiqueta y compílelo

<declare-styleable name="MyProgress"> <attr name="showProgressText" format="boolean" /> <attr name="progress" format="integer" /> <attr name="secondaryProgress" format="integer" /> <attr name="progressColor" format="color" /> <attr name="secondaryProgressColor" format="color" /> <attr name="backgroundColor" format="color" /> <attr name="primaryCapSize" format="integer" /> <attr name="secodaryCapSize" format="integer" /> <attr name="primaryCapVisibility" format="boolean" /> <attr name="secodaryCapVisibility" format="boolean" /> <attr name="strokeWidth" format="dimension" /> <attr name="textColor" format="color" /> </declare-styleable>

eso es todo .... y para usar en tu diseño ..

<Your_Package_Name.MyProgress android:padding="20dp" android:id="@+id/timer1" app:strokeWidth="10dp" app:progress="30" app:secondaryProgress="50" app:backgroundColor="@android:color/black" app:progressColor="@android:color/holo_blue_bright" app:secondaryProgressColor="@android:color/holo_blue_dark" app:primaryCapSize="30" app:secodaryCapSize="40" app:primaryCapVisibility="true" app:secodaryCapVisibility="true" android:layout_width="200dp" android:layout_height="200dp" />

También puede cambiar todas las propiedades de forma programática usando setMethods () ...

siéntete libre de preguntar cualquier cosa ... la mejor de las suertes

[Actualización 23-01-2016]

Finalmente subí el código en github. Puede referirse desde aquí https://github.com/msquare097/MProgressBar

Ahora puede usar esta Barra de progreso simplemente escribiendo la siguiente línea en el archivo build.gradle de su aplicación. No tienes que copiar el código anterior.

compile ''com.msquare.widget.mprogressbar:mprogressbar:1.0.0''


puede agregar una forma de círculo / óvalo en el extremo y el lado de inicio del anillo, al igual que el código de abajo

una lista de capas dibujable contiene dos formas circulares / ovaladas dibujables y una forma de anillo dibujable

round_progress_drawable.xml

<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:bottom="294px" android:left="540px" android:right="48px" android:top="294px"> <shape android:innerRadius="6px" android:shape="oval"> <solid android:color="#FFFFFF"></solid> </shape> </item> <item> <shape android:innerRadius="240px" android:shape="ring" android:thickness="12px"> <size android:width="600px" android:height="600px"></size> <solid android:color="#FFFFFF"></solid> </shape> </item> <item> <rotate> <layer-list> <item android:bottom="294px" android:left="540px" android:right="48px" android:top="294px"> <shape android:innerRadius="6px" android:shape="oval"> <solid android:color="#FFFFFF"></solid> </shape> </item> </layer-list> </rotate> </item> </layer-list>

round_progress_animation_selector.xml

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_window_focused="true"> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="5000" android:propertyName="ImageLevel" android:repeatCount="infinite" android:valueFrom="0" android:valueTo="10000" android:valueType="intType"> </objectAnimator> </item> <item> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="0" android:propertyName="ImageLevel" android:valueFrom="0" android:valueTo="0" android:valueType="intType"> </objectAnimator> </item> </selector>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <FrameLayout 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" android:background="@color/colorPrimaryDark" tools:context=".MainActivity"> <ImageView android:stateListAnimator="@animator/round_progress_animation_selector" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/round_progress_drawable" /> </FrameLayout>