Мульти-формы градиента
Я хотел бы создать фигуру, которая похожа на следующее изображение:

обратите внимание на верхнюю половину градиентов от цвета 1 до цвета 2, но есть нижняя половина, которая градиенты от цвета 3 до цвета 4. Я знаю, как сделать фигуру с одним градиентом, но я не уверен, как разделить фигуру на две половины и сделать 1 фигуру с 2 различными градиентами.
какие идеи?
5 ответов:
Я не думаю, что вы можете сделать это в 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 позволяет выбрать несколько цветовых остановок, а следующий массив float определяет, где расположены эти остановки (от 0 до 1). Затем вы можете, как указано, просто использовать это в качестве стандартного чертежа.
Edit: вот как вы можете использовать это в своем сценарии. Давайте скажем, у вас есть кнопка, определенная в 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% до конца. Это может выглядеть не совсем так, как ваша форма (прямо сейчас, у меня нет способа проверить эти цвета), но вы можете изменить это, чтобы повторить свой пример.
Edit: кроме того,
0, 0, 0, theButton.getHeight()относится к координатам x0, y0, x1, y1 градиента. Таким образом, в основном, он начинается с x = 0 (левая сторона), y = 0 (сверху) и растягивается до x = 0 (нам нужен вертикальный градиент, поэтому не требуется левый правый угол), y = высота кнопка. Таким образом, градиент идет под углом 90 градусов от верхней части кнопки к нижней части кнопки.Edit: хорошо, так что у меня есть еще одна идея, которая работает, ха-ха. Прямо сейчас он работает в 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>! Это приводит к еще одной раздражающей проблеме в том, что вы невозможно измерить TextView до тех пор, пока он не будет нарисован. Я еще не совсем уверен, как вы можете это сделать...но ручная вставка числа для topInset действительно работает.
я соврал, еще одно редактирование
хорошо, узнал, как вручную обновить этот слой drawable, чтобы соответствовать высоте контейнера, полное описание можно найти здесь. Этот код должен входить в ваш метод 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); } });и я сделал! Фу! :)
вы можете накладывать градиентные фигуры в xml с помощью списка слоев. Представьте себе кнопку с состоянием по умолчанию, как показано ниже, где второй элемент является полупрозрачным. Это добавляет своего рода виньетирование. (Пожалуйста, извините пользовательские цвета.)
<!-- Normal state. --> <item> <layer-list> <item> <shape> <gradient android:startColor="@color/grey_light" android:endColor="@color/grey_dark" android:type="linear" android:angle="270" android:centerColor="@color/grey_mediumtodark" /> <stroke android:width="1dp" android:color="@color/grey_dark" /> <corners android:radius="5dp" /> </shape> </item> <item> <shape> <gradient android:startColor="#00666666" android:endColor="#77666666" android:type="radial" android:gradientRadius="200" android:centerColor="#00666666" android:centerX="0.5" android:centerY="0" /> <stroke android:width="1dp" android:color="@color/grey_dark" /> <corners android:radius="5dp" /> </shape> </item> </layer-list> </item>
вы можете сделать это, используя только xml-формы-просто используйте layer-list и отрицательное заполнение следующим образом:
<layer-list> <item> <shape> <solid android:color="#ffffff" /> <padding android:top="20dp" /> </shape> </item> <item> <shape> <gradient android:endColor="#ffffff" android:startColor="#efefef" android:type="linear" android:angle="90" /> <padding android:top="-20dp" /> </shape> </item> </layer-list>
вы пытались наложить один градиент с почти прозрачной непрозрачностью для выделения поверх другого изображения с непрозрачной непрозрачностью для зеленого градиента?
попробуйте этот метод, то вы можете сделать все, что вы хотите.
Это как стек так что будьте осторожны, какой элемент идет первым или последним.<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:right="50dp" android:start="10dp" android:left="10dp"> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="3dp" /> <solid android:color="#012d08"/> </shape> </item> <item android:top="50dp"> <shape android:shape="rectangle"> <solid android:color="#7c4b4b" /> </shape> </item> <item android:top="90dp" android:end="60dp"> <shape android:shape="rectangle"> <solid android:color="#e2cc2626" /> </shape> </item> <item android:start="50dp" android:bottom="20dp" android:top="120dp"> <shape android:shape="rectangle"> <solid android:color="#360e0e" /> </shape> </item>
Comments