失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android 自定义View实现照片裁剪框与照片裁剪

Android 自定义View实现照片裁剪框与照片裁剪

时间:2020-04-03 02:07:00

相关推荐

Android 自定义View实现照片裁剪框与照片裁剪

大部分的软件,

但凡包含登录注册的,

基本都会有选择头像功能,

而其中做的比较有逼格的,

一般会有一个选择框可以裁剪照片。

本文所需要实现的就是这样一种有逼格的效果:

右上角加了个图片框,按下确定可以裁剪正方形区域里的图片并显示在右上角。

实现思路:

1:首先需要自定义一个ZoomImageView来显示我们需要的图片,这个View需要让图片能够以合适的位置展现在当前布局的图片展示区域内(合适的位置值的是:如果图片长度大于屏幕,则压缩图片长度至屏幕宽度,高度等比压缩并居中显示,如果图片高度大于屏幕,则压缩图片高度至屏幕高度,长度等比压缩并居中显示。);

2:然后需要实现这个拖动的框框,该框框实现的功能有四点:拖动、扩大缩小、触摸时显示基准线、截图。

首先是布局设计image_details.xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="55dp"android:background="#323441"><ImageButtonandroid:id="@+id/certification_returnbtn"android:layout_width="55dp"android:layout_height="55dp"android:background="@android:color/transparent"android:padding="15dp"android:scaleType="fitCenter"android:src="@drawable/topbar_returnbtn"/><TextViewandroid:layout_width="wrap_content"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:layout_toRightOf="@id/certification_returnbtn"android:gravity="center_vertical"android:text="裁剪图片"android:textColor="@android:color/white"android:textSize="20sp"/><!-- <ImageButtonandroid:layout_width="55dp"android:layout_height="55dp"android:layout_alignParentRight="true"android:layout_marginRight="10dp"android:background="@android:color/transparent"android:padding="16dp"android:scaleType="fitCenter"android:src="@drawable/ic_rotate_24dp"/>--><ImageViewandroid:id="@+id/testimg"android:layout_alignParentRight="true"android:layout_marginRight="10dp"android:layout_width="55dp"android:layout_height="55dp"/></RelativeLayout><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"><com.whale.nangua.pubuliuzhaopianqiang.ZoomImageViewandroid:id="@+id/zoom_image_view"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#303030"/><com.whale.nangua.pubuliuzhaopianqiang.ChoiceBorderViewandroid:id="@+id/zoom_choiceborder_view"android:layout_width="match_parent"android:layout_height="match_parent"/><Buttonandroid:id="@+id/image_details_subbtn"android:text="确定"android:background="@drawable/image_details_submitbtn_shape"android:layout_marginBottom="20dp"android:layout_width="180dp"android:layout_height="40dp"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"/></RelativeLayout></LinearLayout>

布局比较简单,两个View互相层叠。

自定义图片大小控制视图:ZoomImageView.java

代码注释很详细就不解释了。

package com.whale.nangua.pubuliuzhaopianqiang;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Matrix;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/*** Created by nangua on /7/20.*/public class ZoomImageView extends View {/*** 初始化状态常量*/public static final int STATUS_INIT = 1;/*** 用于对图片进行移动和缩放变换的矩阵*/private Matrix matrix = new Matrix();/*** 待展示的Bitmap对象*/private Bitmap sourceBitmap;/*** 记录当前操作的状态,可选值为STATUS_INIT、STATUS_ZOOM_OUT、STATUS_ZOOM_IN和STATUS_MOVE*/private int currentStatus;/*** ZoomImageView控件的宽度*/private int width;/*** ZoomImageView控件的高度*/private int height;/*** ZoomImageView构造函数,将当前操作状态设为STATUS_INIT。** @param context* @param attrs*/public ZoomImageView(Context context, AttributeSet attrs) {super(context, attrs);currentStatus = STATUS_INIT;}/*** 将待展示的图片设置进来。** @param bitmap 待展示的Bitmap对象*/public void setImageBitmap(Bitmap bitmap) {sourceBitmap = bitmap;invalidate();}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);if (changed) {// 分别获取到ZoomImageView的宽度和高度width = getWidth();height = getHeight();}}/*** 根据currentStatus的值来决定对图片进行什么样的绘制操作。*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);initBitmap(canvas);canvas.drawBitmap(sourceBitmap, matrix, null);}float translateY;//Y轴偏移量float translateX;//X轴偏移量/*** @param canvas* @autohr nangua* 对图片进行初始化操作,包括让图片居中,以及当图片大于屏幕宽高时对图片进行压缩。* <p>* 1.当图片宽度大于显示宽度、图片高度小于显示宽度:* 设置图片宽度为显示宽度,高度缩放*(图片宽度/显示宽度)* <p>* 2.当图片宽度小于显示宽度、图片高度大于显示宽度:* 设置图片高度为显示高度,宽度缩放*(图片高度/显示高 度)* <p>* 3.当图片宽度大于显示宽度,图片高度大于显示宽度:* 选取差度更大的一边进行压缩,另一边等比缩放* <p>* 4.当图片宽度小于显示宽度,图片高度小于显示宽度:* 选取差度更大的一边进行压缩,另一边等比缩放*/private void initBitmap(Canvas canvas) {if (sourceBitmap != null) {matrix.reset(); //重置矩阵int bitmapWidth = sourceBitmap.getWidth(); //得到源图片宽int bitmapHeight = sourceBitmap.getHeight(); //得到源图片高//如果原图片大小大于控件宽高if (bitmapWidth > width || bitmapHeight > height) {//如果宽和高都比屏幕大,选择差度大的一边缩小,另一边等比缩小if (bitmapWidth > width && bitmapHeight > height) {int distanceX = Math.abs(width - bitmapWidth);int distanceY = Math.abs(height - bitmapHeight);float ratio;//找出差值大的一边,进行缩小if (distanceX >= distanceY) {ratio = width / (bitmapWidth * 1.0f);matrix.postScale(ratio, ratio);//此时横轴铺满,只需要对竖轴进行平移translateY = (height - sourceBitmap.getHeight() * ratio) / 2f;matrix.postTranslate(0, translateY);} else {ratio = height / (bitmapHeight * 1.0f);matrix.postScale(ratio, ratio);//此时竖轴铺满,只需要对横轴进行平移translateX = (width - sourceBitmap.getWidth() * ratio) / 2f;matrix.postTranslate(translateX, 0); //在横纵轴上进行平移}//当图片宽度大于显示宽度、图片高度小于显示宽度:} else if (bitmapWidth > width) {// 当图片宽度大于屏幕宽度时,将图片等比例压缩,使它可以完全显示出来float ratio = width / (bitmapWidth * 1.0f); //压缩比例matrix.postScale(ratio, ratio);translateY = (height - (bitmapHeight * ratio)) / 2f;// 在纵坐标方向上进行偏移,以保证图片居中显示matrix.postTranslate(0, translateY);//当图片宽度小于显示宽度、图片高度大于显示宽度:} else if (bitmapHeight > height) {// 当图片高度大于屏幕高度时,将图片等比例压缩,使它可以完全显示出来float ratio = height / (bitmapHeight * 1.0f); //压缩比例matrix.postScale(ratio, ratio);translateX = (width - (bitmapWidth * ratio)) / 2f;// 在横坐标方向上进行偏移,以保证图片居中显示matrix.postTranslate(translateX, 0);}} else {// 当图片的宽高都小于屏幕宽高时,选择差度小的一边铺满,另一边等比扩大//计算长和宽的差值int distanceX = Math.abs(width - bitmapWidth);int distanceY = Math.abs(height - bitmapHeight);float ratio;//找出差值小的一边,进行扩大if (distanceX <= distanceY) {ratio = width / (bitmapWidth * 1.0f);matrix.postScale(ratio, ratio);//此时横轴铺满,只需要对竖轴进行平移translateY = (height - sourceBitmap.getHeight() * ratio) / 2f;matrix.postTranslate(0, translateY);} else {ratio = height / (bitmapHeight * 1.0f);matrix.postScale(ratio, ratio);//此时竖轴铺满,只需要对横轴进行平移translateX = (width - sourceBitmap.getWidth() * ratio) / 2f;matrix.postTranslate(translateX, 0); //在横纵轴上进行平移}}//进行绘制canvas.drawBitmap(sourceBitmap, matrix, null);}}}

重点来了,相册选取框视图:ChoiceBorderView.java

package com.whale.nangua.pubuliuzhaopianqiang;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.Toast;/*** 相册选择框的View* Created by nangua on /7/21.*/public class ChoiceBorderView extends View {private int scale = (int) this.getResources().getDisplayMetrics().density; //屏幕像素密度private float borderHeight; //总高private float borderWith; //总宽private float borderLength = 200 * scale; //边框长度private int RECT_BORDER_WITH = 3 * scale; //长方形框框粗private int RECT_CORNER_WITH = 6 * scale; //四个角的粗private int RECT_CORNER_HEIGHT = 20 * scale; //四个角的长度//四个点坐标private static float[][] four_corner_coordinate_positions;private static int NOW_MOVE_STATE = 1; //移动状态,默认为1,Y轴=1,X轴=2private static boolean MOVE_OR_ZOOM_STATE = true; //移动或缩放状态, true 为移动public ChoiceBorderView(Context context, AttributeSet attrs) {super(context, attrs);this.setFocusable(true);this.setFocusableInTouchMode(true);init();}/*** 初始化布局* @param changed* @param left* @param top* @param right* @param bottom*/@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);borderHeight = this.getHeight();borderWith = this.getWidth();//初始化四个点的坐标four_corner_coordinate_positions = new float[][]{{(borderWith - borderLength) / 2, (borderHeight - borderLength) / 2}, //左上{(borderWith + borderLength) / 2, (borderHeight - borderLength) / 2}, //右上{(borderWith - borderLength) / 2, (borderHeight + borderLength) / 2}, //左下{(borderWith + borderLength) / 2, (borderHeight + borderLength) / 2}, //右上};}private void init() {}private int temp1 = (RECT_CORNER_WITH - RECT_BORDER_WITH) / 2; //长方形的粗半距private int temp2 = (RECT_CORNER_WITH + RECT_BORDER_WITH) / 2; //四个角的粗半距/*** RECT_CORNER_WITH = 6* RECT_BORDER_WITH =3** @param canvas*/@Overrideprotected void onDraw(Canvas canvas) {Paint paintRect = new Paint(); //初始化画笔//画边框的画笔paintRect.setColor(getResources().getColor(R.color.bordercolor)); //颜色paintRect.setStrokeWidth(RECT_BORDER_WITH); //宽度paintRect.setAntiAlias(true); //抗锯齿paintRect.setStyle(Paint.Style.STROKE); //设置空心canvas.drawRect(four_corner_coordinate_positions[0][0],four_corner_coordinate_positions[0][1],four_corner_coordinate_positions[3][0],four_corner_coordinate_positions[3][1], paintRect);//画四个角的画笔paintRect.setColor(Color.WHITE);paintRect.setStrokeWidth(RECT_CORNER_WITH);paintRect.setAntiAlias(true);//左上角的两根canvas.drawLine(four_corner_coordinate_positions[0][0] - temp2,four_corner_coordinate_positions[0][1] - temp1,four_corner_coordinate_positions[0][0] - temp1 + RECT_CORNER_HEIGHT,four_corner_coordinate_positions[0][1] - temp1,paintRect);canvas.drawLine(four_corner_coordinate_positions[0][0] - temp1,four_corner_coordinate_positions[0][1] - temp2,four_corner_coordinate_positions[0][0] - temp1,four_corner_coordinate_positions[0][1] - temp1 + RECT_CORNER_HEIGHT,paintRect);//左下角的两根canvas.drawLine(four_corner_coordinate_positions[2][0] - temp2,four_corner_coordinate_positions[2][1] + temp1,four_corner_coordinate_positions[2][0] - temp1 + RECT_CORNER_HEIGHT,four_corner_coordinate_positions[2][1] + temp1,paintRect);canvas.drawLine(four_corner_coordinate_positions[2][0] - temp1,four_corner_coordinate_positions[2][1] + temp1,four_corner_coordinate_positions[2][0] - temp1,four_corner_coordinate_positions[2][1] + temp1 - RECT_CORNER_HEIGHT,paintRect);//右上角的两根canvas.drawLine(four_corner_coordinate_positions[1][0] + temp1,four_corner_coordinate_positions[1][1] - temp1,four_corner_coordinate_positions[1][0] + temp1 - RECT_CORNER_HEIGHT,four_corner_coordinate_positions[1][1] - temp1,paintRect);canvas.drawLine(four_corner_coordinate_positions[1][0] + temp1,four_corner_coordinate_positions[1][1] - temp2,four_corner_coordinate_positions[1][0] + temp1,four_corner_coordinate_positions[1][1] - temp1 + RECT_CORNER_HEIGHT, paintRect);//右下角的两根canvas.drawLine(four_corner_coordinate_positions[3][0] + temp2,four_corner_coordinate_positions[3][1] + temp1,four_corner_coordinate_positions[3][0] + temp1 - RECT_CORNER_HEIGHT,four_corner_coordinate_positions[3][1] + temp1,paintRect);canvas.drawLine(four_corner_coordinate_positions[3][0] + temp1,four_corner_coordinate_positions[3][1] + temp1,four_corner_coordinate_positions[3][0] + temp1,four_corner_coordinate_positions[3][1] + temp1 - RECT_CORNER_HEIGHT,paintRect);//画扫描线if (IF_SCANNING_SHOW) {paintRect.setColor(Color.WHITE);paintRect.setStrokeWidth(1);paintRect.setAntiAlias(true);paintRect.setStyle(Paint.Style.STROKE);//共四根线//竖1canvas.drawLine(four_corner_coordinate_positions[0][0] + borderLength / 3,four_corner_coordinate_positions[0][1] + temp1,four_corner_coordinate_positions[2][0] + borderLength / 3,four_corner_coordinate_positions[2][1] - temp1,paintRect);//竖2canvas.drawLine(four_corner_coordinate_positions[1][0] - borderLength / 3,four_corner_coordinate_positions[1][1] + temp1,four_corner_coordinate_positions[3][0] - borderLength / 3,four_corner_coordinate_positions[3][1] - temp1,paintRect);//横1canvas.drawLine(four_corner_coordinate_positions[0][0] + temp1,four_corner_coordinate_positions[0][1] + borderLength / 3,four_corner_coordinate_positions[1][0] - temp1,four_corner_coordinate_positions[1][1] + borderLength / 3,paintRect);//横2canvas.drawLine(four_corner_coordinate_positions[2][0] + temp1,four_corner_coordinate_positions[2][1] - borderLength / 3,four_corner_coordinate_positions[3][0] - temp1,four_corner_coordinate_positions[3][1] - borderLength / 3,paintRect);}}private boolean IF_SCANNING_SHOW = false;private int lastX = 0; //上次按下的X位置private int lastY = 0; //上次按下的Y位置private int offsetX = 0; //X轴偏移量private int offsetY = 0; //Y轴偏移量static int point = -1;// 用户按下的点private int POINT_STATE = -1; //判断用户是缩小还是放大 0放大 1缩小@Overridepublic boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:IF_SCANNING_SHOW = true;//显示扫描线if (isInTheCornerCircle(event.getX(), event.getY()) != -1) {//开始缩放操作MOVE_OR_ZOOM_STATE = false; //设置false为缩放状态point = isInTheCornerCircle(event.getX(), event.getY());}lastX = x;lastY = y;invalidate();break;case MotionEvent.ACTION_MOVE:offsetX = x - lastX;offsetY = y - lastY;//判断当前是扩大还是缩小操作judgementXandY();//限定移动范围//移动状态:只有在移动状态下才能移动if (MOVE_OR_ZOOM_STATE) {getoffsetXandoffsetY();//四个点的坐标信息也要随之改变for (int i = 0; i < four_corner_coordinate_positions.length; i++) {four_corner_coordinate_positions[i][0] += offsetX;four_corner_coordinate_positions[i][1] += offsetY;//更新回调接口onImageDetailsSizeChanggedl.onBorderSizeChangged((int) four_corner_coordinate_positions[0][0],(int) four_corner_coordinate_positions[0][1],(int) borderLength);invalidate();}// this.scrollBy(-offsetX, -offsetY); //这里弃用,后面改用了四点坐标移动代替背景移动}//在缩放状态下else {//按住某一个点,该点的坐标改变,其他2个点坐标跟着改变,对点坐标不变max = Math.abs(offsetX) >= Math.abs(offsetY) ? Math.abs(offsetX) : Math.abs(offsetY);//只有在扩大操作才进行边界范围判断if (POINT_STATE == 0) {getoffsetXandoffsetY(); //边界范围判断}//缩小操作时进行边界不能太小判断else if (POINT_STATE == 1) {//如果边长+max太小,直接返回if (borderLength - max <= RECT_CORNER_HEIGHT*2-temp2) {max = 0;}}//改变坐标changgeFourCoodinatePosition(point, offsetX, offsetY);//更新边长notifyNowborderLength();//更新回调接口onImageDetailsSizeChanggedl.onBorderSizeChangged((int) four_corner_coordinate_positions[0][0],(int) four_corner_coordinate_positions[0][1],(int) borderLength);invalidate();}lastX = x;lastY = y;break;case MotionEvent.ACTION_UP:IF_SCANNING_SHOW = false; //不显示扫描线MOVE_OR_ZOOM_STATE = true; //回归为默认的移动状态invalidate();break;}return true;}/*** 更新矩形框边长的方法*/private void notifyNowborderLength() {float a = four_corner_coordinate_positions[0][0];float b = four_corner_coordinate_positions[0][1];float c = four_corner_coordinate_positions[1][0];float d = four_corner_coordinate_positions[1][1];float temp1 = (float) Math.pow(a - c, 2);float temp2 = (float) Math.pow(b - d, 2);borderLength = (float) Math.sqrt(temp1 + temp2);}/*** POINT_STATE 为0放大, 1缩小*/private void judgementXandY() {switch (point) {case 0:if ((offsetX <= 0 && offsetY <= 0) || (offsetX <= 0 && offsetY >= 0)) {POINT_STATE = 0;//扩大} else {POINT_STATE = 1;//缩小}break;case 1:if ((offsetX >= 0 && offsetY <= 0) || (offsetX >= 0 && offsetY >= 0)) {POINT_STATE = 0;} else {POINT_STATE = 1;}break;case 2:if ((offsetX <= 0 && offsetY >= 0) || (offsetX <= 0 && offsetY <= 0)) {POINT_STATE = 0;} else {POINT_STATE = 1;}break;case 3:if ((offsetX >= 0 && offsetY >= 0) || (offsetX >= 0 && offsetY <= 0)) {POINT_STATE = 0;} else {POINT_STATE = 1;}break;}}/*** 防止X和Y溢出边界的算法*/private void getoffsetXandoffsetY() {//如果是移动状态if (MOVE_OR_ZOOM_STATE) {if ((four_corner_coordinate_positions[0][0] + offsetX <= 0) ||(four_corner_coordinate_positions[1][0] + offsetX >= borderWith)) {offsetX = 0;}if ((four_corner_coordinate_positions[0][1] + offsetY <= 0) ||(four_corner_coordinate_positions[2][1] + offsetY >= borderHeight)) {offsetY = 0;}}//如果是缩放状态else {switch (point) {case 0:if ((four_corner_coordinate_positions[0][0] - max <= 0) ||(four_corner_coordinate_positions[0][1] - max <= 0)) {max = 0;}break;case 1:if ((four_corner_coordinate_positions[1][0] + max >= borderWith) ||(four_corner_coordinate_positions[1][1] - max <= 0)) {max = 0;}break;case 2:if ((four_corner_coordinate_positions[2][0] - max <= 0) ||(four_corner_coordinate_positions[2][1] + max >= borderHeight)) {max = 0;}break;case 3:if ((four_corner_coordinate_positions[3][0] + max >= borderWith) ||(four_corner_coordinate_positions[3][1] + max >= borderHeight)) {max = 0;}break;}}}static int max;/*** 扩大缩放方法* 根据用户传来的点改变其他点的坐标* 按住某一个点,该点的坐标改变,其他2个点坐标跟着改变,对点坐标不变* 点阵示意:* 0 1* 2 3** @param point 用户按的点* @param offsetX X轴偏移量* @param offsetY Y轴偏移量*/private void changgeFourCoodinatePosition(int point, int offsetX, int offsetY) {switch (point) {case 0:if (offsetX > 0 && offsetY < 0) {//变化0点的位置 suoxiaofour_corner_coordinate_positions[0][0] += max;four_corner_coordinate_positions[0][1] += max;//变化1点的Y轴four_corner_coordinate_positions[1][1] += max;//变化2点的X轴four_corner_coordinate_positions[2][0] += max;} else if (offsetX < 0 && offsetY > 0) {//变化0点的位置 kuodafour_corner_coordinate_positions[0][0] -= max;four_corner_coordinate_positions[0][1] -= max;//变化1点的Y轴four_corner_coordinate_positions[1][1] -= max;//变化2点的X轴four_corner_coordinate_positions[2][0] -= max;} else if (offsetX < 0 && offsetY < 0) {//变化0点的位置 kuodafour_corner_coordinate_positions[0][0] -= max;four_corner_coordinate_positions[0][1] -= max;//变化1点的Y轴four_corner_coordinate_positions[1][1] -= max;//变化2点的X轴four_corner_coordinate_positions[2][0] -= max;} else if (offsetX > 0 && offsetY > 0) {//变化0点的位置 suoxiaofour_corner_coordinate_positions[0][0] += max;four_corner_coordinate_positions[0][1] += max;//变化1点的Y轴four_corner_coordinate_positions[1][1] += max;//变化2点的X轴four_corner_coordinate_positions[2][0] += max;}break;case 1:if (offsetX > 0 && offsetY < 0) {//变化1点的位置four_corner_coordinate_positions[1][0] += max;four_corner_coordinate_positions[1][1] -= max;//变化0点的Y轴four_corner_coordinate_positions[0][1] -= max;//变化3点的X轴four_corner_coordinate_positions[3][0] += max;} else if (offsetX < 0 && offsetY > 0) {//变化1点的位置four_corner_coordinate_positions[1][0] -= max;four_corner_coordinate_positions[1][1] += max;//变化0点的Y轴four_corner_coordinate_positions[0][1] += max;//变化3点的X轴four_corner_coordinate_positions[3][0] -= max;} else if (offsetX < 0 && offsetY < 0) {//变化1点的位置four_corner_coordinate_positions[1][0] -= max;four_corner_coordinate_positions[1][1] += max;//变化0点的Y轴four_corner_coordinate_positions[0][1] += max;//变化3点的X轴four_corner_coordinate_positions[3][0] -= max;} else if (offsetX > 0 && offsetY > 0) {//变化1点的位置four_corner_coordinate_positions[1][0] += max;four_corner_coordinate_positions[1][1] -= max;//变化0点的Y轴four_corner_coordinate_positions[0][1] -= max;//变化3点的X轴four_corner_coordinate_positions[3][0] += max;}break;case 2:if (offsetX > 0 && offsetY < 0) {//变化2点的位置 suoxiaofour_corner_coordinate_positions[2][0] += max;four_corner_coordinate_positions[2][1] -= max;//变化0点的X轴four_corner_coordinate_positions[0][0] += max;//变化3点的Y轴four_corner_coordinate_positions[3][1] -= max;} else if (offsetX < 0 && offsetY > 0) {//变化2点的位置 kuodafour_corner_coordinate_positions[2][0] -= max;four_corner_coordinate_positions[2][1] += max;//变化0点的X轴four_corner_coordinate_positions[0][0] -= max;//变化3点的Y轴four_corner_coordinate_positions[3][1] += max;} else if (offsetX < 0 && offsetY < 0) {//变化2点的位置 kuodafour_corner_coordinate_positions[2][0] -= max;four_corner_coordinate_positions[2][1] += max;//变化0点的X轴four_corner_coordinate_positions[0][0] -= max;//变化3点的Y轴four_corner_coordinate_positions[3][1] += max;} else if (offsetX > 0 && offsetY > 0) {//变化2点的位置 suoxiaofour_corner_coordinate_positions[2][0] += max;four_corner_coordinate_positions[2][1] -= max;//变化0点的X轴four_corner_coordinate_positions[0][0] += max;//变化3点的Y轴four_corner_coordinate_positions[3][1] -= max;}break;case 3:if (offsetX > 0 && offsetY < 0) {//变化3点的位置 kuodafour_corner_coordinate_positions[3][0] += max;four_corner_coordinate_positions[3][1] += max;//变化1点的X轴four_corner_coordinate_positions[1][0] += max;//变化2点的Y轴four_corner_coordinate_positions[2][1] += max;} else if (offsetX < 0 && offsetY > 0) {//变化3点的位置 suoxiaofour_corner_coordinate_positions[3][0] -= max;four_corner_coordinate_positions[3][1] -= max;//变化1点的X轴four_corner_coordinate_positions[1][0] -= max;//变化2点的Y轴four_corner_coordinate_positions[2][1] -= max;} else if (offsetX < 0 && offsetY < 0) {//变化3点的位置 suoxiaofour_corner_coordinate_positions[3][0] -= max;four_corner_coordinate_positions[3][1] -= max;//变化1点的X轴four_corner_coordinate_positions[1][0] -= max;//变化2点的Y轴four_corner_coordinate_positions[2][1] -= max;} else if (offsetX > 0 && offsetY > 0) {//变化3点的位置 kuodafour_corner_coordinate_positions[3][0] += max;four_corner_coordinate_positions[3][1] += max;//变化1点的X轴four_corner_coordinate_positions[1][0] += max;//变化2点的Y轴four_corner_coordinate_positions[2][1] += max;}break;}}/*** 判断按下的点在圆圈内** @param x 按下的X坐标* @param y 按下的Y坐标* @return 返回按到的是哪个点, 没有则返回-1* 点阵示意:* 0 1* 2 3*/private int isInTheCornerCircle(float x, float y) {for (int i = 0; i < four_corner_coordinate_positions.length; i++) {float a = four_corner_coordinate_positions[i][0];float b = four_corner_coordinate_positions[i][1];float temp1 = (float) Math.pow((x - a), 2);float temp2 = (float) Math.pow((y - b), 2);if (((float) RECT_CORNER_HEIGHT) >= Math.sqrt(temp1 + temp2)) {return i;}}return -1;}public interface onImageDetailsSizeChangged {void onBorderSizeChangged(int x, int y, int length);}public onImageDetailsSizeChangged onImageDetailsSizeChanggedl;public void setonImageDetailsSizeChangged(onImageDetailsSizeChangged onImageDetailsSizeChangged) {this.onImageDetailsSizeChanggedl = onImageDetailsSizeChangged;}}

为了实现这个相框我写了557行,是的其中有大量写的很蠢很重复的代码,大可以花点时间进行优化(逃)。

实现的思路是这样的:首先要确定四个点的位置,然后根据这四个点的位置在onDraw方法中画出相框的边框,四个角框,再在onTouchListner中通过计算按下的坐标偏移量改变四个点的位置从而改变onDraw中整个相框视图的位置。

但是难点在于手势的判断以及不同情况下缩放与扩大的边界值溢出问题,这个问题大概搞了一下午。。。很烧脑

但是总的来说加强了对自定义视图的理解,发现了一些解决问题的新思路。

嗯,继续努力。

如果觉得《Android 自定义View实现照片裁剪框与照片裁剪》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。