Подтвердить что ты не робот

Радиус градиента в процентах от размера экрана

Я пытаюсь создать фигуру с радиальным градиентом, с радиусом, который будет подстраиваться под размер экрана (см. соответствующую документацию).

Это мой код:

<?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", он работает, но тогда радиус будет статичным, поэтому не будет регулироваться размер экрана... Любая идея, что не так?

4b9b3361

Ответ 1

Из того, что я тестировал, % работает, но не так, как вы ожидали.
Прежде всего

android:gradientRadius="50"

кажется, принимает значение в виде пикселей 50px

android:gradientRadius="50%"

преобразуется, как если бы 50% = 0,5 px, попробуйте

android:gradientRadius="5000%"

и вы увидите радиус 50 пикселей.
Использование %p имеет аналогичный результат. Очевидно, это то, что, надеюсь, будет изменено в будущем, потому что оно не имеет большого смысла, как есть. Обычно ресурсы XML ShapeDrawable адаптируют свой размер к некоторому внешнему контейнеру, в этом случае gradientRadius устанавливает размер независимо от контейнера.

Ответ 2

В результате я создал пользовательский вид со следующим методом overden 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);
}

В вашем макете просто добавьте View:

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

Конечно, можно было бы создать атрибуты для представления, например. цвет, процент, позволяющий настраивать через XML.

Ответ 3

Обратите внимание, что проценты gradientRadius работают в Lollipop. Но если вам нужно поддерживать pre-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. Обходной путь заключается в использовании 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 up world?"/>
</FrameLayout>

Ответ 4

Вы можете создать фигуру, которая будет доступна во время выполнения, аналогичную этому сообщению fooobar.com/info/155283/...

Таким образом, вы можете рассчитать процент после получения размера экрана.