1:需求
如果要实现勾选框居右的AppCompatCheckBox怎么办。
image.png
肯定有人会说直接用TextView加一个选择器给DrawableRight不就可以了吗?但是这样有一点不足,就是没有AppCompatCheckBox状态变化的动画了。应该也有人会用一个LinearLayout包裹一个TextView和一个AppCompatCheckBox去实现,但是这样就会导致布局层级变深,布局里面的View的数量增加,布局加载速度变慢。
2:实现过程
1、AppCompatCheckBox是否拥有一个属性可以设置成这样的样式呢?带着这个问题我翻遍了AppCompatCheckBox可设置的属性,没有发现可以使勾选框居右的属性。
2、查看AppCompatCheckBox的源码,看勾选框是怎么绘制的。发现勾选框的绘制是在CompoundButton里面完成的。
@Override
protected void onDraw(Canvas canvas) {
final Drawable buttonDrawable = mButtonDrawable;
if (buttonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
final int drawableHeight = buttonDrawable.getIntrinsicHeight();
final int drawableWidth = buttonDrawable.getIntrinsicWidth();
final int top;
switch (verticalGravity) {
case Gravity.BOTTOM:
top = getHeight() - drawableHeight;
break;
case Gravity.CENTER_VERTICAL:
top = (getHeight() - drawableHeight) / 2;
break;
default:
top = 0;
}
final int bottom = top + drawableHeight;
final int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
final int right = isLayoutRtl() ? getWidth() : drawableWidth;
buttonDrawable.setBounds(left, top, right, bottom);
final Drawable background = getBackground();
if (background != null) {
background.setHotspotBounds(left, top, right, bottom);
}
}
super.onDraw(canvas);
if (buttonDrawable != null) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;
if (scrollX == 0 && scrollY == 0) {
buttonDrawable.draw(canvas);
} else {
canvas.translate(scrollX, scrollY);
buttonDrawable.draw(canvas);
canvas.translate(-scrollX, -scrollY);
}
}
}
这里面有两行代码非常关键
final int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
final int right = isLayoutRtl() ? getWidth() : drawableWidth;
如果布局是从右往左布局那么勾选框就在右边,布局是从左往右布局那么勾选框就在左边。那么我们就从这里下手修改:
public class MyCheckBox extends AppCompatCheckBox {
private final Rect rect;
public MyCheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
rect = new Rect();
}
@Override
protected void onDraw(Canvas canvas) {
Drawable buttonDrawable = CompoundButtonCompat.getButtonDrawable(this);
if (buttonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
final int drawableHeight = buttonDrawable.getIntrinsicHeight();
final int drawableWidth = buttonDrawable.getIntrinsicWidth();
final int top;
switch (verticalGravity) {
case Gravity.BOTTOM:
top = getHeight() - drawableHeight;
break;
case Gravity.CENTER_VERTICAL:
top = (getHeight() - drawableHeight) / 2;
break;
default:
top = 0;
}
final int bottom = top + drawableHeight;
final int left = getWidth() - drawableWidth;
final int right = getWidth();
buttonDrawable.setBounds(left, top, right, bottom);
final Drawable background = getBackground();
if (background != null) {
background.setHotspotBounds(left, top, right, bottom);
}
}
//简单绘制文字
TextPaint paint = getPaint();
paint.setColor(getCurrentTextColor());
String text = (String) getText();
paint.getTextBounds(text, 0, text.length(), rect);
canvas.drawText(text, 0, text.length(), getPaddingLeft(), (getHeight() + rect.height()) / 2, paint);
if (buttonDrawable != null) {
final int scrollX = getScrollX();
final int scrollY = getScrollY();
if (scrollX == 0 && scrollY == 0) {
buttonDrawable.draw(canvas);
} else {
canvas.translate(scrollX, scrollY);
buttonDrawable.draw(canvas);
canvas.translate(-scrollX, -scrollY);
}
}
}
}
写一个类继承AppCompatCheckBox并重写onDraw方法,通过buttonDrawable.setBounds方法将勾选框设置在右边,这样绘制出来的勾选框就在右边,然后绘制需要显示的文字,最后再绘制buttonDrawable就可以了。
网友评论