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.