BiggerView

Android自定义控件之局部图片放大镜--BiggerView

Stars
74

1.onMesure 2.bitmapcanvas 3.:FitImageView()``BiggerView() 4.guihubok 5.``

1.1

2.2(clipOutPathAPI26)

3.(star)
	allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}
	
	dependencies {
	        implementation 'com.github.toly1994328:BiggerView:v1.01'
	}

FitImageView

ImageViewbitmap View

viewView ,


1.
    <!---->
    <declare-styleable name="FitImageView">
        <!---->
        <attr name="z_fit_src" format="reference"/>
    </declare-styleable>
2.
/**
 * <br/>
 * 2018/11/19 0019:0:14<br/>
 * [email protected]<br/>
 * 
 */
public class FitImageView extends View {

    private Paint mPaint;//
    private Drawable mFitSrc;//Drawable
    private Bitmap mBitmapSrc;//
    protected Bitmap mFitBitmap;//

    protected float scaleRateW2fit = 1;//
    protected float scaleRateH2fit = 1;//
    protected int mImageW, mImageH;//

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

    public FitImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public FitImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FitImageView);
        mFitSrc = a.getDrawable(R.styleable.FitImageView_z_fit_src);
        a.recycle();
        init();//
    }

    private void init() {
        //
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBitmapSrc = ((BitmapDrawable) mFitSrc).getBitmap();//
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //TODO draw
    }
3.()
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    mImageW = dealWidth(widthMeasureSpec);//
    mImageH = dealHeight(heightMeasureSpec);//
    float bitmapWHRate = mBitmapSrc.getHeight() * 1.f / mBitmapSrc.getWidth();//
    if (mImageH >= mImageW) {
        mImageH = (int) (mImageW * bitmapWHRate);//
    } else {
       mImageW = (int) (mImageH / bitmapWHRate);//
    }
    setMeasuredDimension(mImageW, mImageH);
}


/**
 * @param heightMeasureSpec
 * @return
 */
private int dealHeight(int heightMeasureSpec) {
    int result = 0;
    int mode = MeasureSpec.getMode(heightMeasureSpec);
    int size = MeasureSpec.getSize(heightMeasureSpec);
    if (mode == MeasureSpec.EXACTLY) {
        //
        // android:layout_height="40dp""match_parent"
        scaleRateH2fit = size * 1.f / mBitmapSrc.getHeight() * 1.f;
        result = size;
    } else {
        result = mBitmapSrc.getHeight();
        if (mode == MeasureSpec.AT_MOST) {//
            result = Math.min(result, size);

        }
    }
    return result;
}


/**
 * @param widthMeasureSpec
 */
private int dealWidth(int widthMeasureSpec) {
    int result = 0;
    int mode = MeasureSpec.getMode(widthMeasureSpec);
    int size = MeasureSpec.getSize(widthMeasureSpec);
    if (mode == MeasureSpec.EXACTLY) {
        //
        // android:layout_XXX="40dp""match_parent"
        scaleRateW2fit = size * 1.f / mBitmapSrc.getWidth();
        result = size;

    } else {
        result = mBitmapSrc.getWidth();
        if (mode == MeasureSpec.AT_MOST) {//
            result = Math.min(result, size);
        }
    }
    return result;
}
4.bitmap

onLayout

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    mFitBitmap = createBigBitmap(Math.min(scaleRateW2fit, scaleRateH2fit), mBitmapSrc);
    mBitmapSrc = null;//
}

/**
 * rate
 *
 * @param rate 
 * @param src  
 * @return 
 */
protected Bitmap createBigBitmap(float rate, Bitmap src) {
    Matrix matrix = new Matrix();
    //:3
    matrix.setValues(new float[]{
            rate, 0, 0,
            0, rate, 0,
            0, 0, 1
    });
    return Bitmap.createBitmap(src, 0, 0,
            src.getWidth(), src.getHeight(), matrix, true);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(mFitBitmap, 0, 0, mPaint);
}

BiggerView

1.attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!---->
    <declare-styleable name="BiggerView">
        <!---->
        <attr name="z_bv_radius" format="dimension"/>
        <!---->
        <attr name="z_bv_outline_width" format="dimension"/>
        <!---->
        <attr name="z_bv_outline_color" format="color"/>
        <!---->
        <attr name="z_bv_rate" format="float"/>
    </declare-styleable>
</resources>
2.
public class BiggerView extends FitImageView {
    private int mBvRadius = dp(30);//
    private int mBvOutlineWidth = 2;//

    private float rate = 4;//
    private int mBvOutlineColor = 0xffCCDCE4;//

    private Paint mPaint;//
    private Bitmap mBiggerBitmap;//
    private Path mPath;//

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

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

    public BiggerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BiggerView);
        mBvRadius = (int) a.getDimension(R.styleable.BiggerView_z_bv_radius, mBvRadius);
        mBvOutlineWidth = (int) a.getDimension(R.styleable.BiggerView_z_bv_outline_width, mBvOutlineWidth);
        mBvOutlineColor = a.getColor(R.styleable.BiggerView_z_bv_outline_color, mBvOutlineColor);
        rate = (int) a.getFloat(R.styleable.BiggerView_z_bv_rate, rate);
        a.recycle();
        init();
    }

    private void init() {
        //
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(mBvOutlineColor);
        mPaint.setStrokeWidth(mBvOutlineWidth * 2);
        mPath = new Path();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        }
    }
}

1.
private int mBvRadius = dp(30);//
private Paint mPaint;//

private float mCurX;//X
private float mCurY;//Y
private boolean isDown;//
2.
@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
            isDown = true;
            mCurX = event.getX();
            mCurY = event.getY();
            break;
        case MotionEvent.ACTION_UP:
            isDown = false;
    }
    invalidate();//
    return true;
}
3.
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (isDown) {
        canvas.drawCircle(mCurX, mCurY, mBvRadius, mPaint);
    }
}

()

1.onLayoutrateBitmap
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    mBiggerBitmap = createBigBitmap(rate, mFitBitmap);
}
2.
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isDown) {
            canvas.drawBitmap(mBiggerBitmap, -mCurX * (rate - 1), -mCurY * (rate - 1), mPaint);
        }
    }

1


3.2

clipOutPathAPI,26 (,...)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    mShowY = -mCurY * (rate - 1) - 2 * mBvRadius;
    canvas.drawBitmap(mBiggerBitmap,
            -mCurX * (rate - 1), mShowY, mPaint);
    float rY = mCurY > 2 * mBvRadius ? mCurY - 2 * mBvRadius : mCurY +  mBvRadius;
    mPath.addCircle(mCurX, rY, mBvRadius, Path.Direction.CCW);
    canvas.clipOutPath(mPath);
    super.onDraw(canvas);
    canvas.drawCircle(mCurX, rY, mBvRadius, mPaint);
}

1.
enum Style {
    NO_CLIP,//
    CLIP_CIRCLE,//
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (isDown) {
        switch (mStyle) {
            case NO_CLIP://
                float showY = -mCurY * (rate - 1);
                canvas.drawBitmap(mBiggerBitmap, -mCurX * (rate - 1), showY, mPaint);
                break;
            case CLIP_CIRCLE:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    mPath.reset();
                    showY = -mCurY * (rate - 1) - 2 * mBvRadius;
                    canvas.drawBitmap(mBiggerBitmap, -mCurX * (rate - 1), showY, mPaint);
                    float rY = mCurY > 2 * mBvRadius ? mCurY - 2 * mBvRadius : mCurY + mBvRadius;
                    mPath.addCircle(mCurX, rY, mBvRadius, Path.Direction.CCW);
                    canvas.clipOutPath(mPath);
                    super.onDraw(canvas);
                    canvas.drawCircle(mCurX, rY, mBvRadius, mPaint);
                } else {
                    mStyle = Style.NO_CLIP;//,
                    invalidate();
                }
                //....
        }
    }
}
2.
@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
            mCurX = event.getX();
            mCurY = event.getY();
            //
            isDown = judgeRectArea(mImageW / 2, mImageH / 2, mCurX, mCurY, mImageW, mImageH);
            break;
        case MotionEvent.ACTION_UP:
            isDown = false;
    }
    invalidate();//
    return true;
}

/**
 * 
 */
public static boolean judgeRectArea(float srcX, float srcY, float dstX, float dstY, float w, float h) {
    return Math.abs(dstX - srcX) < w / 2 && Math.abs(dstY - srcY) < h / 2;
}

github

0.!!!!!!

1.github

2.

3.https://jitpack.io/
4.

ok


1.

| | ---|---|--- V0.1--github|2018-11-17|Android--BiggerView

2.

| QQ|| ---|---|---|---| | 1981462002|zdl1994328| github|||

3.

1----, 2---- 3---- 4----


Related Projects