Овальный градиент в Android

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

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval" >
    <gradient
        android:startColor="#66FFFFFF"
        android:endColor="#00FFFFFF"
        android:gradientRadius="100"
        android:type="radial" />
</shape>

Если вы можете себе представить, этот градиент имеет полупрозрачное белое свечение в середине, а затем исчезает до альфа-нуля по краям. Мне нужно заставить его выйти в овальной форме, а не только круговой градиент. Как я могу достичь этого?

Ответ 1

Это сложно, поскольку чертежи, определенные таким образом, вовлекаются во время выполнения, адаптируясь к пространству, в которое вы их вставляете. Лучшим решением, если вы должны сделать это в коде, было бы взять форму, которую вы определили в XML и нарисуйте его на холсте или в виде растрового изображения как идеальный круг. На этом этапе шаблон градиента будет следовать контуру формы. После того, как форма была втянута в статический контекст, вы можете добавить фигуру в представление (например, в качестве фона), которая будет искажать ее в овале, когда она попытается установить границы представления. Поскольку у вас есть изображение, все это будет искажать пропорционально.

Мы надеемся, что этот метод не будет слишком плохим.

Ответ 2

Я бы предложил более "прямой" подход к рисованию. Если вы можете рисовать градиент по пикселям, вам нужно просто запомнить, что для

  • круг цвет градиента пропорционален r
  • эллипс (овал) цвет градиента пропорционален r1+r2

Здесь:

r - расстояние до центра круга

r1, r2 - расстояния до двух фокусов эллипса

EDIT: Рассмотрим этот код пиксельного шейдера:

uniform sampler2D tex;

void main()
{
    vec2 center = vec2(0.5,0.5);
    float len = 1.3*(distance(gl_TexCoord[0].xy,center));
    vec2 foc1 = vec2(len,0.);
    vec2 foc2 = vec2(-len,0.);
    float r = distance(center+foc1,gl_TexCoord[0].xy) +
             distance(center+foc2,gl_TexCoord[0].xy);
    float k = pow(r*0.9,1.3);
    vec4 color = vec4(k,k,k,1.);
    gl_FragColor = color;
}

Вы получите овальное что-то вроде этого: alt text

удача

Ответ 3

<?xml version="1.0" encoding="utf-8"?>

<stroke android:width="1dp" android:color="#ffffffff" />

<size
    android:width="40dp"
    android:height="40dp"/>

<gradient
    android:type="radial"
    android:startColor="#ffff0000"
    android:endColor="#330000ff"
    android:gradientRadius="40dp"
    android:angle="270"
    android:centerX=".5"
    android:centerY=".5"/>

Ответ 4

"Тупой, но рабочий" способ сделать это - это нарисовать контур эллипса, а затем множество вложенных эллипсов с одним и тем же "центром", размеры и цвета которых меняются по мере того, как эллипсы становятся меньше, вплоть до одноэлементный эллипс. Если вы настраиваете свой градиент, интерполируйте цвета в HSV, а не в RVB!