多梯度形状

我想创build一个如下图所示的形状:

替代文字

注意从颜色1到颜色2的上半部分渐变,但是从颜​​色3到颜色4渐变的下半部分渐变。我知道如何用单个渐变制作一个形状,但是我不确定如何将一个形状分割为两半,并使1形状与2个不同的梯度。

有任何想法吗?

我不认为你可以在XML(至less不是在Android)中做到这一点,但我发现在这里发布了一个很好的解决scheme,看起来会很有帮助!

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数组允许你select多个颜色停止点,下面的float数组定义了停止点的位置(从0到1)。 如你所说,你可以用这个作为标准的Drawable。

编辑:这是你可以在你的情况下使用这个。 假设你有一个用XML定义的button,像这样:

 <Button android:id="@+id/thebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Press Me!" /> 

然后你可以在你的onCreate()方法中join这样的东西:

 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); 

我目前无法testing这个,这是我头上的代码,但基本上只是replace,或者为需要的颜色添加中止。 基本上,在我的例子中,你将开始一个浅绿色,在中心之前略微淡化为白色(使渐变,而不是一个苛刻的过渡),在45%和55%之间从白色渐变为中等绿色,然后从从中间绿色到深绿色从55%到结束。 这可能看起来不像你的形状(现在,我没有办法testing这些颜色),但你可以修改这个复制你的例子。

编辑:此外, 0, 0, 0, theButton.getHeight()指向渐变的x0,y0,x1,y1坐标。 所以基本上,它从x = 0(左边),y = 0(顶部)开始,延伸到x = 0(我们想要一个垂直梯度,所以不需要从左到右的angular度),y =高度的button。 所以梯度从button的顶部到button的底部成90度angular。

编辑:好的,所以我有一个更好的主意,哈哈。 现在它在XML中起作用,但是对于Java中的形状也应该是可行的。 这有点复杂,我想有一种方法可以将它简化为一个单一的形状,但这是我现在所拥有的:

green_horizo​​ntal_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> 

好吧,基本上我已经创build了一个水平的绿色渐变的XML形状渐变,设置在0度angular,从顶部区域的左侧绿色,到右侧绿色。 接下来,我做了一个半透明灰色的形状矩形。 我敢肯定,可以内联到层列表XML,避免这个额外的文件,但我不知道如何。 但好吧,那么这个hacky部分就进入了layer_list XML文件。 我把绿色的梯度作为底层,然后把半覆盖作为第二层,从顶部偏移50dp。 显然你会希望这个数字总是你的视图大小的一半,而不是一个固定的50dp。 不过,我不认为你可以使用百分比。 从那里,我刚刚插入一个TextView到我的test.xml布局,使用layer_list.xml文件作为我的背景。 我将高度设置为100dp(覆盖层偏移量的两倍),结果如下:

替代文字

田田!

多一个编辑 :我意识到你可以将graphicsembedded到可绘制的图层列表中,这意味着您不再需要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获得更多function的结果。

我认为这是最后一次编辑… :好的,所以你可以通过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做的工作。

我撒谎了,还有一个编辑

好的,找出如何手动更新这个图层绘制来匹配容器的高度,完整的描述可以在这里find。 这段代码应该放在你的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中对渐变形状进行图层处理。 设想一下button的默认状态如下,其中第二项是半透明的。 它增加了一种渐晕。 (请原谅自定义的颜色。)

 <!-- 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> <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>