1. 繼承View重寫onDraw方法
public class CircleView extends View {
private int mColor = Color.RED;
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
setBackgroundColor(getResources().getColor(android.R.color.holo_blue_bright));
mPaint.setColor(mColor);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
int radius = Math.min(width, height) / 2;
canvas.drawCircle(width / 2, height / 2, radius, mPaint);
}
}
2. 問題 padding和wrap_content無效
<qingfengmy.developmentofart._4view.CircleView
android:layout_width="wrap_content"
android:padding="20dp"
android:layout_margin="20dp"
android:layout_height="100dp" />
如上設置時,margin是有效的,因為margin在父View中處理;padding無效,因為繼承自View和ViewGroup的控件,padding是需要自己處理的;wrap_content是無效的,前文分析過,在onMeasure的時候,最大模式和精確模式,測量寬高都是設置的父Veiw的剩余空間,wrap_content需要自己處理。
3. wrap_contnet的解決
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
int widthResult = widthSpecSize;
int heightResult = heightSpecSize;
if (widthSpecMode == MeasureSpec.AT_MOST) {
widthResult = mWidth;
}
if (heightSpecMode == MeasureSpec.AT_MOST) {
heightResult = mWidth;
}
setMeasuredDimension(widthResult, heightResult);
}
4. padding的解決
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int width = getWidth() - paddingLeft - paddingRight;
int height = getHeight() - paddingTop - paddingBottom;
int radius = Math.min(width, height) / 2;
canvas.drawCircle(paddingLeft + width / 2, paddingTop + height / 2, radius, mPaint);
}