J'essaie de créer une forme dessinable avec un fond dégradé radial, avec un rayon qui s'adaptera à la taille de l'écran (jetez un œil à la documentation ).
Voici mon code:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:shape="rectangle" >
<gradient
Android:endColor="#000"
Android:gradientRadius="50%p"
Android:startColor="#5d2456"
Android:type="radial" />
</shape>
Mais cela ne semble pas fonctionner. si je supprime le "% p", ça marche, mais alors le rayon sera statique, donc ne s'ajustant pas à la taille de l'écran ... Une idée de ce qui ne va pas?
D'après ce que j'ai testé, le %
fonctionne, mais pas comme prévu.
Tout d'abord
Android:gradientRadius="50"
semble prendre la valeur en pixels 50px
Android:gradientRadius="50%"
est converti comme si 50% = 0,5 px, essayez
Android:gradientRadius="5000%"
et vous verrez un rayon de 50 pixels.
En utilisant %p
a un résultat similaire. Évidemment, c'est quelque chose qui, je l'espère, sera modifié à l'avenir, car il n'a pas beaucoup d'utilité tel qu'il est. Habituellement, les ressources XML ShapeDrawable adaptent leur taille à un conteneur externe, dans ce cas, gradientRadius
définit la taille indépendamment du conteneur.
J'ai fini par créer une vue personnalisée avec la méthode onDraw remplacée suivante:
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
int maxSize = Math.max(getHeight(), getWidth());
RadialGradient gradient = new RadialGradient(
getWidth()/2,
getHeight()/2,
maxSize,
new int[] {Color.RED, Color.BLACK},
new float[] {0, 1},
Android.graphics.Shader.TileMode.CLAMP);
Paint.setDither(true);
Paint.setShader(gradient);
canvas.drawRect(0, 0, getWidth(), getHeight(), Paint);
}
Dans votre mise en page, ajoutez simplement la vue:
<yourpackage.GradientView
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
Bien sûr, il serait possible de créer des attributs pour la vue, par exemple. couleur, pourcentage pour permettre la personnalisation via XML.
Notez que les pourcentages gradientRadius fonctionnent dans Lollipop. Mais si vous devez prendre en charge pré-Lollipop, j'ai développé la réponse de @ marnaish en ajoutant des attributs XML. Mon gradientRadius est défini comme un pourcentage de la largeur de la vue parent:
public class RadialGradientView extends View {
private final int endColor;
private final int startColor;
private final float gradientRadiusWidthPercent;
private final float centerY;
private final float centerX;
private Paint paint;
public RadialGradientView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RadialGradientView, 0, 0);
startColor = a.getColor(R.styleable.RadialGradientView_startColor, Color.RED);
endColor = a.getColor(R.styleable.RadialGradientView_endColor, Color.BLACK);
gradientRadiusWidthPercent = a.getFloat(R.styleable.RadialGradientView_gradientRadiusWidthPercent, 1);
centerX = a.getFloat(R.styleable.RadialGradientView_centerX, .5f);
centerY = a.getFloat(R.styleable.RadialGradientView_centerY, .5f);
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
RadialGradient gradient = new RadialGradient(
parentWidth*centerX,
parentHeight*centerY,
parentWidth*gradientRadiusWidthPercent,
new int[] {startColor, endColor},
null,
Android.graphics.Shader.TileMode.CLAMP);
Paint.setDither(true);
Paint.setShader(gradient);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), Paint);
}
}
Dans attrs.xml:
<declare-styleable name="RadialGradientView">
<attr name="startColor" format="color|reference"/>
<attr name="endColor" format="color|reference"/>
<attr name="gradientRadiusWidthPercent" format="float"/>
<attr name="centerX" format="float"/>
<attr name="centerY" format="float"/>
</declare-styleable>
Malheureusement, vous ne pouvez pas créer un dessin XML à partir d'une classe personnalisée, vous ne pouvez donc pas le définir en tant qu'arrière-plan Android d'une vue. La solution consiste à utiliser un FrameLayout pour le superposer comme arrière-plan.
<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="100dp">
<com.RadialGradientView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:centerX=".3"
app:centerY=".5"
app:endColor="#0f0"
app:startColor="#f00"
app:gradientRadiusWidthPercent=".5"
/>
<TextView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center"
Android:text="What's up world?"/>
</FrameLayout>
Il est impossible de définir un rayon de coin de forme exprimé en pourcentage dans un fichier XML dessinable.
Vous pouvez créer une forme dessinable au moment de l'exécution, similaire à cet article https://stackoverflow.com/a/4943888/604504
De cette façon, vous pouvez calculer le pourcentage après avoir récupéré la taille de l'écran.