之前1 写了很多都删了,2完善了一下,保留思路,
1.三个构造函数,获取了宽高
public DragScaleLinearLayout(Context context) {
this(context, null);
}
public DragScaleLinearLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DragScaleLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
DisplayMetrics dm = getResources().getDisplayMetrics();
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels;
// init();
}
2.有些方法都没动
onMeasure,onLayout,dispatchTouchEvent
3.之前onTouch里判断触摸点是否在view范围内的方法出错了,替换为
// 判断触摸点是否在View的范围内的方法
private boolean isTouchInsideView(View view, float x, float y) {
// 创建一个Rect对象,表示View在屏幕中的矩形区域
Rect rect = new Rect();
view.getGlobalVisibleRect(rect);
// 判断触摸点是否在矩形区域内
return rect.contains((int) x, (int) y);
}
下面是之前的检测是否在view范围的方法
/**
* 计算指定的 View 在屏幕中的坐标。
* 注意这个值是要从屏幕顶端算起,也就是索包括了通知栏的高度
* location[0] x坐标
* location[1] y坐标
* view.getWidth(), 到父布局宽度的位置
* 重点: 旋转后 View.getLocationOnScreen() 等返回的 View 的位置坐标还是以 View 原先左上角返回的旋转后的坐标值
* 这个方法不知道为什么不行了,换成了 isTouchInsideView
*/
public static RectF calcViewScreenLocation(View view) {
int[] location = new int[2];
// 获取当前焦点所在屏幕中的位置 view.getLocationOnScreen(location)
// 获取控件在屏幕中的位置,返回的数组分别为控件左顶点的 x、y 的值
view.getLocationOnScreen(location);
return new RectF(location[0], location[1], location[0] + view.getWidth(),
location[1] + view.getHeight());
}
// * 这个方法不知道为什么不行了,换成了 isTouchInsideView
public static RectF calcViewScreenLocation2(View view) {
int[] location = new int[2];
// 获取当前焦点所在屏幕中的位置 view.getLocationOnScreen(location)
// 获取控件在屏幕中的位置,返回的数组分别为控件左顶点的 x、y 的值
view.getLocationOnScreen(location);
return new RectF(location[0] - view.getWidth(), location[1], location[0],
location[1] + view.getHeight());
}
4.onTouchEvent 方法
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
lastX = ev.getRawX();//设定移动的初始位置相对位置
lastY = ev.getRawY();
// 触摸 iv_move 移动
// RectF rect = calcViewScreenLocation2(ivMove);
// mMove = rect.contains(lastX, lastY);
mMove = isTouchInsideView(ivMove, lastX, lastY);
// RectF rect2 = calcViewScreenLocation2(ivResize);
// isInViewRect = rect2.contains(lastX, lastY);
isInViewRect = isTouchInsideView(ivResize, lastX, lastY);
Log.e(TAG, "onTouchEvent: " + mMove + "___" + isInViewRect);
break;
case MotionEvent.ACTION_MOVE:
//移动//移动的距离X
float dx = ev.getRawX() - lastX;
float dy = ev.getRawY() - lastY;
if (!isInViewRect && mMove) {
moveView((int) dx, (int) dy);
} else {
//放大缩小 params.width =-1 //源码里看下就知道了。。 -1不代表宽度,代表MATCH_PARENT常量的值
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) getLayoutParams();
if (rotation) {
params.height = (int) Math.max(params.height - dx, 400);
params.width = (int) Math.max(getWidth() + dy, 400);
} else {
params.height = (int) Math.max(params.height + dy, 400);
params.width = (int) Math.max(getWidth() + dx, 400);
}
setLayoutParams(params);
}
lastX = (int) ev.getRawX();
lastY = (int) ev.getRawY();
break;
case MotionEvent.ACTION_UP:
requestLayout();
break;
default:
break;
}
return isInViewRect ? isInViewRect : mMove;
}
5.下面是move方法
private void moveView(int dx, int dy) {
//设置控件的新位置 移动
// this.layout(left, top, right, bottom);
//再次将滑动其实位置定位
//理论中X轴拖动的距离
float endX = getX() + dx;
//理论中Y轴拖动的距离
float endY = getY() + dy;
//X轴可以拖动的最大距离
float maxX = mRootMeasuredWidth - getWidth();
//Y轴可以拖动的最大距离
float maxY = mRootMeasuredHeight - getHeight();
//X轴边界限制
endX = endX < 0 ? 0 : Math.min(endX, maxX);
//Y轴边界限制
endY = endY < 0 ? 0 : Math.min(endY, maxY);
setX(endX);
setY(endY);
}