近日听说了tint属性,于是小小的研究了一下。
发现tint属性在实际项目中非常实用。
在开发项目的时候,绝大部分的策划可能都有个这样的需求,当点击一个按钮素材的时候,素材变色。
这个功能并不难,可以说非常简单。设置xml的drawable,pressed的属性就可以。
然而我们却忽略了一点,这样做的时候,往往我们会叫设计师妹妹(还是大叔?)设计两张素材,一张正常的,一张按下去的。
一个地方这样弄还好,如果是一个庞大的项目所有类似这样的地方都这样弄,你会发现很多很多的素材长的是一模一样,只是颜色不一样而已。这样就会导致我们的apk包的大小无形的增大不少。
那怎么办呢?
tint应运而生。
先说一下tint是在android5.0系统才开始出现的。
使用起来非常简单。
举个简单的例子:
就上面的代码,只要加一个tint颜色属性值。
这个tint素材显示出来的颜色就是我们指定的colorAccent。
是不是感觉不可思议,不在担心同样的素材,多变的颜色。
看到这里,有疑问了,那可不可以快捷的设置按下去的颜色?
当然了。
就不多解释了,直接贴代码,看到代码比我balabala理解估计更快。
其中drawable/tint_src_selector和@color/tint_color_selector不再是直接的素材而是xml
tint_src_selector代码:
注意上面代码,依然只用了一个素材。
tine_color_selector代码:
这里涉及到两个颜色,一个正常的,一个按下去的。
就这样,就可以到真机或者模拟器看效果了。
搞到这里,就感觉完美了。
然而,我发现,当我运行在5.0系统以下的时候,就报错了。
晕死,我们apk版本最低兼容要低于5.0啊。这可咋整?
所以想到了,到代码里面去设置tint(为什么?这还问,因为代码里可以判断系统版本咯)
于是我又各种搜。却发现怎么也实现不了,按下去变色的需求。
于是想着模仿xml的实现去解决这个问题。终于,这样就真的可以了。
直接贴代码吧:
为了方便看,直接把方法设置为了static方法:
public static void initImageView(@NonNull Context context, @NonNull ImageView imageIV
, @DrawableRes int imageRes, @ColorRes int colorNormal, @ColorRes int colorPressed) {
Drawable drawable = ContextCompat.getDrawable(context,imageRes);
int[][] states = new int[2][];
states[0] = new int[]{android.R.attr.state_pressed};
states[1] = new int[]{};
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(states[0],drawable);
stateListDrawable.addState(states[1],drawable);
Drawable.ConstantState state = stateListDrawable.getConstantState();
Drawable wrapDrawable = DrawableCompat.wrap(state == null ?
stateListDrawable : state.newDrawable()).mutate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int[] color = new int[]{
ContextCompat.getColor(context,colorPressed),
ContextCompat.getColor(context,colorNormal)
};
ColorStateList colorStateList = new ColorStateList(states,color);
wrapDrawable.setTintList(colorStateList);
}
imageIV.setImageDrawable(wrapDrawable);
//如果还是没效果,加一句clickable
// imageIV.setClickable(true);
}
这样就可以在代码上实现tint属性所带来的功能了。
不过这样的话5.0以下,点击就没有变色的功能了。如果也想有,怎么办?换手机呗(调侃=_=)
最后总结一下,将上面的实现抽成一个自定义控件
核心代码如下:
public class TintImageView extends ImageView {
private int mColorNormal, mColorPressed;
private int mImageRes;
public TintImageView(Context context) {
this(context, null);
}
public TintImageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TintImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintImageView, defStyleAttr, 0);
mColorNormal = a.getColor(R.styleable.TintImageView_colorNormal, 0);
mColorPressed = a.getColor(R.styleable.TintImageView_colorPressed, 0);
mImageRes = a.getResourceId(R.styleable.TintImageView_imageRes, 0);
initImageView();
a.recycle();
}
private void initImageView() {
if(mImageRes == 0){
return;
}
if(mColorNormal != 0){
Drawable drawable = ContextCompat.getDrawable(getContext(),mImageRes);
if(mColorPressed != 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
int[][] states = new int[2][];
states[0] = new int[]{android.R.attr.state_pressed};
states[1] = new int[]{};
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(states[0],drawable);
stateListDrawable.addState(states[1],drawable);
Drawable.ConstantState state = stateListDrawable.getConstantState();
Drawable wrapDrawable = DrawableCompat.wrap(state == null ?
stateListDrawable : state.newDrawable()).mutate();
int[] color = new int[]{mColorPressed,mColorNormal};
ColorStateList colorStateList = new ColorStateList(states,color);
wrapDrawable.setTintList(colorStateList);
setImageDrawable(wrapDrawable);
//如果没效果,加一句clickable
// setClickable(true);
}else{
drawable = DrawableCompat.wrap(drawable.mutate());
DrawableCompat.setTint(drawable, mColorNormal);
setImageDrawable(drawable);
}
}
}
}
其中attrs.xml文件增加代码:
以上皆为原创,请勿擅自转载,或者贴一下博客地址博客原文地址
http://blog.csdn.net/yc1101/article/details/79305740