一、简陋的自定义view(SurfaceView绘制可缩放、旋转、移动的简单视图)
package com.ahtelit.zbv.myapplication;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Created by Administrator on 2018/4/19.
* qzx
*/
public class SimpleTransformView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private boolean isDestroy;
private SurfaceHolder mSurfaceHolder;
private Canvas mCanvas;
private Paint mPaint;
private RectF rectF;
private float rectf_range_width = 200.0f;
private float rectf_range_height = 200.0f;
private static final float TIPS_MARGIN = 80.0f;
private static final float TIPS_RANGE = 100.0f;
private static final float DASH_RANGE = 10.0F;
private static final float Circle_Radius = 20.0f;
private float side_left;
private float side_top;
private float pad_width;
private float pad_height;
private int drawType = 0;
private static final int TYPE_TEXT = 0;
private static final int TYPE_IMG = 1;
public SimpleTransformView(Context context) {
this(context, null);
}
public SimpleTransformView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SimpleTransformView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initConfig();
}
private void initConfig() {
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
mPaint = new Paint();
mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
setKeepScreenOn(true);
setFocusable(true);
setFocusableInTouchMode(true);
rectF = new RectF(100, 100, 100 + rectf_range_width, 100 + rectf_range_height);
side_left = rectF.left;
side_top = rectF.top;
DisplayMetrics dm = getResources().getDisplayMetrics();
pad_width = dm.widthPixels;
pad_height = dm.heightPixels;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
new Thread(this).start();
isDestroy = false;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isDestroy = true;
}
@Override
public void run() {
while (!isDestroy) {
try {
mCanvas = mSurfaceHolder.lockCanvas();
drawUI();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mCanvas != null)
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
private String testText = "七子笑";
private String tipsText = "旋转";
private float hadRotateAngle = 0;
private float rotateAngle = 0;
private String tipsDegree = 0 + "°";
private float wordSize = 20.0f;
private void drawUI() {
if (drawType == TYPE_TEXT) {
mCanvas.drawColor(Color.WHITE);
mCanvas.save();
mCanvas.rotate(rotateAngle, rectF.centerX(), rectF.centerY());
commonView();
mCanvas.restore();
}
}
private void commonView() {
mPaint.setColor(Color.GRAY);
mPaint.setStyle(Paint.Style.FILL);
mCanvas.drawRect(rectF, mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(wordSize);
mCanvas.drawText(testText, rectF.left + rectF.width() / 2, rectF.top + rectF.height() / 2, mPaint);
if (isShowScaleView) {
mPaint.setColor(Color.RED);
mCanvas.drawCircle(rectF.left, rectF.top, Circle_Radius, mPaint);
mCanvas.drawCircle(rectF.left, rectF.bottom, Circle_Radius, mPaint);
mCanvas.drawCircle(rectF.right, rectF.top, Circle_Radius, mPaint);
mCanvas.drawCircle(rectF.right, rectF.bottom, Circle_Radius, mPaint);
}
if (isShowRotateView) {
mPaint.setColor(Color.BLACK);
mCanvas.drawRect(rectF.left, rectF.top - TIPS_MARGIN - TIPS_RANGE, rectF.right, rectF.top - TIPS_MARGIN, mPaint);
mPaint.setColor(Color.WHITE);
Paint.FontMetrics fontMetrics = new Paint.FontMetrics();
float baseLine = (rectF.top * 2 - 2 * TIPS_MARGIN - TIPS_RANGE - (fontMetrics.top + fontMetrics.bottom)) / 2;
tipsDegree = rotateAngle + "°";
mCanvas.drawText(tipsDegree, rectF.left + rectF.width() / 2, baseLine, mPaint);
mPaint.setColor(Color.GRAY);
mPaint.setPathEffect(new DashPathEffect(new float[]{
15, 3}, 0));
mCanvas.drawLine(rectF.left + rectF.width() / 2, rectF.top, rectF.left + rectF.width() / 2, rectF.top - TIPS_MARGIN, mPaint);
} else {
mPaint.setColor(Color.GRAY);
mCanvas.drawRect(rectF.left, rectF.top - TIPS_MARGIN - TIPS_RANGE, rectF.right, rectF.top - TIPS_MARGIN, mPaint);
mPaint.setColor(Color.WHITE);
Paint.FontMetrics fontMetrics = new Paint.FontMetrics();
float baseLine = (rectF.top * 2 - 2 * TIPS_MARGIN - TIPS_RANGE - (fontMetrics.top + fontMetrics.bottom)) / 2;
mCanvas.drawText(tipsText, rectF.left + rectF.width() / 2, baseLine, mPaint);
}
}
private float downX;
private float downY;
private boolean isCanMove = false;
private boolean isShowScaleView = false;
private boolean isCanScale = false;
private boolean isCanRotate = false;
private boolean isShowRotateView = false;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (hadRotateAngle != 0) {
Log.d("zbv", "右旋转角=" + hadRotateAngle);
float currentLocations[] = getBeforeViewLocation(hadRotateAngle, event.getX(), event.getY());
downX = currentLocations[0];
downY = currentLocations[1];
} else {
downX = event.getX();
downY = event.getY();
}
if (isShowRotateView) {
if (downX > (rectF.left + rectF.width() / 2 - DASH_RANGE) && downX < (rectF.left + rectF.width() / 2 + DASH_RANGE)
&& downY < rectF.top && (downY > rectF.top - TIPS_MARGIN)) {
Log.d("zbv", "触碰到虚线了");
isCanRotate = true;
}
} else {
if (rectF.contains(downX, downY)) {
Log.d("zbv", "在绘制范围内可以显示缩放视图");
isShowScaleView = true;
isCanMove = true;
} else {
Log.d("zbv", "绘制区域外隐藏缩放视图");
isShowScaleView = false;
}
if (downX > rectF.left && downX < rectF.right && downY > (rectF.top - TIPS_MARGIN - TIPS_RANGE)
&& downY < (rectF.top - TIPS_MARGIN)) {
Log.d("zbv", "触摸到旋转区域");
isShowRotateView = true;
isCanMove = false;
}
if (((rectF.left - Circle_Radius) < downX && downX < (rectF.left + Circle_Radius)
&& (rectF.top - Circle_Radius) < downY && downY < (rectF.top + Circle_Radius))
|| ((rectF.left - Circle_Radius) < downX && downX < (rectF.left + Circle_Radius)
&& (rectF.bottom - Circle_Radius) < downY && downY < (rectF.bottom + Circle_Radius))
|| ((rectF.right - Circle_Radius) < downX && downX < (rectF.right + Circle_Radius)
&& (rectF.top - Circle_Radius) < downY && downY < (rectF.top + Circle_Radius))
|| ((rectF.right - Circle_Radius) < downX && downX < (rectF.right + Circle_Radius)
&& (rectF.bottom - Circle_Radius) < downY && downY < (rectF.bottom + Circle_Radius))) {
Log.d("zbv", "触摸到要缩放的视图区域了");
isCanScale = true;
isCanMove = false;
downX=event.getX();
downY=event.getY();
}
}
break;
case MotionEvent.ACTION_MOVE:
if (isCanMove) {
if (!rectF.contains(event.getX(), event.getY())) {
rectF.left = event.getX();
rectF.top = event.getY();
rectF.right = rectF.left + rectf_range_width;
rectF.bottom = rectF.top + rectf_range_height;
side_left = rectF.left;
side_top = rectF.top;
} else {
Log.d("zbv", "移动手指仍在绘制视图");
}
}
if (isCanScale) {
rectF.left = side_left;
rectF.left += (event.getX() - downX);
rectf_range_width = rectF.right - rectF.left;
rectF.top = side_top;
rectF.top += (event.getY() - downY);
rectf_range_height = rectF.bottom - rectF.top;
}
if (isCanRotate) {
float angle_1 = (float) Math.atan2(downY - (rectF.top + rectF.height() / 2), downX - (rectF.left + rectF.width() / 2));
float angle_2 = (float) Math.atan2(event.getY() - (rectF.top + rectF.height() / 2), event.getX() - (rectF.left + rectF.width() / 2));
int jiaodu_1 = (int) Math.toDegrees(angle_1);
int jiaodu_2 = (int) Math.toDegrees(angle_2);
rotateAngle = jiaodu_2 - jiaodu_1;
if (rotateAngle > 180.0f) {
rotateAngle -= 360.0f;
}
}
break;
case MotionEvent.ACTION_UP:
if (isCanScale) {
isCanScale = false;
}
if (isCanRotate) {
isCanRotate = false;
isShowRotateView = false;
hadRotateAngle = rotateAngle;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
}
return true;
}
private float[] getBeforeViewLocation(float angle, float dot_x, float dot_y) {
float jiaodu = -angle;
float[] locations = new float[2];
double arcValue = Math.toRadians(jiaodu);
float sin = (float) Math.sin(arcValue);
float cos = (float) Math.cos(arcValue);
locations[0] = (dot_x - (rectF.left + rectF.width() / 2)) * cos - (dot_y - (rectF.top + rectF.height() / 2)) * sin + rectF.left + rectF.width() / 2;
locations[1] = (dot_y - (rectF.top + rectF.height() / 2)) * cos + (dot_x - (rectF.left + rectF.width() / 2)) * sin + rectF.top + rectF.height() / 2;
return locations;
}
/**
* 公开绘制类型的方法:
* 文本---文本
* 图片---资源图
*/
public int getDrawType(int type) {
if (type == TYPE_TEXT) {
drawType = TYPE_TEXT;
} else if (type == TYPE_IMG) {
drawType = TYPE_IMG;
}
return 0;
}
}
二、优化的可操作子视图平移、旋转、复制、删除、编辑等操作
1、容器试图TestLayout
package com.ahtelit.zbv.vphandler;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.icu.text.UnicodeSetSpanner;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.ahtelit.zbv.vphandler.zbvTools.QZXTools;
import java.security.acl.LastOwnerException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2018/4/25.
* qzx
*/
public class TestLayout extends ViewGroup implements View.OnTouchListener, CustomBGView.CustomInterface {
private Boolean isShowActivtiy = false;
public void setShowActivtiy(Boolean showActivtiy) {
isShowActivtiy = showActivtiy;
}
private Context mContext;
private int type;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
private int touch_view_left;
private int touch_view_right;
private int touch_view_top;
private int touch_view_bottom;
private int touch_view_width;
private int touch_view_height;
private static final int TRANSLATE = 0;
private static final int SCALE = 1;
private static final int ROTATE = 2;
private static final int EDITMODE = 3;
private static final int COPY = 4;
private static final int DEL = 5;
private View touchView;
public void setTouchView(View touchView) {
this.touchView = touchView;
}
private CustomBGView cus_view;
/**
* key是int类型,value是int[]类型
* 用于