问题描述
我想创建一个形状像下图:
I'd like to create a shape that's like the following image:
请注意,上半部分渐变颜色从1到2的颜色,但那里有一个底部的一半,从渐变色3色4。我知道如何使一个渐变的形状,但我不知道如何分割形状分为两半,使1形状有2种不同的梯度。
Notice the top half gradients from color 1 to color 2, but theres a bottom half that gradients from color 3 to color 4. I know how to make a shape with a single gradient, but I'm not sure how to split a shape into two halves and make 1 shape with 2 different gradients.
任何想法?
推荐答案
我不认为你可以在XML做到这一点(至少在Android的),但我已经找到了一个很好的解决方案发布here看起来像它会是一个很大的帮助!
I don't think you can do this in XML (at least not in Android), but I've found a good solution posted here that looks like it'd be a great help!
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)。然后,可以作为说明,只是用这个作为标准绘制对象。
Basically, the int array allows you to select multiple color stops, and the following float array defines where those stops are positioned (from 0 to 1). You can then, as stated, just use this as a standard Drawable.
编辑:下面是你可以在你的情况下使用此。比方说,你在XML中定义,像这样一个按钮:
Here's how you could use this in your scenario. Let's say you have a Button defined in XML like so:
<Button
android:id="@+id/thebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
/>
您会然后把这样的事情在你的onCreate()方法:
You'd then put something like this in your onCreate() method:
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.setBackgroundDrawable((Drawable)p);
我不能在此刻进行测试,这是code从我的头,但基本上只需更换,或者您需要的颜色添加停止。基本上,在我的例子,你将开始与浅绿色,渐变为白色稍前中心(给淡入淡出,而不是一个严厉的转变),从白色渐变为45%至55%中间的绿色,然后从褪色中间绿色到深绿色,从55%到最后。这可能不完全一样的形状(我在工作,我也没有办法检测这些颜色的),但你可以修改这个来复制你的榜样。
I cannot test this at the moment, this is code from my head, but basically just replace, or add stops for the colors that you need. Basically, in my example, you would start with a light green, fade to white slightly before the center (to give a fade, rather than a harsh transition), fade from white to mid green between 45% and 55%, then fade from mid green to dark green from 55% to the end. This may not look exactly like your shape (I'm at work, I have no way of testing these colors), but you can modify this to replicate your example.
编辑:此外, 0,0,0,theButton.getHeight()
指的是渐变的X0,Y0,X1,Y1坐标。因此,基本上,它开始在x = 0(左侧)中,y = 0(上),并延伸至x = 0(我们想要的垂直梯度,所以没有左到右角是必要的),Y =高度按钮。所以梯度变为在从底部的顶部按钮的底部成90度角。
Also, the 0, 0, 0, theButton.getHeight()
refers to the x0, y0, x1, y1 coordinates of the gradient. So basically, it starts at x = 0 (left side), y = 0 (top), and stretches to x = 0 (we're wanting a vertical gradient, so no left to right angle is necessary), y = the height of the button. So the gradient goes at a 90 degree angle from the top of the bottom to the bottom of the button.
编辑:好了,我还有一个想法,工作,哈哈。现在,它在XML,而应是可行的形状在Java中也是如此。这是一种复杂的,和我想象有一种方法可以简化成一个单一的形状,但是这是我有现在:
Okay, so I have one more idea that works, haha. Right now it works in XML, but should be doable for shapes in Java as well. It's kind of complex, and I imagine there's a way to simplify it into a single shape, but this is what I've got for now:
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度角,从顶部区域的左绿色去,向右绿色。接下来,我做了一个半透明的灰色形状矩形。我是pretty的肯定会内联到图层列表的XML,避免这些额外的文件,但我不知道怎么样。不过还好,那么那种哈克部分来自于对layer_list XML文件。我把绿色渐变为底层,然后将半盖作为第二层,由50dp从顶偏。很显然,你会想这个数字永远是一半无论你的观点大小,但是,并没有一个固定的50dp。我不认为你可以使用百分比,但。从那里,我只是插入一个TextView到我的test.xml布局,使用layer_list.xml文件作为我的背景。我将高度设置为100dp(的叠加偏移两倍),导致以下内容:
Okay, so basically I've created a shape gradient in XML for the horizontal green gradient, set at a 0 degree angle, going from the top area's left green color, to the right green color. Next, I made a shape rectangle with a half transparent gray. I'm pretty sure that could be inlined into the layer-list XML, obviating this extra file, but I'm not sure how. But okay, then the kind of hacky part comes in on the layer_list XML file. I put the green gradient as the bottom layer, then put the half overlay as the second layer, offset from the top by 50dp. Obviously you'd want this number to always be half of whatever your view size is, though, and not a fixed 50dp. I don't think you can use percentages, though. From there, I just inserted a TextView into my test.xml layout, using the layer_list.xml file as my background. I set the height to 100dp (twice the size of the offset of the overlay), resulting in the following:
田田!
还有一个修改:我明白你可以嵌入到形状图层列表绘制的项目,这意味着你不需要3个独立的XML文件了!你可以达到同样的效果结合他们像这样:
One more edit: I've realized you can just embed the shapes into the layer list drawable as items, meaning you don't need 3 separate XML files any more! You can achieve the same result combining them like so:
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的获得更灵活的结果。
You can layer as many items as you like this way! I may try to play around and see if I can get a more versatile result through Java.
我觉得这是最后的编辑...... :好了,你绝对可以通过Java修正定位,如下所示:
I think this is the last edit...: Okay, so you can definitely fix the positioning through Java, like the following:
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做的工作。
However! This leads to yet another annoying problem in that you cannot measure the TextView until after it has been drawn. I'm not quite sure yet how you can accomplish this...but manually inserting a number for topInset does work.
我撒谎了,多了一个修改
好吧,发现了如何手动更新此层绘制相匹配的容器的高度,充分说明可以发现here.这code应该在去的onCreate()方法:
Okay, found out how to manually update this layer drawable to match the height of the container, full description can be found here. This code should go in your onCreate() method:
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);
}
});
和我做!呼! :)
这篇关于多梯度形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!