Comment dessiner un cercle avec un dégradé radial dans une toile?
J'ai créé un cercle bouton qui permet de changer de couleur quand je l'appelle d'une fonction. Ce que je veux, c'est pour en créer un autre, qui crée le même cercle bouton mais avec un dégradé radial, qui commence dans le milieu avec la couleur choisie et qui va transparente lorsque vous sortez du cercle.
J'ai créé un code similaire à l'aide de l'un à Comment définir le style de gradient pour la peinture de l'objet? mais n'avez pas travaillé.
Le code que j'ai essayé est à ce porpuse est:
mPaint.setShader(new RadialGradient(0, 0, height/3, Color.BLACK, Color.TRANSPARENT, Shader.TileMode.MIRROR));
La classe suivante est celle que j'ai créé pour un Cercle de Bouton.
public class ColorGradientCircleButton extends View{
private Paint mPaint;
private Paint mBitmapPaint;
private Bitmap mBitmap;
private Canvas mCanvas;
private int width, height;
public ColorGradientCircleButton(Context context) {
super(context);
init();
}
public ColorGradientCircleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ColorGradientCircleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(1);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mCanvas.drawCircle(w/2, h/2, h/3, mPaint);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}
public void changeColor(int color){
mPaint.setColor(color);
mCanvas.drawCircle(width/2, height/2, height/3, mPaint);
invalidate();
}
}
source d'informationauteur Gabriel Esteban
Vous devez vous connecter pour publier un commentaire.
Nous devons migrer vers les cases de réponse.
OP a fondamentalement avons ici, et en fait, l'OP est révisé gist est génial.
Quelques conseils d'ordre général au sujet de la première tentative à la question:
1) Dans
protected void onSizeChanged(int w, int h, int oldw, int oldh)
:width = w;
il n'ya aucune raison pourquoi vous ne pouvez pas appelergetWidth()
quand vous en avez besoin. La raison pour laquelle il est conseillé est parce que leView
's largeur intérieure est très en retard aprèsonMeasure
. Par conséquent,onDraw
peut-être la prochaine fois que vous voulez le plus à jour la version, de sorte que l'utilisation de la lecture.mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
. La création d'un bitmap est un processus coûteux et gourmands en mémoire l'opération. Sauf si vous voulez écrire une image bitmap d'un fichier, ou l'envoyer à unBitmapDrawable
pour unImageView
ou quelque chose, vous n'avez pas besoin de le faire. Surtout avec des effets tirés sur l'INTERFACE utilisateur avec androidgraphics
bibliothèque.mCanvas = new Canvas(mBitmap);
suivie par une opération de dessin sur la nouvelle toile. Ce n'est jamais nécessaire. Et pourtant, je l'ai vu (pas de travail) dans de nombreuses bases de code et de tentatives. Je pense c'est la faute d'un vieux débordement de pile post qui a amené les gens à faire ce afin qu'ils puissent transformer une toile sur un affichage personnalisé, sans affecter le dessin sur le reste de la toile. D'ailleurs, si vous avez besoin de cela, utilisez.restore()
et.save()
à la place. Si vous voyeznew Canvas
être suspect.2)
onDraw(...)
:onDraw
comme la création d'objets, ou de tout traitement lourd. Mais vous avez encore besoin de faire les choses dansonDraw
que vous devez faireonDraw
!canvas.drawCircle(float cx, float cy, float radius, Paint paint)
avec des arguments comme par le docs.onDraw
. Si vous êtes inquiet au sujet de l'appel de cette tropcomme ce pourrait être le cas si l'ensemble de votre bouton est l'animation à travers l'écran, vous devez utiliser l'accélération matérielle disponible plus tard dans l'API versions, comme il sera détaillé dans un article intitulé L'optimisation de la Vue; très utile de lire si vous êtes en utilisant beaucoup de coutume établi vues.3) ce fichus dégradé radial. La prochaine question que vous avez eu, c'est que vous avez tout à fait à juste titre, de la création de votre peinture dans un
init
méthode ainsi que la création de l'objet était hors le tirage au sort. Mais alors, à très juste titre, il auraIllegalArgumentException
ed (je pense) sur vous parce que, à ce stade, legetHeight()
de la vue est de 0. Vous avez essayé en passant dans les petites valeurs de pixel - cela ne fonctionnera pas, sauf si vous savez quelque chose de magique à propos de tailles d'écran.Ce n'est pas votre problème autant que l'ennuyeux de visualiser le cycle au cœur de Android les modèles de conception. Le correctif est cependant assez facile: il suffit d'utiliser une partie plus tard de la vue du dessin, après la
onMeasure
appel à l'ensemble de la peinture filtre.Mais il y a quelques problèmes avec l'obtention de ce droit, à savoir que, parfois, fâcheusement,
onDraw
est appelée avant le point auquel vous vous attendez. Le résultat serait votre peinture est nul et vous ne seriez pas obtenir le comportement souhaité.J'ai trouvé une solution plus robuste est simplement de faire un espiègle et coquine peu null vérifier dans le
onDraw
et puis une seule fois construire la peinture de l'objet. Ce n'est pas à proprement parler optimale, mais compte tenu de la complexité du mode de laPaint
objets crochet avec Android graphiques natifs de la couche de mieux que d'essayer de chevaucher la peinture de la configuration et de la construction dans de nombreux fréquemment appelé lieux. Et il en fait sacrément le code plus clair.Ce serait ressembler (en modifiant votre gist):
Donc noter quelques changements - je pense que à partir de votre description vous souhaitez que les deux couleurs échangé tour dans les arguments, aussi n'oubliez pas de centre le centre de votre dégradé dans votre point de vue:
width/2
etheight/2
arguments.Bonne chance!