我爱编程

Android自定义圆角图片

2018-07-26  本文已影响227人  香烟和白粥

回顾一下,自定义view重写的关键方法有:

measure 测量组件本身的大小
layout 确定组件在视图中的位置
draw 根据位置和大小,将组件画出来

    /**
     * 圆形模式
     */
    private static final int MODE_CIRCLE = 1;
    /**
     * 普通模式
     */
    private static final int MODE_NONE = 0;
    /**
     * 圆角模式
     */
    private static final int MODE_ROUND = 2;
    /**
     * 上面的圆角模式
     */
    private static final int MODE_ROUND_TOP = 3;

    /**
     * 下方圆角模式
     */
    private static final int MODE_ROUND_BOTTOM = 4;
    <declare-styleable name="RoundImageview">
        <attr name="viewtype" format="enum">
            <enum name="circle" value="1"/>
            <enum name="round" value="2"/>
            <enum name="roundtop" value="3"/>
            <enum name="round_bottom" value="4"/>
        </attr>
        <attr name="radius" format="dimension"/>
    </declare-styleable>
  private static final int MODE_ROUND_BOTTOM = 4;
    private BitmapShader bitmapShader;

    private Paint mPaint;
    private int currMode = 0;
    private Path path = new Path();
    private RectF rectF = new RectF();
    private Matrix matrix = new Matrix();
    private Bitmap bitmap;
    // 圆角矩形路径
    private float[] radii = new float[8];
    /**
     * 圆角半径
     */
    private int currRound = dp2px(10);

    private int dp2px(float value) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics());
    }
 public RoundImageview(Context context) {
        super(context);
        initViews();
    }

    public RoundImageview(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundImageview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyledAttrs(context, attrs, defStyleAttr);
        initViews();
    }


    private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageview, defStyleAttr, 0);
        currMode = a.hasValue(R.styleable.RoundImageview_viewtype) ? a.getInt(R.styleable.RoundImageview_viewtype, MODE_NONE) : MODE_NONE;
        currRound = a.hasValue(R.styleable.RoundImageview_radius) ? a.getDimensionPixelSize(R.styleable.RoundImageview_radius, currRound) : currRound;
        //用完后记得回收
        a.recycle();
    }

    private void initViews() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    }

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        /*
         * 当模式为圆形模式的时候,我们强制让宽高一致
         */
        if (currMode == MODE_CIRCLE) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int result = Math.min(getMeasuredHeight(), getMeasuredWidth());
            setMeasuredDimension(result, result);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
        path.reset();
        rectF.left = getPaddingLeft();
        rectF.top = getPaddingTop();
        rectF.right = getMeasuredWidth() - getPaddingRight();
        rectF.bottom = getMeasuredHeight() - getPaddingBottom();
        switch (currMode) {
            case MODE_ROUND_TOP:
                fillRadii(currRound, currRound, currRound, currRound, 0, 0, 0, 0);
                break;
            case MODE_ROUND_BOTTOM:
                fillRadii(0, 0, 0, 0, currRound, currRound, currRound, currRound);
                break;
            case MODE_ROUND:
                fillRadii(currRound, currRound, currRound, currRound, currRound, currRound, currRound, currRound);
                break;
            default:
                fillRadii(0, 0, 0, 0, 0, 0, 0, 0);
                break;
        }
        path.addRoundRect(rectF, radii, Path.Direction.CCW);
        if (bitmapShader != null && bitmap != null && getMeasuredHeight() > 0 && getMeasuredWidth() > 0) {
            matrix.reset();
            float sx = getMeasuredWidth() / (float)bitmap.getWidth();
            float sy = getMeasuredHeight() / (float)bitmap.getHeight();
            float scale = Math.max(sx,sy);
            matrix.postScale(scale, scale);
            bitmapShader.setLocalMatrix(matrix);
        }

    }
  private void fillRadii(float... radii) {
        System.arraycopy(radii, 0, this.radii, 0, 8);
    }
@Override
    protected void onDraw(Canvas canvas) {
        final int saveCount = canvas.getSaveCount();
        canvas.save();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            if (getCropToPadding()) {
                final int scrollX = getScrollX();
                final int scrollY = getScrollY();
                canvas.clipRect(scrollX + getPaddingLeft(), scrollY + getPaddingTop(),
                        scrollX + getRight() - getLeft() - getPaddingRight(),
                        scrollY + getBottom() - getTop() - getPaddingBottom());
            }
        }
        canvas.translate(getPaddingLeft(), getPaddingTop());
        mPaint.reset();
        if (bitmapShader != null) {
            if (currMode == MODE_CIRCLE) {//当为圆形模式的时候
                mPaint.setShader(bitmapShader);
                canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, mPaint);
            } else if (currMode == MODE_ROUND) {//当为圆角模式的时候
                mPaint.setShader(bitmapShader);
                canvas.drawRoundRect(rectF,
                        currRound, currRound, mPaint);
            } else if (currMode == MODE_ROUND_TOP || currMode == MODE_ROUND_BOTTOM) {//当为上/下圆角模式的时候
                mPaint.setShader(bitmapShader);
                canvas.drawPath(path, mPaint);
            } else {
                mPaint.setShader(bitmapShader);
                canvas.drawPath(path, mPaint);
            }
        }
        canvas.restoreToCount(saveCount);
    }
    public void setImage(@Nullable Bitmap bitmap) {
        if (bitmap == null) return;
        bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        this.bitmap = bitmap;
        requestLayout();
    }

参考:https://blog.csdn.net/harvic880925/article/details/38926877

上一篇下一篇

猜你喜欢

热点阅读