Drawable个人理解是用在所有空间上的视觉内容,背景色,图片等等,当然包含背景动画。他子类一大把,应该能证明这些了。
通常呢用不到对象,会用android:color 这种就可以了。不过在使用自定义控件的时候,android:color就不完全好使了,特别是跟业务相结合或者你心中牛逼轰轰的状态相关的时候。
简版的步骤,实现一个android:color的效果:
a. 创建个类,继承drawable
b. 类中创建个paint,在drawable的draw中绘制颜色
c. 找到对应的控件,设置到背景setBackground或者setBackgroundDrawable即可。
ps: 这边没有提到Drawable.Callback,这个是官方说道的要做的,之所以没做,是因为View已经实现了,则使用它的子类的时候就免了。源码党自行研究便知。
package com.mc.drawabletest.wiget;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
/**
* 最简单的背景色
* Created by M.C/酸奶 on 2015/12/6.
*/
public class SuqStateDrawable extends Drawable {
private Paint mPaint;
/**
* 构造定个颜色
* @param color
*/
public SuqStateDrawable(int color) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(color);
mPaint.setStrokeWidth(5);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
}
public void setColor(int color) {
mPaint.setColor(color);
invalidateSelf(); //重新上色记得重绘
}
/**
* 绘制的时候把颜色画上去
* @param canvas
*/
@Override
public void draw(Canvas canvas) {
canvas.drawPaint(mPaint);
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return 0;
}
}
麻烦点的,背景色能够跟着状态改变的。其中原理就是:
a. 针对不同的状态对应设置对个颜色,这个和selector 文件一样的意思
b. 把颜色和状态用colorstatelist关联起来
c. 在状态改变时获取状态对应的颜色,然后绘制
d. 把drawable设置给button
package com.mc.drawabletest.wiget;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.util.Log;
/**
* Created by M.C/酸奶 on 2015/12/20
*/
public class ButtonColorDrawable extends Drawable {
/**
* 按钮背景的画笔
*/
private Paint mBGPaint;
/**
* 普通的状态颜色值
*/
private int[] mNoAnimationColor;
private ColorStateList mColorStateList;
private int[][] btStatus;
public ButtonColorDrawable() {
//创建基本的颜色,这个是按钮的颜色
mNoAnimationColor = new int[]{Color.BLUE, Color.GREEN, Color.GRAY};
mBGPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBGPaint.setColor(Color.BLUE);
mBGPaint.setStrokeWidth(5);
mBGPaint.setStyle(Paint.Style.FILL);
mBGPaint.setAntiAlias(true);
//负号表示false,最后那个空数组呢,代表的是除开前面这两个状态以外的状态,这个一定要放到最后,不信你放到第一个试试有什么后果
btStatus = new int[][]{{-android.R.attr.state_pressed}, {android.R.attr.state_pressed}, {}};
//把前面创建好的状态对应的颜色素组塞到这个状态和颜色对应的队列里面
mColorStateList = new ColorStateList(btStatus, mNoAnimationColor);
}
/**
* Draw in its bounds (set via setBounds) respecting optional effects such
* as alpha (set via setAlpha) and color filter (set via setColorFilter).
* 绘图方法
*
* @param canvas The canvas to draw into
*/
@Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(new RectF(getBounds()), 30, 30, mBGPaint);
}
/**
* 设置为true之后,drawable才能接受控件的状态
*
* @return
*/
@Override
public boolean isStateful() {
return true;
}
@Override
protected boolean onStateChange(int[] state) {
//当状态改变的时候,获取当前状态对应的颜色,这个颜色和状态的关系就是构造里面设置的那个
int currentColor = mColorStateList.getColorForState(state, Color.WHITE);
mBGPaint.setColor(currentColor);
invalidateSelf();
return true;
}
/**
* Specify an alpha value for the drawable. 0 means fully transparent, and
* 255 means fully opaque.
*
* @param alpha
*/
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
final ButtonColorDrawable btd = new ButtonColorDrawable();
Button iv = (Button) findViewById(R.id.iv);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
iv.setBackground(btd);
} else {
iv.setBackgroundDrawable(btd);
}
当然还有更高级的,是动画的,那个需要结合值动画,对象动画,多个drawable一起。暂时不多说了,我在源码中有用到,笔者比较懒,效果很丑,不过该有的效果都有了。
http://code.taobao.org/svn/MCAndroid/