为ImageView Android添加边框以进行裁剪

时间:2016-10-17 08:08:50

标签: android imageview

我想在ImageView上添加一个矩形边框,允许用户从8个方向更改它的大小,以便为裁剪目的提供预览。

我可以通过哪种方式实现最佳目的,定义自定义ImageView并添加代码以绘制矩形或将ImageView添加到SurfaceView

这是我的代码,我可以使用它在我的图像周围绘制一个矩形:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class CustomCropImageView extends ImageView implements     View.OnTouchListener{

// Bitmap to draw.
Bitmap myBitmap;

// Fundamental attributes.
int xPos, yPos;
int originWidth, originHeight;
int widthImg, heightImg;
int xCrop, yCrop;
int cropWidth, cropHeight;

GestureDetector myGesture;

public CustomCropImageView(Context context){
    super(context);
    xPos = yPos = xCrop = yCrop = 0;
    // setOnTouchListener(this);
}

public CustomCropImageView(Context context, AttributeSet attSet){
    super(context, attSet);
    xPos = yPos = xCrop = yCrop = 0;
    // setOnTouchListener(this);
}

@Override
protected void onDraw(Canvas canvas) {

    Drawable drawable = getDrawable();

    if(drawable == null)
        return;

    if(originWidth == 0 && originHeight == 0){

        Bitmap tmp = ((BitmapDrawable)drawable).getBitmap();
        myBitmap = tmp.copy(Bitmap.Config.ARGB_8888, true);

        originWidth = myBitmap.getWidth();
        originHeight = myBitmap.getHeight();

        Integer[] myDWAndH = getScreenWidthAndHeight();

        widthImg = cropWidth = myDWAndH[0];
        heightImg = cropHeight = (int)((float)myDWAndH[0]*((float)originHeight / (float)originWidth));
        yPos = yCrop = (myDWAndH[1] - heightImg) / 2;

        myBitmap = Bitmap.createScaledBitmap(myBitmap, widthImg, heightImg, false);

    }

    Paint myPaint = new Paint();

    canvas.drawBitmap(myBitmap, xPos, yPos, myPaint);

    drawAnchorRectangle(canvas);
}

void drawAnchorRectangle(Canvas canvas){

    // Anchor rectangle.
    Paint myPaint = new Paint();

    myPaint.setStyle(Paint.Style.STROKE);
    myPaint.setColor(getContext().getResources().getColor(R.color.ImgVBorder));
    myPaint.setStrokeWidth(5);

    Rect myRect = new Rect(xCrop, yCrop, cropWidth, yCrop + cropHeight);
    canvas.drawRect(myRect, myPaint);

    // Anchor point.
    myPaint.setStyle(Paint.Style.FILL);
    myPaint.setColor(getContext().getResources().getColor(R.color.ImgVAnchorPoint));
    myPaint.setStrokeWidth(3);

    int anchorPointW = 10;
    int halfAnchorPointW = anchorPointW / 2;

    /*
    // Top left.
    Rect anchorPoint = new Rect(xCrop + cropWidth - halfAnchorPointW, yCrop - halfAnchorPointW,
            anchorPointW, yCrop + halfAnchorPointW);

    canvas.drawRect(anchorPoint, myPaint);

    // Top right.
    anchorPoint.set(xCrop + cropWidth - halfAnchorPointW, yCrop - halfAnchorPointW,
            anchorPointW, yCrop + halfAnchorPointW);

    canvas.drawRect(anchorPoint, myPaint);
    */
}

Integer[] getScreenWidthAndHeight(){
    DisplayMetrics dMetrics = new DisplayMetrics();
    ((MainActivity)getContext()).getWindowManager().getDefaultDisplay().getMetrics(dMetrics);

    Integer[] myResult = new Integer[2];
    myResult[0] = dMetrics.widthPixels - 40;
    myResult[1] = dMetrics.heightPixels;

    return myResult;
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    int action = event.getActionMasked();

    final String TAG = "!!!123";

    switch (action) {

        case MotionEvent.ACTION_DOWN:
            Log.d(TAG, "Action was DOWN");
            return true;

        case MotionEvent.ACTION_MOVE:
            Log.d(TAG, "Action was MOVE");
            break;

        case MotionEvent.ACTION_UP:
            Log.d(TAG, "Action was UP");

            break;

        case MotionEvent.ACTION_CANCEL:
            Log.d(TAG, "Action was CANCEL");
            break;

        case MotionEvent.ACTION_OUTSIDE:
            Log.d(TAG, "Movement occurred outside bounds of current screen element");
            break;
    }

    return super.onTouchEvent(event);
}

@Override
public boolean onTouch(View v, MotionEvent event) {

    return super.onTouchEvent(event);
}
}

1 个答案:

答案 0 :(得分:0)

这里是我如何解决的,通过定义自定义图像视图并在OnDraw方法中进行一些更改,我还添加了代码以降低图像的亮度,因此当您调整大小时,真实背后的背景图像看起来不错矩形:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import java.util.ArrayList;
import java.util.List;

public class CustomCropImageView extends ImageView implements View.OnTouchListener{

// Bitmap to draw.
Bitmap myBitmap;

// Fundamental attributes.
int xPos, yPos;
int originWidth, originHeight;
int widthImg, heightImg;
int xCrop, yCrop;
int cropWidth, cropHeight;
int offsetLeft = 0, offsetRight = 0, offsetTop = 0, offsetBottom = 0;

// List of anchor point rectangle.
List<Rect> anchorPoints;

int anchorPointW = 30;
int halfAnchorPointW = anchorPointW / 2;

// Background bitmap for cropping.
Bitmap darkBitmap;

public CustomCropImageView(Context context){
    super(context);
    xPos = yPos = xCrop = yCrop = 0;
    // setOnTouchListener(this);
}

public CustomCropImageView(Context context, AttributeSet attSet){
    super(context, attSet);
    xPos = yPos = xCrop = yCrop = 0;
    // setOnTouchListener(this);
}

Integer[] myDWAndH;

@Override
protected void onDraw(Canvas canvas) {

    Drawable drawable = getDrawable();

    if(drawable == null)
        return;

    if(originWidth == 0 && originHeight == 0){

        Bitmap tmp = ((BitmapDrawable)drawable).getBitmap();
        myBitmap = tmp.copy(Bitmap.Config.ARGB_8888, true);

        originWidth = myBitmap.getWidth();
        originHeight = myBitmap.getHeight();

        myDWAndH = getScreenWidthAndHeight();

        widthImg = cropWidth = myDWAndH[0] - anchorPointW;
        heightImg = cropHeight = (int)((float)myDWAndH[0]*((float)originHeight / (float)originWidth)) - anchorPointW;
        yPos = yCrop = (myDWAndH[1] - heightImg) / 2;

        myBitmap = Bitmap.createScaledBitmap(myBitmap, widthImg, heightImg, false);

        createDarkBitmap(myBitmap);

        initAnchorPoint();

    }

    Paint myPaint = new Paint();

    canvas.drawBitmap(darkBitmap, xPos + halfAnchorPointW, yPos + halfAnchorPointW, myPaint);

    drawAnchorRectangle(canvas);
}

void drawAnchorRectangle(Canvas canvas){

    // Anchor rectangle.
    Paint myPaint = new Paint();

    canvas.drawBitmap(myBitmap, new Rect(offsetLeft, offsetTop, cropWidth + offsetRight, cropHeight + offsetBottom),
            new Rect(xCrop + halfAnchorPointW + offsetLeft, yCrop + halfAnchorPointW + offsetTop,
                    xCrop + halfAnchorPointW + cropWidth + offsetRight, yCrop + halfAnchorPointW + cropHeight + offsetBottom), myPaint);

    myPaint.setStyle(Paint.Style.STROKE);
    myPaint.setColor(getContext().getResources().getColor(R.color.ImgVBorder));
    myPaint.setStrokeWidth(5);

    Rect myRect = new Rect(xCrop + halfAnchorPointW + offsetLeft, yCrop + halfAnchorPointW + offsetTop,
            xCrop + halfAnchorPointW + cropWidth + offsetRight, yCrop + halfAnchorPointW + cropHeight + offsetBottom);

    canvas.drawRect(myRect, myPaint);

    // Anchor point.
    myPaint.setStyle(Paint.Style.FILL);
    myPaint.setColor(getContext().getResources().getColor(R.color.ImgVAnchorPoint));

    // Top left.
    canvas.drawRect(anchorPoints.get(0), myPaint);

    // Top right.
    canvas.drawRect(anchorPoints.get(1), myPaint);

    // Bottom left.
    canvas.drawRect(anchorPoints.get(2), myPaint);

    // Bottom right.
    canvas.drawRect(anchorPoints.get(3), myPaint);

}

void initAnchorPoint(){

    if(anchorPoints != null)
        anchorPoints.clear();
    else
        anchorPoints = new ArrayList<>();

    // Top left.
    anchorPoints.add(new Rect(xCrop + offsetLeft, yCrop + offsetTop,
            xCrop + anchorPointW + offsetLeft, yCrop + anchorPointW + offsetTop));

    // Top right.
    anchorPoints.add(new Rect(xCrop + cropWidth + offsetRight, yCrop + offsetTop,
            xCrop + cropWidth + anchorPointW + offsetRight, yCrop + anchorPointW + offsetTop));

    // Bottom left.
    anchorPoints.add(new Rect(xCrop + offsetLeft, yCrop + cropHeight + offsetBottom,
            xCrop + anchorPointW + offsetLeft, yCrop + cropHeight + anchorPointW + offsetBottom));

    // Bottom right.
    anchorPoints.add(new Rect(xCrop + cropWidth + offsetRight, yCrop + cropHeight + offsetBottom,
            xCrop + cropWidth + anchorPointW + offsetRight, yCrop + cropHeight + anchorPointW + offsetBottom));

}

Integer[] getScreenWidthAndHeight(){
    DisplayMetrics dMetrics = new DisplayMetrics();
    ((MainActivity)getContext()).getWindowManager().getDefaultDisplay().getMetrics(dMetrics);

    Integer[] myResult = new Integer[2];
    myResult[0] = dMetrics.widthPixels - 40;
    myResult[1] = dMetrics.heightPixels;

    return myResult;
}

int anchorChoice = -1;

void setAnchorAction(MotionEvent event){
    int x = (int)event.getRawX();
    int y = (int)event.getRawY();
    int offset = 50 + anchorPointW;

    anchorChoice = -1;

    if(y > (anchorPoints.get(0).top - offset) && y < (anchorPoints.get(0).bottom + offset)){
        if(x < (anchorPoints.get(0).right + offset) && x > (anchorPoints.get(0).left - offset)){
            anchorChoice = 0;
        }
        else if(x < (anchorPoints.get(1).right + offset) && x > (anchorPoints.get(1).left - offset))
            anchorChoice = 1;
    }
    else if(y > (anchorPoints.get(2).top - offset) && y < (anchorPoints.get(2).bottom + offset)){
        if(x < (anchorPoints.get(2).right + offset) && x > (anchorPoints.get(2).left - offset)){
            anchorChoice = 2;
        }
        else if(x < (anchorPoints.get(3).right + offset) && x > (anchorPoints.get(3).left - offset))
            anchorChoice = 3;
    }
}

void resizeRectangle(MotionEvent event){

    if(anchorChoice == -1)
        return;

    int x = (int)event.getRawX();
    int y = (int)event.getRawY();
    int dif = 0;

    initAnchorPoint();
    invalidate();

    // xCrop + halfAnchorPointW + offsetLeft, yCrop + halfAnchorPointW + offsetTop,
    //        xCrop + halfAnchorPointW + cropWidth + offsetRight, yCrop + halfAnchorPointW + cropHeight + offsetBottom
    int prevOLeft = offsetLeft;
    int prevORight = offsetRight;
    int prevOTop = offsetTop;
    int prevOBottom = offsetBottom;

    if(anchorChoice == 0){
        offsetLeft = (x - xCrop - halfAnchorPointW);
        offsetTop = (y - yCrop - halfAnchorPointW);
    }
    else if(anchorChoice == 1){
        offsetRight = (x - xCrop - halfAnchorPointW - cropWidth);
        offsetTop = (y - yCrop - halfAnchorPointW);
    }
    else if(anchorChoice == 2){
        offsetLeft = (x - xCrop - halfAnchorPointW);
        offsetBottom = (y - yCrop - halfAnchorPointW - cropHeight);
    }
    else if(anchorChoice == 3){
        offsetRight = (x - xCrop - halfAnchorPointW - cropWidth);
        offsetBottom = (y - yCrop - halfAnchorPointW - cropHeight);
    }

    // Boundaries.
    // Left boundary.
    if(xCrop + offsetLeft < xCrop)
        offsetLeft = 0;

    if(xCrop + halfAnchorPointW + cropWidth + offsetRight < xCrop + anchorPointW + offsetLeft)
        offsetRight = prevORight;

    // Top boundary.
    if(yCrop + offsetTop < yCrop)
        offsetTop = 0;

    if(yCrop + halfAnchorPointW + cropHeight + offsetBottom < yCrop + anchorPointW + offsetTop)
        offsetBottom = prevOBottom;

    // Right boundary.
    if(xCrop + halfAnchorPointW + cropWidth + offsetRight > xCrop + halfAnchorPointW + cropWidth)
        offsetRight = 0;

    if(xCrop + anchorPointW + offsetLeft > xCrop + halfAnchorPointW + cropWidth + offsetRight)
        offsetLeft = prevOLeft;

    // Bottom boundary.
    if(yCrop + halfAnchorPointW + cropHeight + offsetBottom > yCrop + halfAnchorPointW + cropHeight)
        offsetBottom = 0;

    if(yCrop + anchorPointW + offsetTop > yCrop + halfAnchorPointW + cropHeight + offsetBottom)
        offsetTop = prevOTop;

    // End boundaries.

    return;
}

void createDarkBitmap(Bitmap processedBitmap){

    darkBitmap = Bitmap.createBitmap(processedBitmap.getWidth(), processedBitmap.getHeight(), Bitmap.Config.ARGB_8888);

    int substractValue = 220;

    for(int i = 0; i < processedBitmap.getWidth(); i++){
        for(int j = 0; j < processedBitmap.getHeight(); j++){
            int pixelToProcess = processedBitmap.getPixel(i, j);

            // Get component infos.
            int r = Color.red(pixelToProcess);
            int g = Color.green(pixelToProcess);
            int b = Color.blue(pixelToProcess);
            int alpha = Color.alpha(pixelToProcess);

            // Process component info.
            alpha -= substractValue;

            // alpha = alpha - substractValue;

            darkBitmap.setPixel(i, j, Color.argb(alpha, r, g, b));
        }
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {

    int action = event.getActionMasked();

    final String TAG = "!!!123";

    switch (action) {

        case MotionEvent.ACTION_DOWN:
            setAnchorAction(event);
            Log.d(TAG, "" + anchorChoice);
            return true;

        case MotionEvent.ACTION_MOVE:
            resizeRectangle(event);
            break;

        case MotionEvent.ACTION_UP:
            Log.d(TAG, "Action was UP");

            break;

        case MotionEvent.ACTION_CANCEL:
            Log.d(TAG, "Action was CANCEL");
            break;

        case MotionEvent.ACTION_OUTSIDE:
            Log.d(TAG, "Movement occurred outside bounds of current screen element");
            break;
    }

    return super.onTouchEvent(event);
}

@Override
public boolean onTouch(View v, MotionEvent event) {

    return super.onTouchEvent(event);
}
}