Android: Barre De Progression Semi-Cercle

je veux la barre de progression en demi-cercle en arrière-plan de l'image. tout comme l'image ci-dessous.

enter image description here

j'ai essayé de dessiner en utilisant la toile mais je ne peux pas obtenir de succès. j'ai également fatigué certains custom progress bar library mais le résultat est le même.

n'importe quelles suggestions.

recherche de développement unique et utilisé dans toutes les tailles d'écran.

14
demandé sur Dhawal Sodha Parmar 2014-03-19 12:22:38

6 réponses

ceci peut être réalisé en découpant une toile contenant une image à un angle (en dessinant un arc).

Vous pouvez utiliser une image de quelque chose comme ceci

enter image description here

et clip cette image en dessinant un arc.

Voici comment vous pouvez le faire.

//Convert the progress in range of 0 to 100 to angle in range of 0 180. Easy math.
float angle = (progress * 180) / 100;
mClippingPath.reset();
//Define a rectangle containing the image
RectF oval = new RectF(mPivotX, mPivotY, mPivotX + mBitmap.getWidth(), mPivotY + mBitmap.getHeight());
//Move the current position to center of rect
mClippingPath.moveTo(oval.centerX(), oval.centerY());
//Draw an arc from center to given angle
mClippingPath.addArc(oval, 180, angle);
//Draw a line from end of arc to center
mClippingPath.lineTo(oval.centerX(), oval.centerY());

Et une fois que vous obtenir le chemin d'accès, vous pouvez utiliser clipPath fonction pour couper la toile dans ce chemin.

canvas.clipPath(mClippingPath);

Voici la code

SemiCircleProgressBarView.java

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;



public class SemiCircleProgressBarView extends View {

    private Path mClippingPath;
    private Context mContext;
    private Bitmap mBitmap;
    private float mPivotX;
    private float mPivotY;

    public SemiCircleProgressBarView(Context context) {
        super(context);
        mContext = context;
        initilizeImage();
    }

    public SemiCircleProgressBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initilizeImage();
    }

    private void initilizeImage() {
        mClippingPath = new Path();

        //Top left coordinates of image. Give appropriate values depending on the position you wnat image to be placed
        mPivotX = getScreenGridUnit();
        mPivotY = 0;

        //Adjust the image size to support different screen sizes
        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.circle);
        int imageWidth = (int) (getScreenGridUnit() * 30);
        int imageHeight = (int) (getScreenGridUnit() * 30);
        mBitmap = Bitmap.createScaledBitmap(bitmap, imageWidth, imageHeight, false);
    }

    public void setClipping(float progress) {

        //Convert the progress in range of 0 to 100 to angle in range of 0 180. Easy math.
        float angle = (progress * 180) / 100;
        mClippingPath.reset();
        //Define a rectangle containing the image
        RectF oval = new RectF(mPivotX, mPivotY, mPivotX + mBitmap.getWidth(), mPivotY + mBitmap.getHeight());
        //Move the current position to center of rect
        mClippingPath.moveTo(oval.centerX(), oval.centerY());
        //Draw an arc from center to given angle
        mClippingPath.addArc(oval, 180, angle);
        //Draw a line from end of arc to center
        mClippingPath.lineTo(oval.centerX(), oval.centerY());
        //Redraw the canvas
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //Clip the canvas
        canvas.clipPath(mClippingPath);
        canvas.drawBitmap(mBitmap, mPivotX, mPivotY, null);

    }

    private float getScreenGridUnit() {
        DisplayMetrics metrics = new DisplayMetrics();
        ((Activity)mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
        return metrics.widthPixels / 32;
    }

}

et l'utiliser dans n'importe quelle activité est très facile.

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <com.example.progressbardemo.SemiCircleProgressBarView
        android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>   

Notez que clipPath ne fonctionne pas si le hardware acceleration est activé. Vous pouvez désactiver l'accélération matérielle uniquement pour la vue.

   //Turn off hardware accleration
  semiCircleProgressBarView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SemiCircleProgressBarView semiCircleProgressBarView = (SemiCircleProgressBarView) findViewById(R.id.progress);
        semiCircleProgressBarView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        semiCircleProgressBarView.setClipping(70);
    }

}  

lorsque la progression change, vous pouvez définir la barre de progression en appelant fonction

semiCircleProgressBarView.setClipping(progress);

Ex:semiCircleProgressBarView.setClipping(50); //50% progress

enter image description here

semiCircleProgressBarView.setClipping(70); //70% progress

enter image description here

vous pouvez utiliser votre propre Image pour répondre aux exigences. Espérons que cela aide!!

Edit : pour déplacer le demi-cercle au bas de l'écran, Changez mPivotY valeur. Quelque chose comme ceci

//In `SemiCircleProgressBarView.java`
//We don't get the canvas width and height initially, set `mPivoyY` inside `onWindowFocusChanged` since `getHeight` returns proper results by that time
        public void onWindowFocusChanged(boolean hasWindowFocus) {
            super.onWindowFocusChanged(hasWindowFocus);

            mPivotX = getScreenGridUnit();
            mPivotY = getHeight() - (mBitmap.getHeight() / 2);
        }
36
répondu Abhishek V 2014-03-22 06:57:41

Vous pouvez essayer Seekarc Library. Je sais que c'est un type différent de seekbar, mais avec un peu de personnalisation, vous pouvez l'utiliser pour votre application comme une barre de progression. J'ai fait la même chose. Vous avez juste besoin de changer certaines propriétés comme

seekarc:touchInside="false".

Son assez simple.

maintenant, l'implémentation personnalisée sur mon application ressemble un peu à ceci:

Custom progressbar in CleanMaster

img src: CleanMaster chez Google Jouer

8
répondu saran 2014-03-28 09:09:57

vous pouvez aussi utiliser native ProgressBar pour réaliser le semi-cercle. Définir ProgressBar comme ceci:

<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:max="200"
    android:progress="0"
    android:progressDrawable="@drawable/circular" />

Créer un drawable:

circular (niveau API < 21):

<shape
   android:innerRadiusRatio="2.3"
   android:shape="ring"
   android:thickness="5sp" >
   <solid android:color="@color/someColor" />
</shape>

circular API (Niveau >= 21):

<shape
   android:useLevel="true"
   android:innerRadiusRatio="2.3"
   android:shape="ring"
   android:thickness="5sp" >
   <solid android:color="@color/someColor" />
</shape>

useLevelfalse par défaut au niveau 21 de L'API.

Maintenant, depuis que nous avons mis en max = 200, pour atteindre le demi cercle, la portée du progrès devrait être 0100. Vous pouvez jouer avec ces valeurs atteindre la forme désirée.

Donc l'utiliser comme ceci:

ProgressBar progressBar = (Progressbar) view.findViewById(R.id.progressBar);
progressBar.setProgress(value); // 0 <= value <= 100
3
répondu Rohit Arya 2016-04-11 10:58:34

c'est une vue qui a une hauteur égale à la moitié de sa largeur. Utiliser les opérateurs d'ajuster le comportement souhaité. Par défaut la progression est 0 et la largeur de l'arc est 20. L'appel de setProgress () invalidera la vue avec le progrès donné. L'ajout d'un fond de dessin est possible et la barre de progression sera dessinée sur le dessus.

public class SemicircularProgressBar extends View {
private int mProgress;
private RectF mOval;
private RectF mOvalInner;
private Paint mPaintProgress;
private Paint mPaintClip;
private float ovalsDiff;
private Path clipPath;

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

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

public SemicircularProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    mProgress = 0;
    ovalsDiff = 20;
    mOval = new RectF();
    mOvalInner = new RectF();
    clipPath = new Path();
    mPaintProgress = new Paint();
    mPaintProgress.setColor(Color.GREEN);
    mPaintProgress.setAntiAlias(true);
    mPaintClip = new Paint();
    mPaintClip.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    mPaintClip.setAlpha(0);
    mPaintClip.setAntiAlias(true);
}


// call this from the code to change the progress displayed
public void setProgress(int progress) {
    this.mProgress = progress;
    invalidate();
}

// sets the width of the progress arc
public void setProgressBarWidth(float width) {
    this.ovalsDiff = width;
    invalidate();
}

// sets the color of the bar (#FF00FF00 - Green by default)
public void setProgressBarColor(int color){
    this.mPaintProgress.setColor(color);
}

@Override
public void onDraw(Canvas c) {
    super.onDraw(c);
    mOval.set(0, 0, this.getWidth(), this.getHeight()*2);
    mOvalInner.set(0+ovalsDiff, 0+ovalsDiff, this.getWidth()-ovalsDiff, this.getHeight()*2);
    clipPath.addArc(mOvalInner, 180, 180);
    c.clipPath(clipPath, Op.DIFFERENCE);
    c.drawArc(mOval, 180, 180f * ((float) mProgress / 100), true, mPaintProgress);
}

// Setting the view to be always a rectangle with height equal to half of its width
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
    int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
    this.setMeasuredDimension(parentWidth/2, parentHeight);
    ViewGroup.LayoutParams params = this.getLayoutParams();
    params.width = parentWidth;
    params.height = parentWidth/2;
    this.setLayoutParams(params);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
1
répondu SceLus 2014-03-24 14:13:55

Vous pouvez utiliser cette bibliothèque :

 compile 'com.github.lzyzsd:circleprogress:1.1.1'

enter image description here

par exemple :

   <com.github.lzyzsd.circleprogress.DonutProgress
        android:layout_marginLeft="50dp"
        android:id="@+id/donut_progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:donut_progress="30"/>

enter image description here

<com.github.lzyzsd.circleprogress.ArcProgress
        android:id="@+id/arc_progress"
        android:background="#214193"
        android:layout_marginLeft="50dp"
        android:layout_width="100dp"
        android:layout_height="100dp"
        custom:arc_progress="55"
        custom:arc_bottom_text="MEMORY"/>

Pour plus d'informations, consultez le site web suivant :

https://github.com/lzyzsd/CircleProgress

1
répondu Masoud Siahkali 2016-11-06 12:42:51

Vous pouvez être en mesure d'utiliser ce github bibliothèque - circularseekbar. Pour réaliser le demi-cercle, vous devrez manipuler les attributs suivants: "app: start_angle" & "app: end_angle"

Plus D'Options:

  1. Le Holo Seekbar bibliothèque
  2. tutoriel montrant le seekbar semi-circulaire lien vers le tutoriel
0
répondu user1406716 2014-03-19 15:11:36