J'essaie de créer une barre de progression arrondie. C'est ce que je veux réaliser
Il y a un anneau de fond de couleur grise. En plus de cela, une barre de progression de couleur bleue apparaît, qui se déplace dans une trajectoire circulaire de 0 à 360 en 60 ou quel que soit le nombre de secondes.
Voici mon exemple de code.
<ProgressBar
Android:id="@+id/ProgressBar"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
style="?android:attr/progressBarStyleLarge"
Android:indeterminateDrawable="@drawable/progressBarBG"
Android:progress="50"
/>
Pour ce faire, je crée une liste de couches dans la barre de progression "progressBarBG". Dans cette liste, je donne deux éléments comme indiqué.
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@Android:id/background">
<shape
Android:shape="ring"
Android:innerRadius="64dp"
Android:thickness="8dp"
Android:useLevel="false">
<solid Android:color="@color/grey" />
</shape>
</item>
<item Android:id="@Android:id/progress">
<clip>
<shape
Android:shape="ring"
Android:innerRadius="64dp"
Android:thickness="8dp"
Android:useLevel="false">
<solid Android:color="@color/blue" />
</shape>
</clip>
</item>
Maintenant, le premier anneau gris est bien généré. L'anneau bleu commence cependant à gauche du dessinable et va à droite, tout comme le fonctionnement d'une barre de progression linéaire. C’est ainsi qu’il affiche une progression de 50% avec la flèche de couleur rouge indiquant la direction.
Je souhaite déplacer la barre de progression bleue dans le tracé circulaire comme prévu.
Voici mes deux solutions.
Réponse courte:
Au lieu de créer un layer-list
, je l'ai séparé en deux fichiers. Un pour ProgressBar
et un pour son arrière-plan.
Ceci est le fichier ProgressDrawable
(dossier @drawable): circular_progress_bar.xml
<?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="1dp"
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>
Et ceci pour sa background
(@ dossier dessnable): 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="1dp"
Android:useLevel="false">
<solid Android:color="#CCC" />
</shape>
Et à la fin, dans la mise en page que vous travaillez:
<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="100"
Android:progress="65" />
Voici le résultat:
Réponse longue:
Utilisez une vue personnalisée qui hérite du Android.view.View
Voici le projet complet sur github
J'ai fait de manière simple:
S'il vous plaît vérifier la capture d'écran pour la même chose.
CustomProgressBarActivity.Java :
public class CustomProgressBarActivity extends AppCompatActivity {
private TextView txtProgress;
private ProgressBar progressBar;
private int pStatus = 0;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_progressbar);
txtProgress = (TextView) findViewById(R.id.txtProgress);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
new Thread(new Runnable() {
@Override
public void run() {
while (pStatus <= 100) {
handler.post(new Runnable() {
@Override
public void run() {
progressBar.setProgress(pStatus);
txtProgress.setText(pStatus + " %");
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
pStatus++;
}
}
}).start();
}
}
activity_custom_progressbar.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"
Android:paddingBottom="@dimen/activity_vertical_margin"
Android:paddingLeft="@dimen/activity_horizontal_margin"
Android:paddingRight="@dimen/activity_horizontal_margin"
Android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.skholingua.Android.custom_progressbar_circular.MainActivity" >
<RelativeLayout
Android:layout_width="wrap_content"
Android:layout_centerInParent="true"
Android:layout_height="wrap_content">
<ProgressBar
Android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
Android:layout_width="250dp"
Android:layout_height="250dp"
Android:layout_centerInParent="true"
Android:indeterminate="false"
Android:max="100"
Android:progress="0"
Android:progressDrawable="@drawable/custom_progressbar_drawable"
Android:secondaryProgress="0" />
<TextView
Android:id="@+id/txtProgress"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignBottom="@+id/progressBar"
Android:layout_centerInParent="true"
Android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</RelativeLayout>
custom_progressbar_drawable.xml :
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:fromDegrees="-90"
Android:pivotX="50%"
Android:pivotY="50%"
Android:toDegrees="270" >
<shape
Android:shape="ring"
Android:useLevel="false" >
<gradient
Android:centerY="0.5"
Android:endColor="#FA5858"
Android:startColor="#0099CC"
Android:type="sweep"
Android:useLevel="false" />
</shape>
</rotate>
J'espère que cela vous aidera.
J'ai écrit des exemples détaillés sur barre de progression circulaire sous Android ici sur mon blog demonuts.com . Vous pouvez aussi y trouver le code source complet et l'explication.
Voici comment j'ai créé progressbar circulaire avec pourcentage à l'intérieur du cercle en code pur sans aucune bibliothèque.
commencez par créer un fichier dessinable appelé circular.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@Android:id/secondaryProgress">
<shape
Android:innerRadiusRatio="6"
Android:shape="ring"
Android:thicknessRatio="20.0"
Android:useLevel="true">
<gradient
Android:centerColor="#999999"
Android:endColor="#999999"
Android:startColor="#999999"
Android:type="sweep" />
</shape>
</item>
<item Android:id="@Android:id/progress">
<rotate
Android:fromDegrees="270"
Android:pivotX="50%"
Android:pivotY="50%"
Android:toDegrees="270">
<shape
Android:innerRadiusRatio="6"
Android:shape="ring"
Android:thicknessRatio="20.0"
Android:useLevel="true">
<rotate
Android:fromDegrees="0"
Android:pivotX="50%"
Android:pivotY="50%"
Android:toDegrees="360" />
<gradient
Android:centerColor="#00FF00"
Android:endColor="#00FF00"
Android:startColor="#00FF00"
Android:type="sweep" />
</shape>
</rotate>
</item>
</layer-list>
Maintenant, dans votre activity_main.xml
, ajoutez ce qui suit:
<?xml version="1.0" encoding="utf-8"?>
<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"
Android:background="@color/dialog"
tools:context="com.example.parsaniahardik.progressanimation.MainActivity">
<ProgressBar
Android:id="@+id/circularProgressbar"
style="?android:attr/progressBarStyleHorizontal"
Android:layout_width="250dp"
Android:layout_height="250dp"
Android:indeterminate="false"
Android:max="100"
Android:progress="50"
Android:layout_centerInParent="true"
Android:progressDrawable="@drawable/circular"
Android:secondaryProgress="100"
/>
<ImageView
Android:layout_width="90dp"
Android:layout_height="90dp"
Android:background="@drawable/whitecircle"
Android:layout_centerInParent="true"/>
<TextView
Android:id="@+id/tv"
Android:layout_width="250dp"
Android:layout_height="250dp"
Android:gravity="center"
Android:text="25%"
Android:layout_centerInParent="true"
Android:textColor="@color/colorPrimaryDark"
Android:textSize="20sp" />
</RelativeLayout>
Dans activity_main.xml
, j'ai utilisé une image circulaire avec un fond blanc pour afficher un fond blanc autour du pourcentage. Voici l'image:
Vous pouvez changer la couleur de cette image pour définir une couleur personnalisée autour du texte en pourcentage.
Enfin, ajoutez enfin le code suivant à MainActivity.Java
:
import Android.content.res.Resources;
import Android.graphics.drawable.Drawable;
import Android.os.Handler;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.view.animation.DecelerateInterpolator;
import Android.widget.ProgressBar;
import Android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int pStatus = 0;
private Handler handler = new Handler();
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.circular);
final ProgressBar mProgress = (ProgressBar) findViewById(R.id.circularProgressbar);
mProgress.setProgress(0); // Main Progress
mProgress.setSecondaryProgress(100); // Secondary Progress
mProgress.setMax(100); // Maximum Progress
mProgress.setProgressDrawable(drawable);
/* ObjectAnimator animation = ObjectAnimator.ofInt(mProgress, "progress", 0, 100);
animation.setDuration(50000);
animation.setInterpolator(new DecelerateInterpolator());
animation.start();*/
tv = (TextView) findViewById(R.id.tv);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while (pStatus < 100) {
pStatus += 1;
handler.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
mProgress.setProgress(pStatus);
tv.setText(pStatus + "%");
}
});
try {
// Sleep for 200 milliseconds.
// Just to display the progress slowly
Thread.sleep(8); //thread will take approx 1.5 seconds to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
Si vous voulez faire une barre de progression horizontale, suivez ce lien, il contient de nombreux exemples intéressants avec le code source:
http://www.skholingua.com/Android-basic/user-interface/form-widgets/progressbar
J'ai réalisé une bibliothèque Open Source sur GitHub CircularProgressBar qui fait exactement ce que vous voulez de la manière la plus simple possible:
Pour créer une ProgressBar circulaire, ajoutez CircularProgressBar dans votre présentation XML et ajoutez la bibliothèque CircularProgressBar dans votre projecteur ou vous pouvez également le saisir via Gradle:
compile 'com.mikhaellopez:circularprogressbar:1.0.0'
<com.mikhaellopez.circularprogressbar.CircularProgressBar
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
app:background_progressbar_color="#FFCDD2"
app:background_progressbar_width="5dp"
app:progressbar_color="#F44336"
app:progressbar_width="10dp" />
Vous devez utiliser les propriétés suivantes dans votre XML pour modifier votre CircularProgressBar.
Propriétés:
app:progress
(entier) >> valeur par défaut 0app:progressbar_color
(couleur) >> défaut NOIRapp:background_progressbar_color
(couleur) >> GRIS par défautapp:progressbar_width
(dimension) >> défaut 7dpapp:background_progressbar_width
(dimension) >> 3dp par défautCircularProgressBar circularProgressBar = (CircularProgressBar)findViewById(R.id.yourCircularProgressbar);
circularProgressBar.setColor(ContextCompat.getColor(this, R.color.progressBarColor));
circularProgressBar.setBackgroundColor(ContextCompat.getColor(this, R.color.backgroundProgressBarColor));
circularProgressBar.setProgressBarWidth(getResources().getDimension(R.dimen.progressBarWidth));
circularProgressBar.setBackgroundProgressBarWidth(getResources().getDimension(R.dimen.backgroundProgressBarWidth));
int animationDuration = 2500; // 2500ms = 2,5s
circularProgressBar.setProgressWithAnimation(65, animationDuration); // Default duration = 1500ms
Téléchargez ou branchez cette bibliothèque ici >> https://github.com/lopspower/CircularProgressBar
Je suis nouveau, je ne peux donc pas commenter, mais j'ai pensé partager le correctif paresseux. J'utilise également l'approche originale de Pedram et je viens de rencontrer le même problème avec Lollipop. Mais alanv dans un autre post avait un correctif d'une ligne. C'est une sorte de bogue ou de surveillance dans API21. Littéralement, ajoutez simplement Android:useLevel="true"
à votre progression xml. La nouvelle approche de Pedram reste le correctif approprié, mais je pensais simplement partager le correctif paresseux.
https://github.com/passsy/Android-HoloCircularProgressBar est un exemple de bibliothèque qui effectue cela. Comme Tenfour04 l'a déclaré, il devra être quelque peu personnalisé, en ce sens que cela n'est pas directement pris en charge. Si cette bibliothèque ne se comporte pas comme vous le souhaitez, vous pouvez la modifier et en modifier les détails pour la faire fonctionner à votre guise. Si vous implémentez quelque chose que d'autres peuvent ensuite réutiliser, vous pouvez même envoyer une demande d'extraction pour que cette opération soit fusionnée!
essayez cette méthode pour créer un bitmap et le définir en mode image.
private void circularImageBar(ImageView iv2, int i) {
Bitmap b = Bitmap.createBitmap(300, 300,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
Paint paint = new Paint();
Paint.setColor(Color.parseColor("#c4c4c4"));
Paint.setStrokeWidth(10);
Paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(150, 150, 140, Paint);
Paint.setColor(Color.parseColor("#FFDB4C"));
Paint.setStrokeWidth(10);
Paint.setStyle(Paint.Style.FILL);
final RectF oval = new RectF();
Paint.setStyle(Paint.Style.STROKE);
oval.set(10,10,290,290);
canvas.drawArc(oval, 270, ((i*360)/100), false, Paint);
Paint.setStrokeWidth(0);
Paint.setTextAlign(Align.CENTER);
Paint.setColor(Color.parseColor("#8E8E93"));
Paint.setTextSize(140);
canvas.drawText(""+i, 150, 150+(Paint.getTextSize()/3), Paint);
iv2.setImageBitmap(b);
}
Voici une vue personnalisée simple pour la progression du cercle d'affichage. Vous pouvez modifier et optimiser davantage en fonction de votre projet.
class CircleProgressBar @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val backgroundWidth = 10f
private val progressWidth = 20f
private val backgroundPaint = Paint().apply {
color = Color.LTGRAY
style = Paint.Style.STROKE
strokeWidth = backgroundWidth
isAntiAlias = true
}
private val progressPaint = Paint().apply {
color = Color.RED
style = Paint.Style.STROKE
strokeWidth = progressWidth
isAntiAlias = true
}
var progress: Float = 0f
set(value) {
field = value
invalidate()
}
private val oval = RectF()
private var centerX: Float = 0f
private var centerY: Float = 0f
private var radius: Float = 0f
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
centerX = w.toFloat() / 2
centerY = h.toFloat() / 2
radius = w.toFloat() / 2 - progressWidth
oval.set(centerX - radius,
centerY - radius,
centerX + radius,
centerY + radius)
super.onSizeChanged(w, h, oldw, oldh)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawCircle(centerX, centerY, radius, backgroundPaint)
canvas?.drawArc(oval, 270f, 360f * progress, false, progressPaint)
}
}
Exemple d'utilisation
xml
<com.example.androidcircleprogressbar.CircleProgressBar
Android:id="@+id/circle_progress"
Android:layout_width="200dp"
Android:layout_height="200dp" />
kotlin
class MainActivity : AppCompatActivity() {
val TOTAL_TIME = 10 * 1000L
override fun onCreate(savedInstanceState: Bundle?) {
...
timeOutRemoveTimer.start()
}
private var timeOutRemoveTimer = object : CountDownTimer(TOTAL_TIME, 10) {
override fun onFinish() {
circle_progress.progress = 1f
}
override fun onTick(millisUntilFinished: Long) {
circle_progress.progress = (TOTAL_TIME - millisUntilFinished).toFloat() / TOTAL_TIME
}
}
}
Résultat
Changement
Android:useLevel="false"
à
Android:useLevel="true"
pour un deuxième sahpe avec id="@Android:id/progress
esperons que ça marche
@Pedram, votre ancienne solution fonctionne aussi très bien dans Lollipop (et mieux que la nouvelle car elle est utilisable partout, y compris dans les vues distantes), il suffit de changer votre code circular_progress_bar.xml
en ceci:
<?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="1dp"
Android:useLevel="true"> <!-- Just add this line -->
<gradient
Android:angle="0"
Android:endColor="#007DD6"
Android:startColor="#007DD6"
Android:type="sweep"
Android:useLevel="false" />
</shape>
</rotate>
package com.example.ankitrajpoot.myapplication;
import Android.app.Activity;
import Android.os.Bundle;
import Android.view.View;
import Android.widget.ProgressBar;
public class MainActivity extends Activity {
private ProgressBar spinner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner=(ProgressBar)findViewById(R.id.progressBar);
spinner.setVisibility(View.VISIBLE);
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/loadingPanel"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center">
<ProgressBar
Android:id="@+id/progressBar"
Android:layout_width="48dp"
style="?android:attr/progressBarStyleLarge"
Android:layout_height="48dp"
Android:indeterminateDrawable="@drawable/circular_progress_bar"
Android:indeterminate="true" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:pivotX="50%"
Android:pivotY="50%"
Android:fromDegrees="0"
Android:toDegrees="1080">
<shape
Android:shape="ring"
Android:innerRadiusRatio="3"
Android:thicknessRatio="8"
Android:useLevel="false">
<size
Android:width="56dip"
Android:height="56dip" />
<gradient
Android:type="sweep"
Android:useLevel="false"
Android:startColor="@Android:color/transparent"
Android:endColor="#1e9dff"
Android:angle="0"
/>
</shape>
</rotate>