Android自定义View 一个可设置四个顶点弧度的ImageView

项目介绍:

点击打开链接

代码:

  自定义属性  :

values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomImageView">
        <attr name="leftTopX" format="float" />
        <attr name="leftTopY" format="float" />
        <attr name="rightTopX" format="float" />
        <attr name="rightTopY" format="float" />
        <attr name="rightBottomX" format="float" />
        <attr name="rightBottomY" format="float" />
        <attr name="leftBottomX" format="float" />
        <attr name="leftBottomY" format="float" />
        <attr name="roundPx" format="float"/>
    </declare-styleable>

</resources>

代码部分:

package com.example.he.customimageview;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;

/**
 * Created by he on 2017/3/11.
 */

public class CustomImageView extends ImageView {

    private final String TAG = getClass().getSimpleName();

    private Paint mPaint;
    private Path mPath;
    private Drawable drawable;

    //控件在指定为wrap_content下的默认宽高
    private static final int DEFAULT_WIDTH = 500;
    private static final int DEFAULT_HEIGHT = 300;

    private float leftTopX;
    private float leftTopY;
    private float rightTopX;
    private float rightTopY;
    private float rightBottomX;
    private float rightBottomY;
    private float leftBottomX;
    private float leftBottomY;
    private float roundPx;

    private int dx;
    private int dy;

    public CustomImageView(Context context) {
        this(context, null);
    }

    public CustomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPath = new Path();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.WHITE);
        drawable = getDrawable();
        setWillNotDraw(false);
        obtainStyledAttributes(attrs);
        setImageResource(R.drawable.transparent);

    }


    /**
     * 获取自定义属性
     *
     * @param attrs
     */
    private void obtainStyledAttributes(AttributeSet attrs) {
        final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomImageView);
        leftTopX = a.getFloat(R.styleable.CustomImageView_leftTopX, 10f);
        leftTopY = a.getFloat(R.styleable.CustomImageView_leftTopY, 15f);
        rightTopX = a.getFloat(R.styleable.CustomImageView_rightTopX, 10f);
        rightTopY = a.getFloat(R.styleable.CustomImageView_rightTopY, 15f);
        rightBottomX = a.getFloat(R.styleable.CustomImageView_rightBottomX, 10f);
        rightBottomY = a.getFloat(R.styleable.CustomImageView_rightBottomY, 15f);
        leftBottomX = a.getFloat(R.styleable.CustomImageView_leftBottomX, 10f);
        leftBottomY = a.getFloat(R.styleable.CustomImageView_leftBottomY, 15f);
        roundPx = a.getFloat(R.styleable.CustomImageView_roundPx, 0f);
        a.recycle();

    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        } else if (widthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_WIDTH, heightSize);
        } else if (heightMode == MeasureSpec.AT_MOST) {
            Log.d(TAG, "onMeasure: " + widthSize);
            setMeasuredDimension(widthSize, DEFAULT_HEIGHT);
        } else {
            setMeasuredDimension(widthSize, heightSize);
        }

    }


    @Override
    protected void onDraw(Canvas canvas) {
        if (drawable == null) {
            super.onDraw(canvas);
            return;
        }

        Bitmap b = ((BitmapDrawable) drawable).getBitmap();
        RectF rectF = new RectF(dx, dy, getWidth() - dx, getHeight() - dy);

        //清屏
//        canvas.drawColor(Color.BLUE, PorterDuff.Mode.CLEAR);
//        Paint p=new Paint();
//        p.setColor(Color.WHITE);
//        canvas.drawPaint(p);

        canvas.drawARGB(0, 0, 0, 0);

        int layId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
        final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());
        final Rect rectDst = new Rect(0, 0, getWidth(), getHeight());
        if (roundPx > 0f) {
            canvas.drawRoundRect(rectF, roundPx, roundPx, mPaint);
        } else {
            float radii[] = {leftTopX, leftTopY, rightTopX, rightTopY, rightBottomX, rightBottomY, leftBottomX, leftBottomY};
            mPath.addRoundRect(rectF, radii, Path.Direction.CCW);
            canvas.drawPath(mPath, mPaint);
        }
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(b, rectSrc, rectDst, mPaint);
        mPaint.setXfermode(null);
        canvas.restoreToCount(layId);

    }


    public void clipX(int start, int end, long duration) {
        ValueAnimator animator = ValueAnimator.ofInt(start, end);
        animator.setDuration(duration);
        animator.setInterpolator(new LinearInterpolator());

        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                dx = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        animator.start();
    }


    public void clipY(int start, int end, long duration) {
        ValueAnimator animator = ValueAnimator.ofInt(start, end);
        animator.setDuration(duration);
        animator.setInterpolator(new LinearInterpolator());

        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                dy = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        animator.start();
    }


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


//    /**
//     * 绘制圆角矩形图片
//     */
//    @Override
//    protected void onDraw(Canvas canvas) {
////        Drawable drawable = getDrawable();
//        if (drawable!=null) {
//            Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
//            Bitmap b = getRoundBitmap(bitmap);
//            final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());
//            final Rect rectDst = new Rect(0, 0, getWidth(), getHeight());
//            mPaint.reset();
//            canvas.drawBitmap(b, rectSrc, rectDst, mPaint);
//
//        } else {
//            super.onDraw(canvas);
//        }
//    }

    /**
     * 获取圆角矩形图片
     *
     * @param bitmap
     * @param
     * @return Bitmap
     */
    private Bitmap getRoundBitmap(@NonNull Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        final int color = 0xff424242;
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);

        mPaint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        mPaint.setColor(color);
        Path path = new Path();

        if (roundPx > 0f) {
            canvas.drawRoundRect(rectF, roundPx, roundPx, mPaint);
            Log.d(TAG, "getRoundBitmap: ");
        } else {
            //        float radii[] = {400, 400, 400, 450, 400, 450, 400, 450};
            float radii[] = {leftTopX, leftTopY, rightTopX, rightTopY, rightBottomX, rightBottomY, leftBottomX, leftBottomY};
            path.addRoundRect(rectF, radii, Path.Direction.CCW);
            canvas.drawPath(path, mPaint);
        }

        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, mPaint);
        return output;
    }


}

MainActivity:

package com.example.he.customimageview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private int width;
    private int height;
    private CustomImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (CustomImageView) findViewById(R.id.ima);

        Button clipX = (Button) findViewById(R.id.clipX);
        Button clipY = (Button) findViewById(R.id.clipY);
        Button recoverX = (Button) findViewById(R.id.recoverX);
        Button recoverY = (Button) findViewById(R.id.recoverY);
        clipX.setOnClickListener(this);
        clipY.setOnClickListener(this);
        recoverX.setOnClickListener(this);
        recoverY.setOnClickListener(this);

        width = CustomImageView.dp2px(this, 200);
        height = CustomImageView.dp2px(this, 100);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.clipX:
                //从左右两边同时裁剪,裁剪掉宽度的2/3(左边裁1/3,右边裁1/3)
                imageView.clipX(0, width / 3, 5000);
                break;
            case R.id.clipY:
                //从上下两边同时裁剪,裁剪掉高度的2/3(上边裁1/3,下边裁1/3)
                imageView.clipY(0, height / 3, 5000);
                break;
            case R.id.recoverX:
                imageView.clipX(width / 3, 0, 4000);
                break;
            case R.id.recoverY:
                imageView.clipY(height / 3, 0, 5000);
                break;
            default:
                break;
        }

    }
}


源码地址:点击打开链接

如果觉得还可以求个Star




猜你喜欢

转载自blog.csdn.net/fuckluy/article/details/61631635