我想创建一个类似于下图的形状:
注意上半部分从颜色 1 渐变到颜色 2,但下半部分从颜色 3 渐变到颜色 4。我知道如何使用单个渐变制作形状,但我不确定如何将形状拆分为两半,用 2 个不同的渐变制作 1 个形状。
有任何想法吗?
我认为您不能在 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,如下所示:
<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 度角。
0, 0, 0, theButton.getHeight()
编辑:好的,所以我还有一个可行的想法,哈哈。现在它适用于 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>
测试.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 中,从而避免这个额外的文件,但我不确定如何。但是好的,那么 layer_list XML 文件中就出现了这种骇人听闻的部分。我将绿色渐变作为底层,然后将半覆盖层作为第二层,从顶部偏移 50dp。显然,您希望这个数字始终是您的视图大小的一半,而不是固定的 50dp。不过,我认为您不能使用百分比。从那里,我刚刚将 TextView 插入到我的 test.xml 布局中,使用 layer_list.xml 文件作为我的背景。
多田!
另一个编辑 :我意识到您可以将形状作为项目嵌入到可绘制的图层列表中,这意味着您不再需要 3 个单独的 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); } });
我完成了!哇!:)