1:需求
如果要實(shí)現(xiàn)勾選框居右的AppCompatCheckBox怎么辦礁竞。
肯定有人會說直接用TextView加一個(gè)選擇器給DrawableRight不就可以了嗎蚊逢?但是這樣有一點(diǎn)不足臭猜,就是沒有AppCompatCheckBox狀態(tài)變化的動畫了猪瞬。應(yīng)該也有人會用一個(gè)LinearLayout包裹一個(gè)TextView和一個(gè)AppCompatCheckBox去實(shí)現(xiàn)姥闪,但是這樣就會導(dǎo)致布局層級變深俗扇,布局里面的View的數(shù)量增加,布局加載速度變慢。
2:實(shí)現(xiàn)過程
1涵防、AppCompatCheckBox是否擁有一個(gè)屬性可以設(shè)置成這樣的樣式呢?帶著這個(gè)問題我翻遍了AppCompatCheckBox可設(shè)置的屬性沪铭,沒有發(fā)現(xiàn)可以使勾選框居右的屬性壮池。
2、查看AppCompatCheckBox的源碼杀怠,看勾選框是怎么繪制的椰憋。發(fā)現(xiàn)勾選框的繪制是在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);
}
}
}
這里面有兩行代碼非常關(guān)鍵
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);
}
}
}
}
寫一個(gè)類繼承AppCompatCheckBox并重寫onDraw方法证舟,通過buttonDrawable.setBounds方法將勾選框設(shè)置在右邊,這樣繪制出來的勾選框就在右邊窗骑,然后繪制需要顯示的文字女责,最后再繪制buttonDrawable就可以了。