Радиус градиента в процентах от размера экрана
Я пытаюсь создать форму для рисования с радиальным градиентным фоном, с радиусом, который будет соответствовать размеру экрана (посмотрите соответствующую документацию).
Это мой код:
<?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>
Но это не похоже на работу. если я удаляю "%p", он работает, но тогда радиус будет статичным, поэтому не будет приспосабливаться к размеру экрана... Любая идея, что не так?
4 ответа
Из того, что я проверял, %
работает, но не так, как вы ожидали.
Прежде всего
android:gradientRadius="50"
кажется, принимает значение в пикселях 50 пикселей
android:gradientRadius="50%"
конвертируется так, как будто 50% = 0,5 px, попробуйте
android:gradientRadius="5000%"
и вы увидите радиус 50 пикселей.
С помощью %p
имеет аналогичный результат. Очевидно, что это то, что, я надеюсь, будет изменено в будущем, потому что оно не имеет особой пользы, как есть. Обычно ресурсы XML ShapeDrawable адаптируют свой размер к некоторому внешнему контейнеру, в этом случае gradientRadius
устанавливает размер независимо от контейнера.
В итоге я создал собственный вид со следующим переопределенным методом onDraw:
@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);
}
В вашем макете просто добавьте вид:
<yourpackage.GradientView
android:layout_width="match_parent"
android:layout_height="match_parent" />
Конечно, было бы возможно создать атрибуты для вида, например. цвет, процент, чтобы разрешить настройку через XML.
Обратите внимание, что процентные доли градиента работают в Lollipop. Но если вам нужна поддержка до Lollipop, я расширил ответ @marnaish, добавив атрибуты XML. Мой GradientRadius определяется в процентах от ширины родительского представления:
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);
}
}
В 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>
К сожалению, вы не можете создать XML-объект для рисования из пользовательского класса, поэтому вы не можете установить его в качестве фона для Android: View. Обходной путь должен использовать FrameLayout, чтобы наложить его как фон.
<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>
Вы можете создать форму для рисования во время выполнения, похожую на эту запись /questions/34820156/izmenenie-tsveta-gradienta-fona-na-android-vo-vremya-vyipolneniya/34820171#34820171
Таким образом, вы можете рассчитать процент после получения размера экрана.
Невозможно установить радиус угла фигуры, выраженный в процентах в отрисовываемом xml.