自定義 View 在 XML 中設定 wrap_content,但執行時卻佔滿整個螢幕,無法依內容大小顯示。
protected void onDraw(Canvas canvas) {
Paint mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.parseColor("#26ffffff"));
mPaint.setStrokeWidth(3);
canvas.drawCircle(80, 80, 80, mPaint);
Paint arcPaint = new Paint();
arcPaint.setAntiAlias(true);
arcPaint.setStyle(Paint.Style.STROKE);
arcPaint.setColor(Color.parseColor("#d08cc9"));
arcPaint.setStrokeWidth(3);
RectF mRectF = new RectF(0, 0, 160, 160);
canvas.drawArc(mRectF, 0f, 90f, false, arcPaint);
super.onDraw(canvas);
}
View 本身不知道繪製內容的大小,onDraw() 只是在給定的畫布上繪圖。若不覆寫 onMeasure(),View 預設會填滿父容器,導致 wrap_content 失效。
在自定義 View 中覆寫 onMeasure(),根據實際繪製內容計算寬高:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 設定期望大小,例如 160x160
int desiredWidth = 160;
int desiredHeight = 160;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width, height;
// 根據 MeasureSpec 模式決定最終大小
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
width = Math.min(desiredWidth, widthSize);
} else {
width = desiredWidth;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(desiredHeight, heightSize);
} else {
height = desiredHeight;
}
setMeasuredDimension(width, height);
}
加入此方法後,XML 中的 wrap_content 即可正常運作,View 大小將符合繪製內容範圍。