181 votes

Formes multiples de gradients

Je souhaite créer une forme qui ressemble à l’image suivante :

alt text

Notez les gradients de la moitié supérieurs de couleur 1 vers 2, mais il y a un fond demi que dégradés de couleur 3 à la couleur 4. Je sais comment faire une forme avec un dégradé simple, mais je ne suis pas sûr de savoir comment diviser une forme en deux moitiés et faire 1 forme avec 2 différents gradients.

Toutes les idées ?

388voto

kcoppock Points 57219

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:

alt text

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! :)

30voto

LordParsley Points 622

Vous pouvez superposer des formes gradients dans le fichier xml à l’aide d’une liste des calques. Imaginez un bouton dont l’État par défaut comme ci-dessous, où le deuxième élément est semi-transparent. Il ajoute une sorte de vignettage. (Veuillez excuser les couleurs personnalisées.)

4voto

konmik Points 121

Vous pouvez le faire en utilisant seulement des formes de xml - juste utiliser la liste des calques et négatif rembourrage comme ceci :

0voto

Greg D Points 24218

Avez-vous essayé de superposer un dégradé avec une opacité presque transparent pour le clou sur le dessus une autre image avec une opacité opaque pour le dégradé vert ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X