一、簡陋的自定義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;//canvas繪製矩形有兩種:一種是int的還有就是這個float
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;//tips的矩形高度
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 side_right;
// private float side_bottom;
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);
// mPaint.setStyle(Paint.Style.STROKE);//描邊繪製
//保持常亮
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;
// side_right=rectF.left+RECTF_RANGE;
// side_bottom=rectF.top+RECTF_RANGE;
//獲取手機屏幕大小
DisplayMetrics dm = getResources().getDisplayMetrics();
pad_width = dm.widthPixels;
pad_height = dm.heightPixels;
}
// @TargetApi(Build.VERSION_CODES.LOLLIPOP)
// public SimpleTransformView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
// super(context, attrs, defStyleAttr, defStyleRes);
// }
@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);//清屏操作
// if (isCanRotate) {
mCanvas.save();
/*
如果不設置旋轉點默認是起始位置,可能使(0,0)
並且Canvas的旋轉都是數學座標系的Y軸向上的爲其實0度旋轉
--->據說旋轉的是畫布,視圖屬性還是在原來的位置的
*/
mCanvas.rotate(rotateAngle, rectF.centerX(), rectF.centerY());
commonView();
mCanvas.restore();
// } else {
// commonView();
// }
/*所以fontMetrics的bottom是正數=bottom-baseline;的top是負數=top-baseline
除了fontMetrics.leading是負數=top-ascent,其餘的都是和baseline掛鉤
*/
// float baseline=(side_top+side_bottom-(fontMetrics.bottom+fontMetrics.top))/2;
//通過FontMetrics的baseline繪製
// mCanvas.drawText(testText,rectF.centerX(),baseline,mPaint);
}
}
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);//繪製在x,y虛擬矩形中間
// Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
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 static final float INVALID_RANGE = 10;//設置無效的範圍點
private float downX;//觸摸點的起始位置-X
private float downY;//觸摸點的起始位置-Y
private boolean isCanMove = false;
private boolean isShowScaleView = false;//是否顯示可縮放的view
private boolean isCanScale = false;
private boolean isCanRotate = false;
private boolean isShowRotateView = false;//是否顯示可旋轉的view
// private boolean isHadRotateDegree = 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();
}
// if (event.getX() > (rectF.left + rectF.width() / 2 - DASH_RANGE) && event.getX() < (rectF.left + rectF.width() / 2 + DASH_RANGE)
// && event.getY() < rectF.top && (event.getY() > rectF.top + TIPS_MARGIN)) {
// Log.d("zbv", "觸碰到虛線了");
// isCanRotate = true;
// }
}
break;
case MotionEvent.ACTION_MOVE:
if (isCanMove) {
if (!rectF.contains(event.getX(), event.getY())) {
// Log.d("zbv", "移動手指出了繪製視圖"+rectf_range_width);
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;
// Log.d("zbv","scale of rectLeft="+rectF.left+";width="+rectf_range_width);
rectF.top = side_top;
rectF.top += (event.getY() - downY);
rectf_range_height = rectF.bottom - rectF.top;
// Log.d("zbv","scale of rectLeft="+rectF.right+";height="+rectf_range_height);
}
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;
// Log.d("zbv","rotateAngle="+rotateAngle);
if (rotateAngle > 180.0f) {
rotateAngle -= 360.0f;
}
// Log.d("zbv", "起始觸摸點到中心點角度爲=" + angle_1 + ";角度爲=" + jiaodu_1
// + ";移動點到中心點角度爲=" + angle_2 + ";角度爲=" + jiaodu_2);
}
break;
case MotionEvent.ACTION_UP:
//擡起-如果可以縮放就置爲原始不縮放狀態
if (isCanScale) {
isCanScale = false;
}
if (isCanRotate) {
isCanRotate = false;
isShowRotateView = false;
hadRotateAngle = rotateAngle;
}
break;
//多點觸摸---當一根手指已經down
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
}
return true;
}
/*
爲了處理canvas旋轉導致的視圖屬性沒有變化從而使得觸摸點的無法生效
所以反推原始點即:知道圓點、和旋轉後的點以及角度--->推導出旋轉前的點
*/
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;
//操作ID
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 List<View> allChildViews;
private View touchView;
public void setTouchView(View touchView) {
this.touchView = touchView;
}
private CustomBGView cus_view;
/**
* key是int類型,value是int[]類型
* 用於存儲添加的孩子在Layout中的位置以及添加的編號
* 一開始就具有位置參數
*/
private SparseArray<int[]> child_sarray;
/**
* 存儲角度---如果沒有臨時添加
*/
private SparseArray<Integer> degree_sarray;
//畫筆
// private Paint mPaint;
// private SharedPreferences sp_child;//用來保存當前子類的數量
private int childCount;
public void setChildCount(int childCount) {
this.childCount = childCount;
}
// private ScaleGestureDetector scaleGestureDetector;
public TestLayout(Context context) {
this(context, null);
}
public TestLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TestLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Log.d("zbv","初始化");
initConfig(context);
}
private void initConfig(Context context) {
mContext = context;
//可以在Layout繪製
// setWillNotDraw(false);
//設置子類的繪製順序
setChildrenDrawingOrderEnabled(true);
// mPaint = new Paint();
// mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
// mPaint.setStyle(Paint.Style.FILL);
// mPaint.setStrokeCap(Paint.Cap.ROUND);
// mPaint.setStrokeJoin(Paint.Join.ROUND);
// sp_child = mContext.getSharedPreferences("save_view_count", Context.MODE_PRIVATE);
// allChildViews = new ArrayList<View>();
// scaleGestureDetector = new ScaleGestureDetector(mContext, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Log.d("zbv","onMeasure");
//默認的View中的onMeasure-建議重寫
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*
* 依據測量模式和尺寸重新計算---主要針對Wrap_Content---因爲父類無法準確測量
*/
int mode_width = MeasureSpec.getMode(widthMeasureSpec);
int size_width = MeasureSpec.getSize(widthMeasureSpec);//具體值或者Match_Parent
int mode_height = MeasureSpec.getMode(heightMeasureSpec);
int size_height = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
//單行的寬高
int lineWidth = 0;
int lineHeight = 0;
// QZXTools.logE("zbv", "childCount=" + getChildCount(), null);
//得到layout中的子類個數
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
// allChildViews.add(child);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
//判斷是否INVISIBLE或者GONE
if (child.getVisibility() != View.VISIBLE) {
//最後一個的話需要總結一下
if (i == (childCount - 1)) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
continue;
}
//測量子類
measureChild(child, widthMeasureSpec, heightMeasureSpec);
//子類的寬度+左右的padding+左右的margin
// Log.d("zbv","getWidth="+child.getWidth()+";getMeasuredWidth="+child.getMeasuredWidth());
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if (lineWidth + childWidth > size_width - getPaddingLeft() - getPaddingRight()) {
//超過了父類的寬度->getPaddingLeft和Right是Layout自己的所以需要減去
width = Math.max(width, lineWidth);
lineWidth = childWidth;//另起一行的寬度
lineHeight += childHeight;
} else {
lineWidth += childWidth;
//可能一行排列中有的視圖高度會比之前高
lineHeight = Math.max(lineHeight, childHeight);
}
//最後再比較一下寬度
if (i == (childCount - 1)) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
}
setMeasuredDimension((mode_width == MeasureSpec.EXACTLY) ? size_width : width,
(mode_height == MeasureSpec.EXACTLY) ? size_height : height);
}
private boolean isFirst = true;
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//獲取layout中的所有子視圖個數
int childCount = getChildCount();
Log.d("zbv", "-------------------->onLayout" + childCount);
int left_padding = getPaddingLeft();
int top_padding = getPaddingTop();
// if (isFirst) {
// isFirst = false;
// for (int i = 0; i < childCount; i++) {
// //獲取對應i的子視圖
// View childView = getChildAt(i);
//// //獲取最後的BG
//// if((childCount-1)==i){
//// cus_view=(CustomBGView) childView;
//// }
// //添加觸摸監聽
// childView.setOnTouchListener(this);
// //因爲id要大於零---設置
// childView.setId(i + 1);
// MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();
// //依據給定的位置和margin以及padding設置子類的位置
// childView.layout(child_sarray.get(i)[0], child_sarray.get(i)[1],
// left_padding + childView.getMeasuredWidth() + layoutParams.leftMargin,
// top_padding + childView.getMeasuredHeight() + layoutParams.topMargin);
//
// }
// } else {
for (int i = 0; i < getChildCount(); i++) {
// Log.d("zbv","childCount="+getChildCount());
View childView = getChildAt(i);
childView.setOnTouchListener(this);
//手動設置childview的ID是從一開始的
childView.setId(i + 1);
MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();
// Log.d("zbv","childCount="+getChildCount()
// +";array_x="+child_sarray.get(i)[0]
// +";array_y="+child_sarray.get(i)[1]
// +";measureWidth="+childView.getMeasuredWidth()
// +";measureHeight="+childView.getMeasuredHeight()
// +";leftm="+layoutParams.leftMargin
// +";topm="+layoutParams.topMargin);
//依據給定的位置和margin以及padding設置子類的位置
QZXTools.logE("zbv", "------->child_array i=" + i, null);
// if (child_sarray.get(i) != null) {
childView.layout(child_sarray.get(i)[0], child_sarray.get(i)[1],
left_padding + childView.getMeasuredWidth() + layoutParams.leftMargin,
top_padding + childView.getMeasuredHeight() + layoutParams.topMargin);
// }
// //當最後一個加載完畢更新縮略圖----會調用很多次,每添加一個就會調用一次
// if(i==(getChildCount()-1)){
// Log.d("zbv","onLayout");
// thumbnailInterface.notifyLayoutChange();
// }
}
// }
}
// @Override
// protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// Log.d("zbv","onSizeChanged");
// super.onSizeChanged(w, h, oldw, oldh);
// thumbnailInterface.notifyLayoutChange();
// }
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Log.d("zbv","onInterceptTouchEvent action="+ev.getAction()+";pointerCount="+ev.getPointerCount());
// if(ev.getPointerCount()==2){
// return true;
//
// }
return super.onInterceptTouchEvent(ev);
}
private static final float CIRCLE_RADIUS = 10;
private static final int DEG_TIPS_DIVIDE = 30;
private static final int DEG_TIP_MARGIN = 90;
// @Override
// protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// //可以顯示提示Canvas
// if(isCanShowTips){
// for (View child : allChildViews){
// child.setAlpha(0.7f);
// }
// //繪製四個角的圓點----左上、左下、右上、右下---紅色
// mPaint.setColor(Color.RED);
// canvas.drawCircle(touch_view_left,touch_view_top,CIRCLE_RADIUS,mPaint);
// canvas.drawCircle(touch_view_left,touch_view_bottom,CIRCLE_RADIUS,mPaint);
// canvas.drawCircle(touch_view_right,touch_view_top,CIRCLE_RADIUS,mPaint);
// canvas.drawCircle(touch_view_right,touch_view_bottom,CIRCLE_RADIUS,mPaint);
//
//// //繪製旋轉度數的文本顯示---矩形背景綠色,文字白色
//// mPaint.setColor(Color.GREEN);
//// canvas.drawRect(touch_view_left+touch_view_width/2-DEG_TIPS_DIVIDE,
//// touch_view_top+DEG_TIP_MARGIN,
//// touch_view_left+touch_view_width/2+DEG_TIPS_DIVIDE,
//// touch_view_top+DEG_TIP_MARGIN,mPaint);
//
// mPaint.setColor(Color.YELLOW);
// Rect bounds=new Rect();
// String testText=-180+"°";
// mPaint.getTextBounds(testText,0,testText.length(),bounds);
// Paint.FontMetrics fontMetrics=mPaint.getFontMetrics();
// float baseLine=touch_view_top+(bounds.height()+fontMetrics.top-fontMetrics.bottom)/2-fontMetrics.top;
// canvas.drawText(0+"°",touch_view_left+bounds.width()/2,baseLine,mPaint);
// }
//
// }
// private double startDistance;//一開始兩指間的距離
// private double moveDistance;//移動中的兩指間距離
// private boolean isCanWholeScale = false;
// private boolean isGeasture = false;
// //是否可以移動---默認不可以移動
// private boolean isCanMove=false;
//四---處理觸摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
// Log.d("zbv", "onTouchEvent action=" + event.getAction());
//解決彈出軟鍵盤取消繪畫背景後的取消焦點問題
if (event.getAction() == MotionEvent.ACTION_DOWN && editText != null && editText.isFocusable()) {
if (event.getX() < touch_view_left || event.getX() > touch_view_right
|| event.getY() < touch_view_top || event.getY() > touch_view_bottom) {
Log.d("zbv", "編輯文本處於聚焦狀態---Layout onTouchEvent---在外邊");
touchFoucusForEditText(false);
}
}
// //多指操作---手勢操作
// switch (event.getAction() & MotionEvent.ACTION_MASK) {
// case MotionEvent.ACTION_DOWN:
//
// break;
// case MotionEvent.ACTION_MOVE:
//
// if (event.getPointerCount() == 2 && isCanWholeScale) {
// float point_1_x = event.getX(0);
// float point_1_y = event.getY(0);
//
// float point_2_x = event.getX(1);
// float point_2_y = event.getY(1);
//
// moveDistance = Math.sqrt((Math.pow(point_2_x - point_1_x, 2) + Math.pow(point_2_y - point_1_y, 2)));
//
// Log.d("zbv","moveDistance="+moveDistance);
//
// //沒動會跳動
// if (moveDistance != startDistance) {
// //才真正縮放
// float ratio = (float) (moveDistance / startDistance);
//
// Log.d("zbv","ratio="+ratio);
// setScaleX(ratio);
// setScaleY(ratio);
//
// }
// }
//
// break;
// case MotionEvent.ACTION_CANCEL:
// case MotionEvent.ACTION_UP:
//
// isCanWholeScale=false;
//
// dismisssDraw();
// break;
// case MotionEvent.ACTION_POINTER_DOWN:
//
// //只允許兩隻手指操作
// if (event.getPointerCount() == 2) {
//
// float point_1_x = event.getX();
// float point_1_y = event.getY();
//
// float point_2_x = event.getX(1);
// float point_2_y = event.getY(1);
//
// startDistance = Math.sqrt((Math.pow(point_2_x - point_1_x, 2) + Math.pow(point_2_y - point_1_y, 2)));
//
// Log.d("zbv","startDistance="+startDistance);
//
// if (startDistance > 10.0f) {
// isCanWholeScale = true;
// }
//
// }
//
// break;
// case MotionEvent.ACTION_POINTER_UP:
//
//
// break;
// }
// scaleGestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
// 滑動距離及座標 歸還父控件焦點iewPager
private float xDistance, yDistance, xLast, yLast, mLeft;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// Log.d("zbv","dispatchTouchEvent action="+ev.getAction());
// return super.dispatchTouchEvent(ev);
//這個是重點告訴父佈局我這裏是ViewPager不要攔截觸摸事件,否則橫向操作會滑動V
getParent().requestDisallowInterceptTouchEvent(true);
// switch (ev.getAction()) {
// case MotionEvent.ACTION_DOWN:
// Log.d("touch", "ACTION_DOWN");
// xDistance = yDistance = 0f;
// xLast = ev.getX();
// yLast = ev.getY();
// mLeft = ev.getX();// 解決與側邊欄滑動衝突
// break;
// case MotionEvent.ACTION_MOVE:
// final float curX = ev.getX();
// final float curY = ev.getY();
//
// xDistance += Math.abs(curX - xLast);
// yDistance += Math.abs(curY - yLast);
// xLast = curX;
// yLast = curY;
// if (mLeft < 100 || xDistance < yDistance) {
// getParent().requestDisallowInterceptTouchEvent(false);
// }
// break;
// case MotionEvent.ACTION_UP:
// case MotionEvent.ACTION_CANCEL:
// break;
// }
return super.dispatchTouchEvent(ev);
}
//是否可以顯示Canvas的提示
private boolean isCanShowTips = false;
// private boolean isDismiss=false;
private int interceptCount = 0;//處理兩個控件重疊的攔截
private boolean needShowEdit = false;
//三---得到觸摸的控件是哪一個子類,如果兩個控件重疊的話先觸摸到最後添加的
//不過EditText有點奇怪???
@Override
public boolean onTouch(View v, MotionEvent event) {
// Log.d("zbv", "onTouch " + ";event action=" + event.getAction());
//單指觸摸
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Log.d("zbv", "interceptCount=" + interceptCount + ";chihldCount=" + getChildCount());
//如果存在editText的操作---每次觸摸都會調用縮略圖的更新
touchFoucusForEditText(false);
//動態添加移除
if (interceptCount == 0) {
interceptCount++;//1
touchView = v;
touch_view_left = v.getLeft();
touch_view_right = v.getRight();
touch_view_top = v.getTop();
touch_view_bottom = v.getBottom();
touch_view_width = touch_view_right - touch_view_left;
touch_view_height = touch_view_bottom - touch_view_top;
if (touchView instanceof EditText) {
needShowEdit = true;
} else {
needShowEdit = false;
}
/*
添加遮罩層
因爲是觸摸到才添加所以第一觸摸的事件無效-所以出現bug是第一次無法觸摸拖動,
因爲遮罩層是最後一個控件所以位置是需要所有控件數+1
*/
// addDrawCustomViewWhenTouch(sp_child.getInt("childCount", -1));
addDrawCustomViewWhenTouch(childCount);
if (touchView instanceof TextView || touchView instanceof EditText) {
QZXTools.logE("zbv", "觸摸到文本視圖", null);
thumbnailInterface.touchTextView((TextView) touchView);
} else {
thumbnailInterface.touchTextView(null);
}
}
// Log.d("zbv", "touch_width="+touch_view_width+";touch_height=" +touch_view_height
// +";touch_left="+touch_view_left+";touch_top="+touch_view_top
// +";touch_right="+touch_view_right+";touch_bottom="+touch_view_bottom
// +";getX="+event.getX()+";getY="+event.getY());
break;
//----想通過動態修改customBGView的onTouchEvent攔截--->不行-因爲一旦修改了就變不回來了
// Log.d("zbv","interceptCount="+interceptCount);
// if(isDismiss){
// interceptCount=0;
// touchView=null;
// touch_view_left=0;
// touch_view_top=0;
// touch_view_right=0;
// touch_view_bottom=0;
// touch_view_width=0;
// touch_view_height=0;
// cus_view.transmitParams(0,touch_view_left,touch_view_top,touch_view_width,touch_view_height);
// cus_view.updateView(false);
// }else{
// //觸碰到第二個視圖纔是用戶真正想要操作的對象
// if(interceptCount==1){
// touchView=v;
// touch_view_left=v.getLeft();
// touch_view_right=v.getRight();
// touch_view_top=v.getTop();
// touch_view_bottom=v.getBottom();
// touch_view_width=touch_view_right-touch_view_left;
// touch_view_height=touch_view_bottom-touch_view_top;
//
// cus_view.transmitParams(0,touch_view_left,touch_view_top,touch_view_width,touch_view_height);
//
// cus_view.updateView(true);
//
// Log.d("zbv", "touch_width="+touch_view_width+";touch_height=" +touch_view_height
// +";touch_left="+touch_view_left+";touch_top="+touch_view_top
// +";touch_right="+touch_view_right+";touch_bottom="+touch_view_bottom
// +";getX="+event.getX()+";getY="+event.getY());
// }
// }
// interceptCount++;
//--------------------------------------------------
}
return false;
}
//主動添加孩子的位置和順序號
public void getChildLocation(int[] location, int position, int degree) {
//因爲我是先設置這個位置然後再添加給父類所以SparseArray的實例化要在這裏開始
if (child_sarray == null) {
child_sarray = new SparseArray<int[]>();
}
// QZXTools.logE("zbv", "position=" + position, null);
child_sarray.put(position, location);
//角度
if (degree_sarray == null) {
degree_sarray = new SparseArray<Integer>();
}
if (degree_sarray.get(position) == null) {
degree_sarray.put(position, degree);
}
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {
//觸摸的那個視圖倒數第二個繪製---因爲我加了一個控制層視圖
if (touchView != null) {
// QZXTools.logE("zbv", "touchview--->id" + touchView.getId(), null);
int position = touchView.getId();
//想要最後繪製的視圖
if (i == (position - 1)) {
return childCount - 2;
}
//原本最後繪製的視圖
else if (i == (childCount - 2)) {
return position - 1;
}
}
return super.getChildDrawingOrder(childCount, i);
}
/**
* 當觸摸到視圖時爲其添加自定義外圍視圖
* 觸摸點的位置,寬高,旋轉角度
*/
private void addDrawCustomViewWhenTouch(int position) {
QZXTools.logE("zbv", "addDrawCustomViewWhenTouch", null);
cus_view = new CustomBGView(mContext);
cus_view.setCustomInterface(this);
//設置是否僅僅支持移動操作
cus_view.setOnlyCanMove(isShowActivtiy);
getChildLocation(new int[]{0, 0}, position, 0);
// //如果不先賦值會空指針---不用了,改爲一開始就需要設置角度
// if (degree_sarray == null) {
// degree_sarray = new SparseArray<Integer>();
// }
// if (degree_sarray.get(touchView.getId()) == null) {
// degree_sarray.put(touchView.getId(), 0);
// }
// Log.d("zbv", "position=" + position + ";touchview id=" + touchView.getId());
int id = touchView.getId();
cus_view.setDegree(degree_sarray.get(id - 1));
cus_view.setTouch_x(touch_view_left);
cus_view.setTouch_y(touch_view_top);
cus_view.setTouch_width(touch_view_width);
cus_view.setTouch_height(touch_view_height);
//是否需要顯示編輯提示---當存在EditText控件時
cus_view.setNeedShowEdit(needShowEdit);
ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
addView(cus_view, lp);
}
/**
* 當沒有觸碰到視圖的時候移除
*/
private void removeDrawCustomViewWhenTouch() {
removeView(cus_view);
}
/**
* 回調的去除BG
*/
@Override
public void dismisssDraw() {
// Log.d("zbv", "dismissDraw");
interceptCount = 0;
removeDrawCustomViewWhenTouch();
}
//VP當前頁的ID
private int curVPPage;
/**
* 傳入正在操作的是ViewPager的那一頁---每次VP更新都需要重置
* 放在Adapter中傳遞,每次instantiate
*/
public void translateVPPage(int page) {
curVPPage = page;
}
//------------------------------------------------------------------------------
// private boolean isBackOrGo = false;//是否是撤銷或者前進操作
// public void setBackOrGo(boolean backOrGo) {
// isBackOrGo = backOrGo;
// }
//如何知道上次是什麼操作???現在的問題是:我保存的數據是原始的,但是操作卻是當前的
//-------------------------操作更新-------------------------------------------------
@Override
public void updateViewMoveLocation(int x, int y) {
// Log.d("zbv", "x=" + x + ";y=" + y + ";touchID=" + touchView.getId()+";curVPPage="+curVPPage);
int index = touchView.getId();
//重置SparseArray的值
child_sarray.setValueAt(index - 1, new int[]{x, y});
MarginLayoutParams layoutParams = (MarginLayoutParams) touchView.getLayoutParams();
//這兩個margin必須要設置的不然高度小於其實繪製的點就看不見了
layoutParams.leftMargin = (int) x;
layoutParams.topMargin = (int) y;
requestLayout();
invalidate();
//延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
postDelayed(new Runnable() {
@Override
public void run() {
thumbnailInterface.notifyLayoutChange();
}
}, 200);
String transText = null;
if (touchView instanceof TextView || touchView instanceof EditText) {
transText = ((TextView) touchView).getText().toString();
}
OperationRecord operationRecord = new OperationRecord(true, curVPPage, touchView, TRANSLATE, touchView.getId(),
degree_sarray.get(index - 1), touch_view_left, touch_view_top, touch_view_width, touch_view_height, transText);
OperationRecord operationRecord_new = new OperationRecord(true, curVPPage, touchView, TRANSLATE, touchView.getId(),
degree_sarray.get(index - 1), x, y, touch_view_width, touch_view_height, transText);
//不是撤銷前進操作就需要記錄操作
// if (!isBackOrGo) {
Log.d("zbv", "operation=" + operationRecord);
thumbnailInterface.saveOperation(operationRecord, operationRecord_new);
thumbnailInterface.saveNewOperation(operationRecord_new);
// }
// //爲什麼不可以
// touchView.layout(x,y,x+touch_view_width,y+touch_view_height);
// invalidate();
//動畫
// TranslateAnimation translateAnimation=new TranslateAnimation(
// Animation.RELATIVE_TO_SELF, 0,
// Animation.RELATIVE_TO_SELF, 200,
// Animation.RELATIVE_TO_SELF, 0,
// Animation.RELATIVE_TO_SELF,0);
// translateAnimation.setDuration(200);
// translateAnimation.setFillAfter(true);
// touchView.startAnimation(translateAnimation);
}
@Override
public void updateViewScaleLocation(int x, int y, int right, int bottom) {
Log.d("zbv", "x=" + x + ";y=" + y + ";right=" + right + ";bottom=" + bottom + ";touchID=" + touchView.getId());
int index = touchView.getId();
//重置SparseArray的值
child_sarray.setValueAt(index - 1, new int[]{x, y});
MarginLayoutParams layoutParams = (MarginLayoutParams) touchView.getLayoutParams();
//這兩個margin必須要設置的不然高度小於其實繪製的點就看不見了
layoutParams.leftMargin = (int) x;
layoutParams.topMargin = (int) y;
//改變縮放的寬高
layoutParams.width = right - x;
layoutParams.height = bottom - y;
requestLayout();
invalidate();
//延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
postDelayed(new Runnable() {
@Override
public void run() {
thumbnailInterface.notifyLayoutChange();
}
}, 200);
String transText = null;
if (touchView instanceof TextView || touchView instanceof EditText) {
transText = ((TextView) touchView).getText().toString();
}
OperationRecord operationRecord = new OperationRecord(true, curVPPage, touchView, SCALE, touchView.getId(),
degree_sarray.get(index - 1), touch_view_left, touch_view_top, touch_view_width, touch_view_height, transText);
OperationRecord operationRecord_new = new OperationRecord(true, curVPPage, touchView, SCALE, touchView.getId(),
degree_sarray.get(index - 1), x, y, right - x, bottom - y, transText);
//不是撤銷前進操作就需要記錄操作
// if (!isBackOrGo) {
Log.d("zbv", "operation=" + operationRecord);
thumbnailInterface.saveOperation(operationRecord, operationRecord_new);
thumbnailInterface.saveNewOperation(operationRecord_new);
// }
}
private int beforeDegree;
@Override
public void updateViewRotateLocation(int degree) {
int id = touchView.getId();
beforeDegree = degree_sarray.get(id - 1);
//存儲角度
degree_sarray.put(id - 1, degree);
ValueAnimator valueAnimator = ValueAnimator.ofFloat(beforeDegree, degree);
valueAnimator.setDuration(500);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
touchView.setRotation((float) animation.getAnimatedValue());
}
});
valueAnimator.start();
// touchView.setRotation(degree);
invalidate();
//延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
postDelayed(new Runnable() {
@Override
public void run() {
thumbnailInterface.notifyLayoutChange();
}
}, 700);
String transText = null;
if (touchView instanceof TextView || touchView instanceof EditText) {
transText = ((TextView) touchView).getText().toString();
}
OperationRecord operationRecord = new OperationRecord(true, curVPPage, touchView, ROTATE, touchView.getId(),
beforeDegree, touch_view_left, touch_view_top, touch_view_width, touch_view_height, transText);
OperationRecord operationRecord_new = new OperationRecord(true, curVPPage, touchView, ROTATE, touchView.getId(),
degree_sarray.get(id - 1), touch_view_left, touch_view_top, touch_view_width, touch_view_height, transText);
//不是撤銷前進操作就需要記錄操作
// if (!isBackOrGo) {
thumbnailInterface.saveOperation(operationRecord, operationRecord_new);
thumbnailInterface.saveNewOperation(operationRecord_new);
// }
}
private EditText editText;
@Override
public void touchFoucusForEditText(boolean isFocus) {
if (touchView instanceof EditText) {
Log.d("zbv", "touchVeiw is equal to editText " + isFocus);
editText = (EditText) touchView;
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
int index = touchView.getId();
OperationRecord operationRecord_new = new OperationRecord(true, curVPPage, touchView, EDITMODE, index,
degree_sarray.get(index - 1), touch_view_left, touch_view_top, touch_view_width, touch_view_height, s.toString());
thumbnailInterface.saveNewOperation(operationRecord_new);
}
});
editText.setFocusableInTouchMode(isFocus);
editText.setFocusable(isFocus);
InputMethodManager methodManager = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
if (isFocus) {
//彈出軟鍵盤
editText.requestFocus();
methodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
} else {
//不可焦且取消軟鍵盤
methodManager.hideSoftInputFromWindow(getWindowToken(), 0);
}
} else {
if (editText != null) {
editText.setFocusable(false);
editText.setFocusableInTouchMode(false);
}
}
//延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
postDelayed(new Runnable() {
@Override
public void run() {
thumbnailInterface.notifyLayoutChange();
}
}, 200);
}
//拷貝複製不進行撤銷和回退
@Override
public void copyOnceView() {
if (touchView instanceof TextView) {
TextView originalTextView = (TextView) touchView;
TextView tv_one = new TextView(mContext);
tv_one.setText(originalTextView.getText());
tv_one.setTextColor(originalTextView.getTextColors());
tv_one.setBackground(originalTextView.getBackground());
//爲所要添加的視圖給予一個其所在父類的佈局參數
ViewGroup.MarginLayoutParams lp_one = new ViewGroup.MarginLayoutParams(
originalTextView.getWidth(), originalTextView.getHeight());
int[] location_one = new int[]{originalTextView.getLeft(), originalTextView.getTop()};
QZXTools.logE("zbv", "childCount=" + childCount, null);
//編號從零開始
// getChildLocation(location_one, sp_child.getInt("childCount", -1));
getChildLocation(location_one, childCount, 0);
//設置初始在Layout中的位置
lp_one.setMargins(location_one[0], location_one[1], 0, 0);
//如果不添加index默認是-1添加到最後
addView(tv_one, lp_one);
String transText = null;
if (tv_one instanceof TextView || tv_one instanceof EditText) {
transText = ((TextView) tv_one).getText().toString();
}
// OperationRecord operationRecord = new OperationRecord(true, curVPPage, tv_one, COPY, tv_one.getId(),
// degree_sarray.get(childCount), location_one[0], location_one[1], lp_one.width, lp_one.height, transText);
//
OperationRecord operationRecord_new = new OperationRecord(true, curVPPage, originalTextView, COPY,
originalTextView.getId(), degree_sarray.get(childCount),
location_one[0], location_one[1], lp_one.width, lp_one.height, transText);
//設置拷貝的視圖類型
operationRecord_new.setType(type);
// //不是撤銷前進操作就需要記錄操作
//// if (!isBackOrGo) {
// thumbnailInterface.saveOperation(operationRecord,operationRecord_new);
thumbnailInterface.saveNewOperation(operationRecord_new);
// }
//視圖增加一
// sp_child.edit().putInt("childCount", sp_child.getInt("childCount", -1) + 1).commit();
childCount++;
} else if (touchView instanceof EditText) {
} else if (touchView instanceof ImageView) {
}
//延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
postDelayed(new Runnable() {
@Override
public void run() {
thumbnailInterface.notifyLayoutChange();
}
}, 200);
}
@Override
public void deleteOnceView() {
int id = touchView.getId();
if (touchView instanceof TextView) {
removeView(touchView);
childCount--;
String transText = null;
if (touchView instanceof TextView || touchView instanceof EditText) {
transText = ((TextView) touchView).getText().toString();
}
// OperationRecord operationRecord = new OperationRecord(true, curVPPage, touchView, DEL, touchView.getId(),
// degree_sarray.get(id - 1), touch_view_left, touch_view_top, touch_view_width, touch_view_height, transText);
//
OperationRecord operationRecord_new = new OperationRecord(true, curVPPage, touchView, DEL, touchView.getId(),
degree_sarray.get(id - 1), touch_view_left, touch_view_top, touch_view_width, touch_view_height, transText);
// //不是撤銷前進操作就需要記錄操作
//// if (!isBackOrGo) {
// thumbnailInterface.saveOperation(operationRecord,operationRecord_new);
thumbnailInterface.saveNewOperation(operationRecord_new);
// }
//注意的是:所有大於該視圖編號的要重排
child_sarray.removeAt(touchView.getId());
degree_sarray.removeAt(touchView.getId());
} else if (touchView instanceof EditText) {
} else if (touchView instanceof ImageView) {
}
//延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
postDelayed(new Runnable() {
@Override
public void run() {
thumbnailInterface.notifyLayoutChange();
}
}, 200);
}
// //一下三個方法用於撤銷和回退以及文本返回的----不可取重新new了新的對象
// public void cancelDelView(View cancleView) {
//
// if (cancleView instanceof TextView) {
//
// TextView tv_one = new TextView(mContext);
// tv_one.setText("七子笑");
// tv_one.setTextColor(Color.WHITE);
// tv_one.setBackgroundColor(Color.BLACK);
// //爲所要添加的視圖給予一個其所在父類的佈局參數
// ViewGroup.MarginLayoutParams lp_one = new ViewGroup.MarginLayoutParams(300, 200);
// int[] location_one = new int[]{100, 200};
// //編號從零開始
//// getChildLocation(location_one, sp_child.getInt("childCount", -1));
//
// getChildLocation(location_one, childCount, 0);
// //設置初始在Layout中的位置
// lp_one.setMargins(location_one[0], location_one[1], 0, 0);
// //如果不添加index默認是-1添加到最後
// addView(tv_one, lp_one);
//
// //視圖增加一
//// sp_child.edit().putInt("childCount", sp_child.getInt("childCount", -1) + 1).commit();
// childCount++;
//
// } else if (cancleView instanceof EditText) {
//
// } else if (cancleView instanceof ImageView) {
//
// }
// //延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
// postDelayed(new Runnable() {
// @Override
// public void run() {
// thumbnailInterface.notifyLayoutChange();
// }
// }, 200);
//
// }
//
// public void cancleCopyView(View cancleView) {
// if (cancleView instanceof TextView) {
//
// removeView(cancleView);
// childCount--;
//
// //注意的是:所有大於該視圖編號的要重排
// child_sarray.removeAt(cancleView.getId());
// degree_sarray.removeAt(cancleView.getId());
//
// } else if (cancleView instanceof EditText) {
//
// } else if (cancleView instanceof ImageView) {
//
// }
//
// //延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
// postDelayed(new Runnable() {
// @Override
// public void run() {
// thumbnailInterface.notifyLayoutChange();
// }
// }, 200);
// }
/**
* 針對複製和刪除的操作不能new一個新的對象,而是要對之前的對象進行操作
*/
public void updateOperation(int x, int y, int right, int bottom, int degree, boolean isCopy, boolean isDel, boolean isBack) {
int index = touchView.getId();
//重置SparseArray的值
child_sarray.setValueAt(index - 1, new int[]{x, y});
beforeDegree = degree_sarray.get(index - 1);
//存儲角度
degree_sarray.put(index - 1, degree);
MarginLayoutParams layoutParams = (MarginLayoutParams) touchView.getLayoutParams();
//這兩個margin必須要設置的不然高度小於其實繪製的點就看不見了
layoutParams.leftMargin = (int) x;
layoutParams.topMargin = (int) y;
//改變縮放的寬高
layoutParams.width = right - x;
layoutParams.height = bottom - y;
touchView.setRotation(degree);
// if(isCopy){
// if(isBack){
// removeView(touchView);
// }else{
// addView(touchView);
// }
// }else if(isDel){
// if(isBack){
// addView(touchView);
// }else{
// removeView(touchView);
// }
// }
requestLayout();
invalidate();
//延遲200ms這個時間可以依據實際調節,立即調用的話layout沒有繪製完全
postDelayed(new Runnable() {
@Override
public void run() {
thumbnailInterface.notifyLayoutChange();
}
}, 200);
}
//---------------------------操作更新-----------------------------------------------
//---------------------------記錄保存---------------------------------------------
// /**
// * 操作記錄保存
// */
// private void operationSave(int x, int y, int right, int bottom) {
//
// }
//---------------------------記錄保存---------------------------------------------
// @Override
// public boolean onScale(ScaleGestureDetector detector) {
// float scaleFactor=detector.getScaleFactor();
// Log.d("zbv","scaleFactor="+scaleFactor);
// setScaleX(scaleFactor);
// setScaleY(scaleFactor);
// return true;
// }
//
// @Override
// public boolean onScaleBegin(ScaleGestureDetector detector) {
// return true;
// }
//
// @Override
// public void onScaleEnd(ScaleGestureDetector detector) {
//
// }
//提供接口和Activity交互
private ThumbnailInterface thumbnailInterface;
public void setThumbnailInterface(ThumbnailInterface thumbnailInterface) {
this.thumbnailInterface = thumbnailInterface;
}
public interface ThumbnailInterface {
/**
* 加載完畢和佈局改變都一樣
*/
void notifyLayoutChange();
/**
* 操作記錄保存
*/
void saveOperation(OperationRecord operationRecord, OperationRecord newOperationRecord);
/**
* 保存最新的操作---用於json的數據實時保存
*/
void saveNewOperation(OperationRecord operationRecord);
/**
* 觸摸到的是文本視圖:TextView或者EditText
* <br/><br/>
* 如果觸摸的不是文本類就置空null
*/
void touchTextView(TextView textView);
}
}
2、遮罩層CustomBGView
package com.ahtelit.zbv.vphandler;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Administrator on 2018/4/27.
* qzx
* <p>
* Match_Parent Match_Parent
*/
public class CustomBGView extends View {
//設置僅僅可以移動操作標誌
private boolean isOnlyCanMove = false;
public void setOnlyCanMove(boolean onlyCanMove) {
isOnlyCanMove = onlyCanMove;
}
private Paint mPaint;
//在添加給Layout時需要預先設置--------------
private int degree;
private float touch_x;
private float touch_y;
private float touch_right;
private float touch_bottom;
private int touch_width;
private int touch_height;
public float getDegree() {
return degree;
}
public void setDegree(int degree) {
this.degree = degree;
}
public float getTouch_x() {
return touch_x;
}
public void setTouch_x(float touch_x) {
this.touch_x = touch_x;
}
public float getTouch_y() {
return touch_y;
}
public void setTouch_y(float touch_y) {
this.touch_y = touch_y;
}
public int getTouch_width() {
return touch_width;
}
//必須在設置了touch_x後
public void setTouch_width(int touch_width) {
this.touch_width = touch_width;
// if(degree!=0){
// touch_right= (float) (touch_x+touch_width*Math.cos(Math.toRadians(degree)));
// }else{
touch_right = touch_x + touch_width;
// }
}
public int getTouch_height() {
return touch_height;
}
//必須在設置了touch_後
public void setTouch_height(int touch_height) {
this.touch_height = touch_height;
// if(degree!=0){
// touch_bottom= (float) (touch_x+touch_height*Math.cos(Math.toRadians(degree)));
// }else{
touch_bottom = touch_y + touch_height;
// }
}
// public void transmitParams(int deg,float x,float y,int width,int height){
// degree=deg;
// touch_x=x;
// touch_y=y;
// touch_width=width;
// touch_height=height;
// }
//------------------------------------------------
public void updateView() {
invalidate();
}
//----------------------------------------------
public CustomBGView(Context context) {
this(context, null);
}
public CustomBGView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomBGView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
rotate_rect = new Rect();
copy_rect = new Rect();
edit_rect = new Rect();
del_rect = new Rect();
line_rect = new Rect();
effect = new DashPathEffect(new float[]{20, 5}, 0);
}
private static final float CIRCLE_RADIUS = 20;
private static final int INTERVAL = 90;
private float TIPS_WIDTH = 200;
private static final int TIPS_HEIGHT = 60;
private static final float TEXT_SIZE = 30;
// private static final float TIPS_INTERVAL=40;//每個字體佔用的空間
private static final float TIPS_DIVIDE = 10;//豎線的間隔
private static final String TEXT_ROTATE = "旋轉";
private static final String TEXT_COPY = "複製";
private static final String TEXT_EDIT = "編輯";
private static final String TEXT_DEL = "刪除";
private static final String TEXT_LINE = "|";
// //操控音樂盒視頻
// private static final String TEXT_OPERATE_MUSIC = "操控音樂";
// private static final String TEXT_OPERATE_VIDEO = "操控視頻";
// private int degree_rotate = 0;//顯示角度提示
private Rect rotate_rect, copy_rect, edit_rect, del_rect, line_rect;
private DashPathEffect effect;//波折線
private static final int LineTouchW = 70;
private static final int STROKE_WIDTH = 7;
//因爲是全屏的
@Override
protected void onDraw(Canvas canvas) {
// Log.d("zbv", "isCanMove=" + isCanMove + ";isCanScale=" + isCanScale + ";isCanRotate=" + isCanRotate + ";rotate_degree=" + degree);
if (!isCanMove && !isCanScale && !isCanRotate) {
if (isOnlyCanMove) {
mPaint.setColor(Color.GREEN);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(STROKE_WIDTH);
canvas.drawRect(touch_x, touch_y, touch_x + touch_width, touch_y + touch_height, mPaint);
} else {
if (degree != 0) {
canvas.save();
canvas.rotate(degree, touch_x + touch_width / 2, touch_y + touch_height / 2);
//可縮放的紅點區域
mPaint.setColor(Color.RED);
canvas.drawCircle(touch_x, touch_y, CIRCLE_RADIUS, mPaint);//左上
canvas.drawCircle(touch_x + touch_width, touch_y, CIRCLE_RADIUS, mPaint);//右上
canvas.drawCircle(touch_x, touch_y + touch_height, CIRCLE_RADIUS, mPaint);//左下
canvas.drawCircle(touch_x + touch_width, touch_y + touch_height, CIRCLE_RADIUS, mPaint);//右下
//是否顯示可編輯-在有EditText視圖下顯示
if (isNeedShowEdit) {
//重置tips的寬度
TIPS_WIDTH = 320;
//提示操作區域
mPaint.setColor(Color.GRAY);
//左邊+參考寬度的一半-所畫矩形寬度的一半
canvas.drawRect(touch_x + touch_width / 2 - TIPS_WIDTH / 2, touch_y - INTERVAL - TIPS_HEIGHT, touch_x + touch_width / 2 + TIPS_WIDTH / 2, touch_y - INTERVAL, mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(TEXT_SIZE);
//文本居中對齊
mPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
//需要計算一番,讓文字在矩形背景的中間
float baseLine = touch_y - INTERVAL + (fontMetrics.top - fontMetrics.bottom) / 2;
mPaint.getTextBounds(TEXT_ROTATE, 0, TEXT_ROTATE.length(), rotate_rect);
mPaint.getTextBounds(TEXT_COPY, 0, TEXT_COPY.length(), copy_rect);
mPaint.getTextBounds(TEXT_EDIT, 0, TEXT_EDIT.length(), edit_rect);
mPaint.getTextBounds(TEXT_LINE, 0, TEXT_LINE.length(), line_rect);
mPaint.getTextBounds(TEXT_DEL, 0, TEXT_DEL.length(), del_rect);
//因爲align是center所以只要自己的一半算進去就可以了,其他的原來多長就算多長
// canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - copy_rect.width() / 2 - TIPS_DIVIDE * 2 - line_rect.width(), baseLine, mPaint);
// canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 - copy_rect.width() / 2 - TIPS_DIVIDE - line_rect.width() / 2, baseLine, mPaint);
// canvas.drawText(TEXT_COPY, touch_x + touch_width / 2, baseLine, mPaint);
// canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 + copy_rect.width() / 2 + TIPS_DIVIDE + line_rect.width() / 2, baseLine, mPaint);
// canvas.drawText(TEXT_EDIT, touch_x + touch_width / 2 + edit_rect.width() / 2 + copy_rect.width() / 2 + TIPS_DIVIDE * 2, baseLine, mPaint);
canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - copy_rect.width() - TIPS_DIVIDE * 3 - line_rect.width(), baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 - copy_rect.width() - TIPS_DIVIDE * 2 - line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_COPY, touch_x + touch_width / 2 - copy_rect.width() / 2 - TIPS_DIVIDE, baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2, baseLine, mPaint);//中心
canvas.drawText(TEXT_EDIT, touch_x + touch_width / 2 + edit_rect.width() / 2 + TIPS_DIVIDE, baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 + edit_rect.width() + TIPS_DIVIDE * 2 + line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_DEL, touch_x + touch_width / 2 + del_rect.width() / 2 + edit_rect.width() + TIPS_DIVIDE * 3 + line_rect.width(), baseLine, mPaint);
} else {
//重置tips的寬度
TIPS_WIDTH = 240;
//提示操作區域
mPaint.setColor(Color.GRAY);
//左邊+參考寬度的一半-所畫矩形寬度的一半
canvas.drawRect(touch_x + touch_width / 2 - TIPS_WIDTH / 2, touch_y - INTERVAL - TIPS_HEIGHT, touch_x + touch_width / 2 + TIPS_WIDTH / 2, touch_y - INTERVAL, mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(TEXT_SIZE);
//文本居中對齊
mPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
//需要計算一番,讓文字在矩形背景的中間
float baseLine = touch_y - INTERVAL + (fontMetrics.top - fontMetrics.bottom) / 2;
mPaint.getTextBounds(TEXT_ROTATE, 0, TEXT_ROTATE.length(), rotate_rect);
mPaint.getTextBounds(TEXT_COPY, 0, TEXT_COPY.length(), copy_rect);
mPaint.getTextBounds(TEXT_EDIT, 0, TEXT_EDIT.length(), edit_rect);
mPaint.getTextBounds(TEXT_DEL, 0, TEXT_DEL.length(), del_rect);
// canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - TIPS_DIVIDE, baseLine, mPaint);
// canvas.drawText(TEXT_LINE, touch_x + touch_width / 2, baseLine, mPaint);
// canvas.drawText(TEXT_COPY, touch_x + touch_width / 2 + copy_rect.width() / 2 + TIPS_DIVIDE, baseLine, mPaint);
canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - copy_rect.width() / 2 - TIPS_DIVIDE * 2 - line_rect.width(), baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 - copy_rect.width() / 2 - TIPS_DIVIDE - line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_COPY, touch_x + touch_width / 2, baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 + copy_rect.width() / 2 + TIPS_DIVIDE + line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_DEL, touch_x + touch_width / 2 + del_rect.width() / 2 + copy_rect.width() / 2 + TIPS_DIVIDE * 2, baseLine, mPaint);
}
canvas.restore();
} else {
//可縮放的紅點區域
mPaint.setColor(Color.RED);
canvas.drawCircle(touch_x, touch_y, CIRCLE_RADIUS, mPaint);//左上
canvas.drawCircle(touch_x + touch_width, touch_y, CIRCLE_RADIUS, mPaint);//右上
canvas.drawCircle(touch_x, touch_y + touch_height, CIRCLE_RADIUS, mPaint);//左下
canvas.drawCircle(touch_x + touch_width, touch_y + touch_height, CIRCLE_RADIUS, mPaint);//右下
//是否顯示可編輯-在有EditText視圖下顯示
if (isNeedShowEdit) {
//重置tips的寬度
TIPS_WIDTH = 320;
//提示操作區域
mPaint.setColor(Color.GRAY);
//左邊+參考寬度的一半-所畫矩形寬度的一半
canvas.drawRect(touch_x + touch_width / 2 - TIPS_WIDTH / 2, touch_y - INTERVAL - TIPS_HEIGHT, touch_x + touch_width / 2 + TIPS_WIDTH / 2, touch_y - INTERVAL, mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(TEXT_SIZE);
//文本居中對齊
mPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
//需要計算一番,讓文字在矩形背景的中間
float baseLine = touch_y - INTERVAL + (fontMetrics.top - fontMetrics.bottom) / 2;
mPaint.getTextBounds(TEXT_ROTATE, 0, TEXT_ROTATE.length(), rotate_rect);
mPaint.getTextBounds(TEXT_COPY, 0, TEXT_COPY.length(), copy_rect);
mPaint.getTextBounds(TEXT_EDIT, 0, TEXT_EDIT.length(), edit_rect);
mPaint.getTextBounds(TEXT_LINE, 0, TEXT_LINE.length(), line_rect);
mPaint.getTextBounds(TEXT_DEL, 0, TEXT_DEL.length(), del_rect);
//因爲align是center所以只要自己的一半算進去就可以了,其他的原來多長就算多長
// canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - copy_rect.width() / 2 - TIPS_DIVIDE * 2 - line_rect.width(), baseLine, mPaint);
// canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 - copy_rect.width() / 2 - TIPS_DIVIDE - line_rect.width() / 2, baseLine, mPaint);
// canvas.drawText(TEXT_COPY, touch_x + touch_width / 2, baseLine, mPaint);
// canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 + copy_rect.width() / 2 + TIPS_DIVIDE + line_rect.width() / 2, baseLine, mPaint);
// canvas.drawText(TEXT_EDIT, touch_x + touch_width / 2 + edit_rect.width() / 2 + copy_rect.width() / 2 + TIPS_DIVIDE * 2, baseLine, mPaint);
canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - copy_rect.width() - TIPS_DIVIDE * 3 - line_rect.width(), baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 - copy_rect.width() - TIPS_DIVIDE * 2 - line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_COPY, touch_x + touch_width / 2 - copy_rect.width() / 2 - TIPS_DIVIDE, baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2, baseLine, mPaint);//中心
canvas.drawText(TEXT_EDIT, touch_x + touch_width / 2 + edit_rect.width() / 2 + TIPS_DIVIDE, baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 + edit_rect.width() + TIPS_DIVIDE * 2 + line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_DEL, touch_x + touch_width / 2 + del_rect.width() / 2 + edit_rect.width() + TIPS_DIVIDE * 3 + line_rect.width(), baseLine, mPaint);
} else {
//重置tips的寬度
TIPS_WIDTH = 240;
//提示操作區域
mPaint.setColor(Color.GRAY);
//左邊+參考寬度的一半-所畫矩形寬度的一半
canvas.drawRect(touch_x + touch_width / 2 - TIPS_WIDTH / 2, touch_y - INTERVAL - TIPS_HEIGHT, touch_x + touch_width / 2 + TIPS_WIDTH / 2, touch_y - INTERVAL, mPaint);
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(TEXT_SIZE);
//文本居中對齊
mPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
//需要計算一番,讓文字在矩形背景的中間
float baseLine = touch_y - INTERVAL + (fontMetrics.top - fontMetrics.bottom) / 2;
mPaint.getTextBounds(TEXT_ROTATE, 0, TEXT_ROTATE.length(), rotate_rect);
mPaint.getTextBounds(TEXT_COPY, 0, TEXT_COPY.length(), copy_rect);
mPaint.getTextBounds(TEXT_EDIT, 0, TEXT_EDIT.length(), edit_rect);
mPaint.getTextBounds(TEXT_DEL, 0, TEXT_DEL.length(), del_rect);
// canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - TIPS_DIVIDE, baseLine, mPaint);
// canvas.drawText(TEXT_LINE, touch_x + touch_width / 2, baseLine, mPaint);
// canvas.drawText(TEXT_COPY, touch_x + touch_width / 2 + copy_rect.width() / 2 + TIPS_DIVIDE, baseLine, mPaint);
canvas.drawText(TEXT_ROTATE, touch_x + touch_width / 2 - rotate_rect.width() / 2 - copy_rect.width() / 2 - TIPS_DIVIDE * 2 - line_rect.width(), baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 - copy_rect.width() / 2 - TIPS_DIVIDE - line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_COPY, touch_x + touch_width / 2, baseLine, mPaint);
canvas.drawText(TEXT_LINE, touch_x + touch_width / 2 + copy_rect.width() / 2 + TIPS_DIVIDE + line_rect.width() / 2, baseLine, mPaint);
canvas.drawText(TEXT_DEL, touch_x + touch_width / 2 + del_rect.width() / 2 + copy_rect.width() / 2 + TIPS_DIVIDE * 2, baseLine, mPaint);
}
}
}
}
mPaint.setColor(0x70cccccc);
//如果是演示層重置會實體繪製
mPaint.setStyle(Paint.Style.FILL);
if (isCanMove) {
if (degree != 0) {
canvas.save();
canvas.rotate(degree, touch_x + touch_width / 2, touch_y + touch_height / 2);
canvas.drawRect(touch_x, touch_y, touch_x + touch_width, touch_y + touch_height, mPaint);
canvas.restore();
} else {
//要做變換的矩形
canvas.drawRect(touch_x, touch_y, touch_x + touch_width, touch_y + touch_height, mPaint);
}
} else if (isCanScale) {
if (degree != 0) {
Log.d("zbv", "縮放有角度旋轉" + degree);
canvas.save();
canvas.rotate(degree, touch_x + touch_width / 2, touch_y + touch_height / 2);
canvas.drawRect(touch_x, touch_y, touch_right, touch_bottom, mPaint);
canvas.restore();
} else {
// Log.d("zbv","touch_right="+touch_right+";touch_bottom="+touch_bottom);
canvas.drawRect(touch_x, touch_y, touch_right, touch_bottom, mPaint);
}
} else if (isNeedRotate || isCanRotate) {
//黑色背景,白色字跡,灰色旋轉線
canvas.save();
canvas.rotate(degree, touch_x + touch_width / 2, touch_y + touch_height / 2);
//旋轉的矩形
canvas.drawRect(touch_x, touch_y, touch_x + touch_width, touch_y + touch_height, mPaint);
TIPS_WIDTH = 70;
//繪畫可旋轉的視圖
mPaint.setColor(Color.BLACK);
canvas.drawRect(touch_x + touch_width / 2 - TIPS_WIDTH / 2, touch_y - INTERVAL - TIPS_HEIGHT, touch_x + touch_width / 2 + TIPS_WIDTH / 2, touch_y - INTERVAL, mPaint);
mPaint.setColor(Color.WHITE);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float baseLine = touch_y - INTERVAL + (fontMetrics.top - fontMetrics.bottom) / 2;
canvas.drawText(degree + "°", touch_x + touch_width / 2, baseLine, mPaint);
//虛線
mPaint.setColor(Color.GRAY);
mPaint.setPathEffect(effect);
canvas.drawLine(touch_x + touch_width / 2, touch_y, touch_x + touch_width / 2, touch_y - INTERVAL, mPaint);
canvas.restore();
}
}
//記錄觸摸下的down座標
private float downX;
private float downY;
private boolean isCanMove;
private boolean isCanScale;
private boolean isCanCopy;//拷貝對象
private boolean isCanDelete;//刪除對象
// private boolean isCanEdit;
private boolean isCanRotate;
private boolean isNeedRotate;
private String scaleText;
private static final float MIN_WIDTH = 100;
private boolean isNeedShowEdit = false;//是否需要顯示編輯
public void setNeedShowEdit(boolean needShowEdit) {
isNeedShowEdit = needShowEdit;
}
private float scaleDownX;
private float scaleDonwY;
/**
* 由這個自定義背景視圖來處理操作給予反饋
* 如果第一次返回false之後再也接受不到了
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
// Log.d("zbv", "customView onTouchEvent" + event.getAction());
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (isOnlyCanMove) {
downX = event.getX();
downY = event.getY();
if (downX < touch_x || downX > (touch_x + touch_width)
|| downY < touch_y || downY > (touch_y + touch_height)) {
isCanMove = false;
//需要傳遞觸摸事件
customInterface.dismisssDraw();
return false;
} else {
isCanMove = true;
}
} else {
//使用downX和downY
scaleDownX = event.getX();
scaleDonwY = event.getY();
if (degree != 0) {
Log.d("zbv", "右旋轉角=" + degree);
float currentLocations[] = getBeforeViewLocation(degree, event.getX(), event.getY());
downX = currentLocations[0];
downY = currentLocations[1];
} else {
downX = event.getX();
downY = event.getY();
}
if (isCanRotate) {
//觸摸到旋轉線以外的地方都取消旋轉操作---設置粗一點
//增加觸摸提示旋轉角度矩形也可以觸發旋轉
if (downX > touch_x + touch_width / 2 - LineTouchW / 2 && downX < touch_x + touch_width / 2 + LineTouchW / 2
&& downY > touch_y - INTERVAL && downY < touch_y) {
Log.d("zbv", "觸摸到旋轉虛線");
isNeedRotate = true;
} else if (downX > touch_x + touch_width / 2 - TIPS_WIDTH / 2
&& downX < touch_x + touch_width / 2 + TIPS_WIDTH / 2
&& downY > touch_y - INTERVAL - TIPS_HEIGHT && downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到旋轉提示框");
isNeedRotate = true;
} else {
//取消操作
customInterface.dismisssDraw();
}
} else {
//如果觸摸到縮放區域-左上 左下 右上 右下
if ((downX > touch_x - CIRCLE_RADIUS && downX < touch_x + CIRCLE_RADIUS
&& downY > touch_y - CIRCLE_RADIUS && downY < touch_y + CIRCLE_RADIUS)) {
Log.d("zbv", "觸摸到要縮放的區域了---左上");
isCanScale = true;
scaleText = "左上";
invalidate();
} else if (downX > touch_x - CIRCLE_RADIUS && downX < touch_x + CIRCLE_RADIUS
&& downY > touch_y - CIRCLE_RADIUS + touch_height &&
downY < touch_y + CIRCLE_RADIUS + touch_height) {
Log.d("zbv", "觸摸到要縮放的區域了---左下");
isCanScale = true;
scaleText = "左下";
invalidate();
} else if (downX > touch_x - CIRCLE_RADIUS + touch_width
&& downX < touch_x + CIRCLE_RADIUS + touch_width
&& downY > touch_y - CIRCLE_RADIUS && downY < touch_y + CIRCLE_RADIUS) {
Log.d("zbv", "觸摸到要縮放的區域了---右上");
isCanScale = true;
scaleText = "右上";
invalidate();
} else if (downX > touch_x - CIRCLE_RADIUS + touch_width
&& downX < touch_x + CIRCLE_RADIUS + touch_width
&& downY > touch_y - CIRCLE_RADIUS + touch_height
&& downY < touch_y + CIRCLE_RADIUS + touch_height) {
Log.d("zbv", "觸摸到要縮放的區域了---右下");
isCanScale = true;
scaleText = "右下";
invalidate();
}
//是否觸摸到旋轉區域
else if (isNeedShowEdit) {
//顯示編輯的旋轉區域---不用修改在邊緣
if (downX > touch_x + touch_width / 2 - TIPS_WIDTH / 2 &&
downX < touch_x + touch_width / 2 + rotate_rect.width() - TIPS_WIDTH / 2 &&
downY > touch_y - INTERVAL - TIPS_HEIGHT &&
downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到可編輯的旋轉");
isCanRotate = true;
invalidate();
}
//顯示編輯的複製區域
else if (downX > touch_x + touch_width / 2 - copy_rect.width() &&
downX < touch_x + touch_width / 2 &&
downY > touch_y - INTERVAL - TIPS_HEIGHT &&
downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到可編輯的複製");
isCanCopy = true;
}
//顯示編輯的編輯區域
else if (downX > touch_x + touch_width / 2 &&
downX < touch_x + touch_width / 2 + edit_rect.width() &&
downY > touch_y - INTERVAL - TIPS_HEIGHT &&
downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到可編輯的編輯");
// isCanEdit = true;
//可以聚焦
customInterface.touchFoucusForEditText(true);
}
//顯示編輯的刪除區域
else if (downX > touch_x + touch_width / 2 + del_rect.width() &&
downX < touch_x + touch_width / 2 + TIPS_WIDTH / 2 &&
downY > touch_y - INTERVAL - TIPS_HEIGHT &&
downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到可編輯的刪除");
isCanDelete = true;
}
//是否觸摸到不操作區域
else if (downX < touch_x || downX > (touch_x + touch_width)
|| downY < touch_y || downY > (touch_y + touch_height)) {
Log.d("zbv", "觸摸到可編輯外邊了");
isCanMove = false;
//消失不可編輯
// isCanEdit=false;
customInterface.touchFoucusForEditText(false);
//需要傳遞觸摸事件
customInterface.dismisssDraw();
return false;
} else {
isCanMove = true;
}
} else if (!isNeedShowEdit) {
//不顯示編輯的旋轉區域
if (downX > touch_x + touch_width / 2 - TIPS_WIDTH / 2 &&
downX < touch_x + touch_width / 2 - copy_rect.width() / 2 &&
downY > touch_y - INTERVAL - TIPS_HEIGHT &&
downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到無編輯的旋轉");
isCanRotate = true;
invalidate();
}
//不顯示編輯的複製區域
else if (downX > touch_x + touch_width / 2 - copy_rect.width() / 2 &&
downX < touch_x + touch_width / 2 + copy_rect.width() / 2 &&
downY > touch_y - INTERVAL - TIPS_HEIGHT &&
downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到無編輯的複製");
isCanCopy = true;
} else if (downX > touch_x + touch_width / 2 + copy_rect.width() / 2 &&
downX < touch_x + touch_width / 2 + TIPS_WIDTH / 2 &&
downY > touch_y - INTERVAL - TIPS_HEIGHT &&
downY < touch_y - INTERVAL) {
Log.d("zbv", "觸摸到無編輯的刪除");
isCanDelete = true;
}
//是否觸摸到不操作區域
else if (downX < touch_x || downX > (touch_x + touch_width)
|| downY < touch_y || downY > (touch_y + touch_height)) {
Log.d("zbv", "觸摸到不可編輯外邊了");
isCanMove = false;
//需要傳遞觸摸事件
customInterface.dismisssDraw();
return false;
} else {
isCanMove = true;
}
}
}
}
break;
case MotionEvent.ACTION_MOVE:
if (isCanScale) {
//----------------可縮放 限制最小縮放大小
if (scaleText.equals("左上")) {
//top and left
//之所以使用原先的觸摸點是因爲旋轉改變了真實的觸摸點,所以要還原
touch_x += event.getX() - scaleDownX;
touch_y += event.getY() - scaleDonwY;
//必須分開,不然注意判斷
if (Math.abs(touch_right - touch_x) < MIN_WIDTH) {
touch_x = touch_right - MIN_WIDTH;
}
if (Math.abs(touch_bottom - touch_y) < MIN_WIDTH) {
touch_y = touch_bottom - MIN_WIDTH;
}
} else if (scaleText.equals("左下")) {
//bottom and left
touch_x += event.getX() - scaleDownX;
touch_bottom += event.getY() - scaleDonwY;
//必須分開,不然注意判斷
if (Math.abs(touch_right - touch_x) < MIN_WIDTH) {
touch_x = touch_right - MIN_WIDTH;
}
if (Math.abs(touch_bottom - touch_y) < MIN_WIDTH) {
touch_bottom = touch_y + MIN_WIDTH;
}
} else if (scaleText.equals("右上")) {
//top and right
touch_right += event.getX() - scaleDownX;
touch_y += event.getY() - scaleDonwY;
//必須分開,不然注意判斷
if (Math.abs(touch_right - touch_x) < MIN_WIDTH) {
touch_right = touch_x + MIN_WIDTH;
}
if (Math.abs(touch_bottom - touch_y) < MIN_WIDTH) {
touch_y = touch_bottom - MIN_WIDTH;
}
} else if (scaleText.equals("右下")) {
//bottom and right
touch_right += event.getX() - scaleDownX;
touch_bottom += event.getY() - scaleDonwY;
//必須分開,不然注意判斷
if (Math.abs(touch_right - touch_x) < MIN_WIDTH) {
touch_right = touch_x + MIN_WIDTH;
}
if (Math.abs(touch_bottom - touch_y) < MIN_WIDTH) {
touch_bottom = touch_y + MIN_WIDTH;
}
}
invalidate();
scaleDownX = event.getX();
scaleDonwY = event.getY();
} else if (isNeedRotate) {
//----------------可旋轉
//以視圖中心點爲圓心進行旋轉
double arc_1 = Math.atan2(downY - (touch_y + touch_height / 2), downX - (touch_x + touch_width / 2));
double arc_2 = Math.atan2(event.getY() - (touch_y + touch_height / 2), event.getX() - (touch_x + touch_width / 2));
double angle_1 = Math.toDegrees(arc_1);
double angle_2 = Math.toDegrees(arc_2);
// Log.d("zbv","angle_1="+angle_1+";angle_2="+angle_2);
degree = (int) Math.round(angle_2 - angle_1);
if (degree > 180.0f) {
degree -= 360.0f;
}
invalidate();
} else if (isCanMove) {
//----------------可移動
touch_x = touch_x + event.getX() - downX;
touch_y = touch_y + event.getY() - downY;
//設置移動邊界防止越界看不見
if (touch_x <= 0) {
touch_x = 0;
} else if (touch_x >= (getWidth() - touch_width)) {
touch_x = getWidth() - touch_width;
}
if (touch_y <= 0) {
touch_y = 0;
} else if (touch_y >= (getHeight() - touch_height)) {
touch_y = getHeight() - touch_height;
}
// Log.d("zbv","touch_x="+touch_x+";touch_y="+touch_y);
invalidate();
//必須重置觸摸點
downX = event.getX();
downY = event.getY();
}
break;
case MotionEvent.ACTION_UP:
if (isCanRotate) {
if (isNeedRotate) {
isCanRotate = false;
isNeedRotate = false;
customInterface.updateViewRotateLocation(degree);
//取消bg繪製
customInterface.dismisssDraw();
}
} else {
//縮放重置
if (isCanScale) {
isCanScale = false;
customInterface.updateViewScaleLocation((int) touch_x, (int) touch_y, (int) touch_right, (int) touch_bottom);
}
//跟新視圖的移動位置
if (isCanMove) {
isCanMove = false;
customInterface.updateViewMoveLocation((int) touch_x, (int) touch_y);
}
//取消bg繪製
customInterface.dismisssDraw();
//執行拷貝
if (isCanCopy) {
isCanCopy = false;
customInterface.copyOnceView();
}
//執行刪除
if (isCanDelete) {
isCanDelete = false;
customInterface.deleteOnceView();
}
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
}
return true;
}
/*
爲了處理canvas旋轉導致的視圖屬性沒有變化從而使得觸摸點的無法生效
所以反推原始點即:知道圓點、和旋轉後的點以及角度--->推導出旋轉前的點
*/
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 - (touch_x + touch_width / 2)) * cos - (dot_y - (touch_y + touch_height / 2)) * sin + touch_x + touch_width / 2;
locations[1] = (dot_y - (touch_y + touch_height / 2)) * cos + (dot_x - (touch_x + touch_width / 2)) * sin + touch_y + touch_height / 2;
return locations;
}
//----------------------------
private CustomInterface customInterface;
public void setCustomInterface(CustomInterface customInterface) {
this.customInterface = customInterface;
}
public interface CustomInterface {
void dismisssDraw();
void updateViewMoveLocation(int x, int y);
void updateViewScaleLocation(int x, int y, int right, int bottom);
void updateViewRotateLocation(int degree);
void touchFoucusForEditText(boolean isFoucus);
void copyOnceView();
void deleteOnceView();
}
}
後續功能增加以及優化、demo例子使用更新中。。。