Je ne pense pas que vous pouvez le faire en XML (du moins pas dans Android), mais j'ai trouvé une bonne solution posté ici qui ressemble comme il serait d'une grande aide!
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0, 0, width, height,
new int[]{Color.GREEN, Color.GREEN, Color.WHITE, Color.WHITE},
new float[]{0,0.5f,.55f,1}, Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable p=new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
Fondamentalement, l'int tableau vous permet de sélectionner plusieurs arrêts de couleur, et le suivant float tableau définit l'endroit où ces arrêts sont placés (de 0 à 1). Vous pouvez ensuite, comme indiqué, il suffit d'utiliser cela comme un standard Drawable.
Edit: Voici comment vous pouvez l'utiliser dans votre scénario. Disons que vous avez un Bouton défini en XML comme ceci:
<Button
android:id="@+id/thebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
/>
Vous devez ensuite mettre quelque chose comme ceci dans votre onCreate() la méthode:
Button theButton = (Button)findViewById(R.id.thebutton);
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0, 0, 0, theButton.getHeight(),
new int[] {
Color.LIGHT_GREEN,
Color.WHITE,
Color.MID_GREEN,
Color.DARK_GREEN }, //substitute the correct colors for these
new float[] {
0, 0.45f, 0.55f, 1 },
Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable p = new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
theButton.setBackgroundDrawable((Drawable)p);
Je ne peux pas tester ceci en ce moment, c'est le code de ma tête, mais fondamentalement, il suffit de remplacer ou d'ajouter des arrêts pour les couleurs dont vous avez besoin. En gros, dans mon exemple, vous commencez avec un peu de vert, fondu au blanc légèrement avant que le centre (pour donner un effet de fondu, plutôt que d'une dure de transition), fondu de blanc à la mi-vert entre 45% et 55%, puis fondu à partir de mi-vert à vert foncé, passant de 55% à la fin. Cela peut ne pas ressembler exactement à la forme (je suis au travail, je n'ai aucun moyen de tester ces couleurs), mais vous pouvez modifier cette répliquer votre exemple.
Edit: Aussi, l' 0, 0, 0, theButton.getHeight()
se réfère à l'x0, y0, x1, y1 coordonnées de la pente. Donc, fondamentalement, il commence à x = 0 (à gauche), y = 0 (en haut), et s'étend à x = 0 (nous sommes vouloir un dégradé vertical, donc pas de gauche à l'angle droit est nécessaire), y = la hauteur du bouton. De sorte que le gradient va à un angle de 90 degrés à partir du haut et du bas vers le bas de la touche.
Edit: Bon, j'ai une idée qui fonctionne, haha. Pour l'instant il fonctionne dans le XML, mais devrait être faisable pour les formes en Java. C'est une sorte de complexe, et j'imagine qu'il y a un moyen de le simplifier en une seule forme, mais c'est ce que j'ai pour l'instant:
green_horizontal_gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners
android:radius="3dp"
/>
<gradient
android:angle="0"
android:startColor="#FF63a34a"
android:endColor="#FF477b36"
android:type="linear"
/>
</shape>
half_overlay.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid
android:color="#40000000"
/>
</shape>
layer_list.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item
android:drawable="@drawable/green_horizontal_gradient"
android:id="@+id/green_gradient"
/>
<item
android:drawable="@drawable/half_overlay"
android:id="@+id/half_overlay"
android:top="50dp"
/>
</layer-list>
test.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<TextView
android:id="@+id/image_test"
android:background="@drawable/layer_list"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:gravity="center"
android:text="Layer List Drawable!"
android:textColor="@android:color/white"
android:textStyle="bold"
android:textSize="26sp"
/>
</RelativeLayout>
Ok, donc en gros j'ai créé un gradient de forme XML pour l'horizontale verte gradient, fixé à un angle de 0 degré, en allant de la zone supérieure gauche de couleur verte, à la droite de couleur verte. Ensuite, j'ai fait un rectangle avec une demi-transparent gris. Je suis assez sûr que pourrait être incorporé dans la couche XML de liste, ce qui évite ce fichier supplémentaire, mais je ne suis pas sûr de savoir comment. Mais bon, ensuite le type de hacky partie arrive sur la layer_list fichier XML. J'ai mis le vert dégradé comme couche de fond, puis mettre la moitié de superposition, dans la deuxième couche, compensée par le haut par 50dp. Évidemment, vous voulez ce nombre à toujours être la moitié de ce que votre taille est bien, et n'est pas fixe 50dp. Je ne pense pas que vous pouvez utiliser des pourcentages, même si. À partir de là, j'ai juste inséré un TextView dans mon test.xml mise en page, à l'aide de la layer_list.xml fichier comme mon arrière-plan. J'ai réglé la hauteur de 100dp (deux fois la taille de l'offset de la superposition), entraînant la suivante:
Tada!
Un de plus edit: j'ai réalisé que vous pouvez simplement intégrer les formes dans la liste des calques drawable éléments, ce qui signifie que vous n'avez pas besoin de 3 fichiers XML plus! Vous pouvez obtenir le même résultat en les combinant comme suit:
layer_list.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners
android:radius="3dp"
/>
<gradient
android:angle="0"
android:startColor="#FF63a34a"
android:endColor="#FF477b36"
android:type="linear"
/>
</shape>
</item>
<item
android:top="50dp"
>
<shape
android:shape="rectangle"
>
<solid
android:color="#40000000"
/>
</shape>
</item>
</layer-list>
Vous pouvez empiler que de nombreux éléments que vous voulez de cette façon! Je peut essayer de jouer autour et voir si je peux obtenir une plus grande adaptabilité du résultat par le biais de Java.
Je pense que c'est la dernière édition...: d'Accord, alors vous pouvez certainement corriger le positionnement par le biais de Java, comme suit:
TextView tv = (TextView)findViewById(R.id.image_test);
LayerDrawable ld = (LayerDrawable)tv.getBackground();
int topInset = tv.getHeight() / 2 ; //does not work!
ld.setLayerInset(1, 0, topInset, 0, 0);
tv.setBackgroundDrawable(ld);
Toutefois! Cela nous amène à un autre problème gênant dans le fait que vous ne peut pas mesurer le TextView qu'après qu'il a été établi. Je ne suis pas certain comment vous pouvez accomplir cela...mais insérant manuellement un certain nombre de topInset fonctionne.
J'ai menti, un de plus éditer
Ok, trouvé comment mettre à jour manuellement cette couche dessinés à la hauteur du conteneur, description complète peut être trouvée ici. Ce code devrait aller dans votre onCreate() la méthode:
final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
LayerDrawable ld = (LayerDrawable)tv.getBackground();
ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
}
});
Et je suis fait! Ouf! :)