自定义视图中的奇怪行为

时间:2017-11-12 08:29:59

标签: android view

我想知道它的宽度和高度总是相等的。

当用户在xml中定义指定的高度和宽度时,它会选择较小的一个。

例如:

    <com.mmmmar.ControlView
    android:layout_width="100dp"
    android:layout_height="200dp"
    android:background="#f00" />
它运行良好。 image that app runs well

然而,当我使宽度大于高度时,它会意外地运行。 绿色块是我在这个视图上绘制的,红色块是我在xml中设置的背景,用于指示视图区域。

<com.mmmmar.ControlView
    android:layout_width="200dp"
    android:layout_height="100dp"
    android:background="#f00" />

iamge that app runs wrong

这是我的代码

 public class ControlView extends View {

    private final static int DEFAULT_SIZE = 200;

    private int mDrawRadius;
    private Paint mPaint;

    public ControlView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        // configure paint
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        mPaint = paint;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int size = dp2px(DEFAULT_SIZE, getContext());
        int width = calculateSpec(widthMeasureSpec, size);
        int height = calculateSpec(heightMeasureSpec, size);
        int radius = Math.min(width, height);
        // width should equal height.
        setMeasuredDimension(radius, radius);
        mDrawRadius = radius;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = mPaint;
        paint.setColor(Color.GREEN);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawRect(0, 0, mDrawRadius, mDrawRadius, paint);
    }

    public int dp2px(float dp, Context context) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }

    public int calculateSpec(int measureSpec, int defaultSize) {
        int mode = View.MeasureSpec.getMode(measureSpec);
        int size = View.MeasureSpec.getSize(measureSpec);
        int realSize;
        if (mode == View.MeasureSpec.EXACTLY) {
            realSize = size;
        } else {
            // For Mode :UNSPECIFIED and AT_MOST
            realSize = Math.min(size, defaultSize);
        }
        return realSize;
    }
}

1 个答案:

答案 0 :(得分:0)

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int size = dp2px(DEFAULT_SIZE, getContext());
    int width = calculateSpec(widthMeasureSpec, size);
    int height = calculateSpec(heightMeasureSpec, size);
    int radius = Math.min(width, height);
    // width should equal height.
    setMeasuredDimension(radius, radius);
    mDrawRadius = radius;
}

计算后无需设置测量尺寸。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // Your logic comes here to pick smallest border
    super.onMeasure(smallest_border_that_you_pick,smallest_border_that_you_pick)
}

会解决你的问题。