web-dev-qa-db-fra.com

Android: barre de progression semi-circulaire

Je veux une 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 n'ai pas réussi. j'ai également fatigué une bibliothèque de barre de progression personnalisée, mais le résultat est le même.

aucune suggestion.

à la recherche d'un développement unique et utilisé dans toutes les tailles d'écran.

17
Dhaval Parmar

Cela peut être mis en œuvre en découpant un canevas contenant une image à un angle (en dessinant un arc).

Vous pouvez utiliser une image quelque chose comme ça

enter image description here

Et découpez 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 obtenez le chemin, vous pouvez utiliser la fonction clipPath pour découper le canevas dans ce chemin.

canvas.clipPath(mClippingPath);

Voici le code complet

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 la fonction clipPath ne fonctionne pas si le hardware acceleration Est activé. Vous pouvez désactiver l'accélération matérielle uniquement pour cette 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);
    }

}  

Au fur et à mesure que la progression change, vous pouvez définir la barre de progression en appelant la 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. J'espère que ça aide!!

Edit: Pour déplacer le demi-cercle en bas de l'écran, modifiez la valeur de mPivotY. Quelque chose comme ça

//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);
        }
39
Abhishek V

Vous pouvez essayer SeekArc Library . Je sais que c'est un autre type de barre de recherche, mais avec une personnalisation mineure, vous pouvez l'utiliser pour votre application comme barre de progression. J'ai fait pareil. Vous avez juste besoin de changer certaines propriétés comme
seekarc:touchInside="false".
C'est assez simple.

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

Custom progressbar in CleanMaster

img src: CleanMaster sur Google Play

9
saran

Vous pouvez également utiliser le ProgressBar natif pour réaliser un demi-cercle. Définissez 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éez un dessin:

circular (niveau API <21):

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

circular (Niveau API> = 21):

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

useLevel est false par défaut dans l'API niveau 21.

Maintenant que nous avons défini max = 200, pour réaliser un demi-cercle, la plage de progression doit être 0 à 100. Vous pouvez jouer avec ces valeurs pour obtenir la forme souhaitée.

Utilisez-le ainsi:

ProgressBar progressBar = (Progressbar) view.findViewById(R.id.progressBar);
progressBar.setProgress(value); // 0 <= value <= 100
3
Rohit Arya

Il s'agit d'une vue qui a une hauteur égale à la moitié de sa largeur. Utilisez les paramètres pour ajuster le comportement comme vous le souhaitez. Par défaut, la progression est 0 et la largeur de l'arc est de 20. L'appel à setProgress () invalidera la vue avec la progression donnée. L'ajout d'un arrière-plan dessinable est possible et la barre de progression sera dessinée en haut.

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
SceLus

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
Masoud Siahkali

Vous pourrez peut-être utiliser ceci bibliothèque github - circularseekbar . Pour réaliser le demi-cercle, vous devrez manipuler les attributs suivants: "app: start_angle" & "app: end_angle"

Plus d'options :

  1. La bibliothèque Holo Seekbar
  2. Tutoriel montrant la barre de recherche semi-circulaire lien vers le tutoriel
0
user1406716