studio programacion herramientas fundamentos con avanzado aplicaciones android android-xml radial-gradients shapedrawable

programacion - manual de android en pdf



Radio de gradiente como porcentaje del tamaƱo de la pantalla (4)

Estoy tratando de crear una forma dibujable con fondo de degradado radial, con un radio que se ajustará al tamaño de la pantalla (eche un vistazo a la documentation pertinente).

Este es mi código:

<?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>

Pero parece que no funciona. si elimino el "% p", funciona, pero luego el radio será estático, por lo tanto, no se ajustará al tamaño de la pantalla ... ¿Alguna idea de lo que está mal?


Por lo que he probado, el % funciona, pero no como esperaba.
Ante todo

android:gradientRadius="50"

parece tomar el valor como píxeles 50px

android:gradientRadius="50%"

se convierte como si 50% = 0.5 px, intenta

android:gradientRadius="5000%"

y verá un radio de 50 píxeles.
Usar %p tiene un resultado similar. Obviamente, esto es algo que espero se modifique en el futuro, ya que no tiene mucho uso. Por lo general, los recursos XML ShapeDrawable adaptan su tamaño a algún contenedor externo, en este caso gradientRadius está configurando el tamaño independientemente del contenedor.


Puede crear una forma dibujable en tiempo de ejecución similar a esta publicación https://.com/a/4943888/604504

De esta forma, puedes calcular el porcentaje después de recuperar el tamaño de la pantalla.


Tenga en cuenta que los porcentajes gradientRadius funcionan en Lollipop. Pero si tiene que admitir pre-Lollipop, amplié la respuesta de @ marnaish agregando atributos XML. Mi gradienteRadius se define como un porcentaje del ancho de la vista principal:

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

En 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>

Desafortunadamente no puedes crear un XML dibujable desde una clase personalizada, por lo que no puedes establecerlo como un android de View: fondo. La solución consiste en utilizar FrameLayout para superponerlo como fondo.

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


Terminé creando una vista personalizada con el siguiente método onDraw anulado:

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

En su diseño simplemente agregue la Vista:

<yourpackage.GradientView android:layout_width="match_parent" android:layout_height="match_parent" />

Por supuesto, sería posible crear atributos para la Vista, ej. color, porcentaje para permitir la personalización a través de XML.