Formas de múltiples gradientes

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

texto alternativo

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?

No creo que puedas hacer esto en XML (al menos no en Android), pero he encontrado una buena solución publicada aquí 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:

  

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

      

half_overlay.xml

     

layer_list.xml

      

test.xml

     

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:

texto alternativo

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

               

¡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 aquí . 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! 🙂

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

                    

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

                

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

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