tutorial developer color android gradient shapes

android - developer - Formas de mĂșltiples gradientes



shape android (5)

Me gustaría crear una forma que sea como la siguiente imagen:

Observe los gradientes de la mitad superior del color 1 al color 2, pero hay una mitad inferior que se degrada del color 3 al color 4. Sé cómo hacer una figura con un solo degradado, pero no estoy seguro de cómo dividir una forma en dos mitades y hacer 1 forma con 2 gradientes diferentes.

¿Algunas ideas?


¿Ha intentado superponer un degradado con una opacidad casi transparente para resaltar encima de otra imagen con una opacidad opaca para el degradado verde?


No creo que puedas hacer esto en XML (al menos no en Android), pero he encontrado una buena solución publicada here que parece ser de gran ayuda.

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);

Básicamente, la matriz int le permite seleccionar múltiples paradas de color, y la siguiente matriz flotante define dónde se ubican esas paradas (de 0 a 1). Entonces puede, como se dijo, usar esto como un Drawable estándar.

Editar: Así es cómo podría usar esto en su escenario. Digamos que tienes un botón definido en XML como ese:

<Button android:id="@+id/thebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Press Me!" />

Luego pondrías algo como esto en tu método onCreate ():

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.setBackground((Drawable)p);

No puedo probar esto en este momento, este es un código de mi cabeza, pero básicamente solo reemplace o agregue stops para los colores que necesita. Básicamente, en mi ejemplo, comenzaría con un color verde claro, se desvanecería en blanco ligeramente antes del centro (para dar un desvanecimiento, en lugar de una transición dura), se desvanecería de blanco a medio verde entre 45% y 55%, luego se desvanecería de verde medio a verde oscuro desde el 55% hasta el final. Puede que esto no se parezca exactamente a tu forma (en este momento, no tengo forma de probar estos colores), pero puedes modificar esto para replicar tu ejemplo.

Editar: Además, el 0, 0, 0, theButton.getHeight() refiere a las coordenadas x0, y0, x1, y1 del degradado. Básicamente, comienza en x = 0 (lado izquierdo), y = 0 (arriba), y se extiende hasta x = 0 (queremos un gradiente vertical, por lo que no es necesario el ángulo de izquierda a derecha), y = la altura del botón. Entonces, el gradiente va en un ángulo de 90 grados desde la parte superior del botón hasta la parte inferior del botón.

Editar: Bien, entonces tengo una idea más que funciona, jaja. En este momento funciona en XML, pero también debería ser factible para las formas en Java. Es algo complejo, e imagino que hay una forma de simplificarlo en una sola forma, pero esto es lo que tengo por ahora:

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>

De acuerdo, básicamente he creado un degradado de forma en XML para el degradado verde horizontal, establecido en un ángulo de 0 grados, yendo desde el color verde izquierdo del área superior, al color verde correcto. A continuación, hice un rectángulo de forma con un gris medio transparente. Estoy bastante seguro de que podría incluirse en el XML de la lista de capas, obviando este archivo adicional, pero no estoy seguro de cómo. Pero está bien, entonces el tipo de parte hacky entra en el archivo XML layer_list. Pongo el degradado verde como la capa inferior, luego pongo la mitad superpuesta como la segunda capa, compensada desde la parte superior por 50dp. Obviamente, querrás que este número siempre sea la mitad del tamaño de tu vista, y no un 50dp fijo. Aunque no creo que puedas usar porcentajes. A partir de ahí, simplemente inserté un TextView en mi diseño test.xml, usando el archivo layer_list.xml como mi fondo. Establecí la altura en 100 pb (dos veces el tamaño del desplazamiento de la superposición), lo que da como resultado lo siguiente:

Tada!

Una edición más : me di cuenta de que puedes insertar las formas en la lista de capas dibujables como elementos, lo que significa que ya no necesitas 3 archivos XML separados. Puedes lograr el mismo resultado combinándolos así:

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>

¡Puedes poner tantos objetos como quieras de esta manera! Puedo tratar de jugar y ver si puedo obtener un resultado más versátil a través de Java.

Creo que esta es la última edición ... : Bien, entonces definitivamente puedes arreglar el posicionamiento a través de Java, como el siguiente:

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);

¡Sin embargo! Esto conduce a otro problema más molesto en el sentido de que no se puede medir el TextView hasta que se haya dibujado. Todavía no estoy seguro de cómo puede lograr esto ... pero manualmente insertando un número para topInset funciona.

Mentí, una edición más

De acuerdo, descubrimos cómo actualizar manualmente esta capa dibujable para que coincida con la altura del contenedor, la descripción completa se puede encontrar here . Este código debe ir en su método onCreate ():

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); } });

¡Y he terminado! ¡Uf! :)


PUEDES hacerlo usando solo formas xml - solo usa layer-list AND padding negativo como este:

<layer-list> <item> <shape> <solid android:color="#ffffff" /> <padding android:top="20dp" /> </shape> </item> <item> <shape> <gradient android:endColor="#ffffff" android:startColor="#efefef" android:type="linear" android:angle="90" /> <padding android:top="-20dp" /> </shape> </item> </layer-list>


Pruebe este método y luego puede hacer todo lo que quiera.
Es como una pila, así que ten cuidado con qué elemento viene primero o último.

<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:right="50dp" android:start="10dp" android:left="10dp"> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="3dp" /> <solid android:color="#012d08"/> </shape> </item> <item android:top="50dp"> <shape android:shape="rectangle"> <solid android:color="#7c4b4b" /> </shape> </item> <item android:top="90dp" android:end="60dp"> <shape android:shape="rectangle"> <solid android:color="#e2cc2626" /> </shape> </item> <item android:start="50dp" android:bottom="20dp" android:top="120dp"> <shape android:shape="rectangle"> <solid android:color="#360e0e" /> </shape> </item>


Puede superponer formas de degradado en el xml usando una lista de capas. Imagine un botón con el estado predeterminado como se muestra a continuación, donde el segundo elemento es semitransparente. Agrega una especie de viñeteado. (Disculpe los colores personalizados).

<!-- Normal state. --> <item> <layer-list> <item> <shape> <gradient android:startColor="@color/grey_light" android:endColor="@color/grey_dark" android:type="linear" android:angle="270" android:centerColor="@color/grey_mediumtodark" /> <stroke android:width="1dp" android:color="@color/grey_dark" /> <corners android:radius="5dp" /> </shape> </item> <item> <shape> <gradient android:startColor="#00666666" android:endColor="#77666666" android:type="radial" android:gradientRadius="200" android:centerColor="#00666666" android:centerX="0.5" android:centerY="0" /> <stroke android:width="1dp" android:color="@color/grey_dark" /> <corners android:radius="5dp" /> </shape> </item> </layer-list> </item>