Я не думаю, что вы можете сделать это в XML (по крайней мере, в Android), но я нашел хорошее решение, опубликованное здесь, которое выглядит так, как будто это очень поможет!
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0, 0, width, height,
new int[]{Color.GREEN, Color.GREEN, Color.WHITE, Color.WHITE},
new float[]{0,0.5f,.55f,1}, Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable p=new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
По сути, массив int позволяет вам выбрать несколько цветовых остановок, а следующий массив с плавающей точкой определяет, где эти остановки расположены (от 0 до 1). Затем, как уже говорилось, вы можете просто использовать это как стандартный Drawable.
Изменить: Вот как вы могли бы использовать это в вашем сценарии. Допустим, у вас есть кнопка, определенная в XML следующим образом:
<Button
android:id="@+id/thebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
/>
Затем вы бы поместили что-то вроде этого в свой метод onCreate ():
Button theButton = (Button)findViewById(R.id.thebutton);
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0, 0, 0, theButton.getHeight(),
new int[] {
Color.LIGHT_GREEN,
Color.WHITE,
Color.MID_GREEN,
Color.DARK_GREEN }, //substitute the correct colors for these
new float[] {
0, 0.45f, 0.55f, 1 },
Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable p = new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
theButton.setBackground((Drawable)p);
Я не могу проверить это в данный момент, это код из моей головы, но в основном просто заменить или добавить остановки для цветов, которые вам нужны. В основном, в моем примере, вы начинаете со светло-зеленого, постепенно переходите в белый цвет перед центром (чтобы дать переход, а не резкий переход), переходите от белого к среднему зеленому между 45% и 55%, затем переходите от от среднего до темно-зеленого от 55% до конца. Возможно, это не совсем похоже на вашу форму (сейчас у меня нет возможности проверить эти цвета), но вы можете изменить это, чтобы повторить ваш пример.
Редактировать: Кроме того, 0, 0, 0, theButton.getHeight()
ссылка относится к координатам градиента x0, y0, x1, y1. Таким образом, в основном, он начинается с x = 0 (левая сторона), y = 0 (верх) и простирается до x = 0 (мы хотим вертикальный градиент, поэтому не требуется угол слева направо), y = высота кнопки. Таким образом, градиент идет под углом 90 градусов от верхней части кнопки до нижней части кнопки.
Редактировать: Хорошо, у меня есть еще одна идея, которая работает, ха-ха. Прямо сейчас это работает в XML, но должно быть выполнимо и для фигур в Java. Это довольно сложно, и я думаю, что есть способ упростить его до единой формы, но вот что я получил сейчас:
green_horizontal_gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners
android:radius="3dp"
/>
<gradient
android:angle="0"
android:startColor="#FF63a34a"
android:endColor="#FF477b36"
android:type="linear"
/>
</shape>
half_overlay.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid
android:color="#40000000"
/>
</shape>
layer_list.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item
android:drawable="@drawable/green_horizontal_gradient"
android:id="@+id/green_gradient"
/>
<item
android:drawable="@drawable/half_overlay"
android:id="@+id/half_overlay"
android:top="50dp"
/>
</layer-list>
test.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<TextView
android:id="@+id/image_test"
android:background="@drawable/layer_list"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:gravity="center"
android:text="Layer List Drawable!"
android:textColor="@android:color/white"
android:textStyle="bold"
android:textSize="26sp"
/>
</RelativeLayout>
Итак, в основном я создал градиент формы в XML для горизонтального зеленого градиента, установленный под углом 0 градусов, переходящий от левого зеленого цвета верхней области к правому зеленому цвету. Затем я сделал прямоугольник с полупрозрачным серым цветом. Я почти уверен, что это может быть встроено в XML списка слоев, исключая этот дополнительный файл, но я не уверен, как это сделать. Но хорошо, тогда какая-то хакерская часть появляется в XML-файле layer_list. Я поставил зеленый градиент в качестве нижнего слоя, а затем наложил половину наложения в качестве второго слоя со смещением от вершины на 50dp. Очевидно, вы бы хотели, чтобы это число всегда составляло половину от размера вашего представления, а не фиксированного 50dp. Я не думаю, что вы можете использовать проценты, хотя. Оттуда я просто вставил TextView в свой макет test.xml, используя файл layer_list.xml в качестве фона.
Тада!
Еще одно редактирование : я понял, что вы можете просто вставить фигуры в список слоев, которые можно нарисовать как элементы, а это значит, что вам больше не нужно 3 отдельных файла XML! Вы можете достичь того же результата, комбинируя их примерно так:
layer_list.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners
android:radius="3dp"
/>
<gradient
android:angle="0"
android:startColor="#FF63a34a"
android:endColor="#FF477b36"
android:type="linear"
/>
</shape>
</item>
<item
android:top="50dp"
>
<shape
android:shape="rectangle"
>
<solid
android:color="#40000000"
/>
</shape>
</item>
</layer-list>
Вы можете наложить столько элементов, сколько хотите, таким образом! Я могу попытаться поиграть и посмотреть, смогу ли я получить более универсальный результат с помощью Java.
Я думаю, что это последнее редактирование ... : Хорошо, так что вы можете определенно исправить позиционирование через Java, как показано ниже:
TextView tv = (TextView)findViewById(R.id.image_test);
LayerDrawable ld = (LayerDrawable)tv.getBackground();
int topInset = tv.getHeight() / 2 ; //does not work!
ld.setLayerInset(1, 0, topInset, 0, 0);
tv.setBackgroundDrawable(ld);
Тем не мение! Это приводит к еще одной досадной проблеме, заключающейся в том, что вы не можете измерить TextView, пока он не будет нарисован. Я не совсем уверен, как вы можете сделать это ... но ручная вставка числа для topInset работает.
Я соврал, еще один править
Хорошо, узнал, как вручную обновить этот слой для рисования, чтобы он соответствовал высоте контейнера, полное описание можно найти здесь . Этот код должен идти в вашем методе onCreate ():
final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
LayerDrawable ld = (LayerDrawable)tv.getBackground();
ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
}
});
И я сделал! Уф! :)