我想大家在开发的时候,经常会看到UED会设计渐变颜色的产品需求,当然如果图片不需要动态更换,直接使用UED设计的渐变色的图片就可以了,但是很多时候,像我们最近项目里面,就有根据不同的皮肤,渐变色是不一样的,我们总不能有几十种皮肤就让UED设计几十张渐变色的图片放到项目里,一方面这样不灵活,另外会增加APP的安装包的大小。那么怎么办呢?这就需要我们自己来绘制。我总结了一下,在android中做渐变图标的几种方法,供大家参考。
第一种:使用LinearGradient
第二种:使用GradientDrawable
第三种:使用xml,selector来配置。
先看看效果图(为了能看到透明效果,背景用了ab的照片):
可以看到,每种方法,其实都可以实现相同的效果,正所谓,条条大路通罗马。好,下面开始讲解,每种方法的实现过程:
方法一:通过LinearGradient绘制渐变图片
看看官方文档(LinearGradient介绍),大家要习惯去看官方文档,官方才是权威的。
我们看到人家有两个构造函数:
public LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)
Create a shader that draws a linear gradient along a line.
Parameters
x0 | The x-coordinate for the start of the gradient line |
---|---|
y0 | The y-coordinate for the start of the gradient line |
x1 | The x-coordinate for the end of the gradient line |
y1 | The y-coordinate for the end of the gradient line |
colors | The colors to be distributed along the gradient line |
positions | May be null. The relative positions [0..1] of each corresponding color in the colors array. If this is null, the the colors are distributed evenly along the gradient line. |
tile | The Shader tiling mode |
public LinearGradient (float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
Create a shader that draws a linear gradient along a line.
Parameters
x0 | The x-coordinate for the start of the gradient line |
---|---|
y0 | The y-coordinate for the start of the gradient line |
x1 | The x-coordinate for the end of the gradient line |
y1 | The y-coordinate for the end of the gradient line |
color0 | The color at the start of the gradient line. |
color1 | The color at the end of the gradient line. |
tile | The Shader tiling mode |
public static Drawable makePowerGradientDrawable(int baseColor, int numStops, int gravity, float power, final Shader.TileMode mode) {
numStops = Math.max(numStops, 2);
PaintDrawable paintDrawable = new PaintDrawable();
paintDrawable.setShape(new RectShape());
paintDrawable.setIntrinsicWidth(200);
paintDrawable.setIntrinsicHeight(200);
final int[] stopColors = new int[numStops];
int red = Color.red(baseColor);
int green = Color.green(baseColor);
int blue = Color.blue(baseColor);
int alpha = Color.alpha(baseColor);
for (int i = 0; i < numStops; i++) {
float x = i * 1f / (numStops - 1);
float opacity =Math.min(1, (float) Math.pow(x, power));
stopColors[i] = Color.argb((int) (alpha * opacity), red, green, blue);
}
final float x0, x1, y0, y1;
switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
x0 = 1;
x1 = 0;
break;
case Gravity.RIGHT:
x0 = 0;
x1 = 1;
break;
default:
x0 = 0;
x1 = 0;
break;
}
switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
case Gravity.TOP:
y0 = 1;
y1 = 0;
break;
case Gravity.BOTTOM:
y0 = 0;
y1 = 1;
break;
default:
y0 = 0;
y1 = 0;
break;
}
paintDrawable.setShaderFactory(new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient linearGradient = new LinearGradient(width * x0, height * y0, width * x1, height * y1, stopColors, null, mode);
return linearGradient;
}
});
return paintDrawable;
}
方法调用:
//方法一:使用LinearGradient
//CLAMP
mImageTest1=(ImageView)findViewById(R.id.img_test1);
Drawable drawable1=makePowerGradientDrawable(Color.parseColor("#80FF0000"),10,Gravity.TOP,0.5f,Shader.TileMode.CLAMP);
mImageTest1.setImageDrawable(drawable1);
//MIRROR
mImageTest2=(ImageView)findViewById(R.id.img_test2);
Drawable drawable2=makePowerGradientDrawable(Color.parseColor("#80FF0000"),10,Gravity.TOP,0.5f,Shader.TileMode.MIRROR);
mImageTest2.setImageDrawable(drawable2);
//REPEAT
mImageTest3=(ImageView)findViewById(R.id.img_test3);
Drawable drawable3=makePowerGradientDrawable(Color.parseColor("#80FF0000"),10,Gravity.TOP,0.5f,Shader.TileMode.REPEAT);
mImageTest3.setImageDrawable(drawable3);
第二种:使用GradientDrawable
先看GradientDrawable官方文档,我们看到,那个构造函数,写得很清晰了。
GradientDrawable( GradientDrawable.Orientation orientation, int[] colors)
方法调用:
//方法二:使用GradientDrawable
//GradientDrawable 第一个参数表示渐变方向,总共8个方向,第二个是渐变点数组
GradientDrawable gd = new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM, new int[] { 0x80FF0000,
0x30FF0000, 0x00FF0000 });
// gd.setGradientType(GradientDrawable.LINEAR_GRADIENT);
// gd.setGradientType(GradientDrawable.RADIAL_GRADIENT);
// gd.setGradientType(GradientDrawable.SWEEP_GRADIENT);
gd.setSize(200, 200);
mImageTest4=(ImageView)findViewById(R.id.img_test4);
mImageTest4.setImageDrawable(gd);
第三种:使用XML,Selector配置
在drawable文件夹下放置:selector_gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--点击状态-->
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#80FF0000" />
<corners android:radius="2dp" />
</shape>
</item>
<!--没写状态表示常态写-->
<item>
<shape android:shape="rectangle">
<!--大小-->
<size android:width="100dp" android:height="100dp"></size>
<!-- 顏色填充 -->
<!--solid android:color="#587df9" /-->
<!-- 圆角 还可以单独设置四个圆角的圆半径,比如topLeftRadius左上圆角半径-->
<corners android:radius="2dp" />
<!-- 渐变 -->
<gradient android:angle="270" android:startColor="#80FF0000" android:endColor="#00FF0000" />
<!-- 描边 -->
<!--stroke android:width="2dp" android:color="#dcdcdc" /-->
<!--上下左右padding-->
<!--padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" /-->
</shape>
</item>
</selector>
具体见drawable resources官方文档
调用方法:
//方法三:使用selector xml
mImageTest5=(ImageView)findViewById(R.id.img_test5);
mImageTest5.setImageDrawable(getResources().getDrawable(R.drawable.selector_gradient));