一个可以拖动,缩放的相对布局,真正写起来还是很简单的。
public class MoveZoomRelativeLayout extends RelativeLayout {
//event.actiondown发生的坐标
private float oldX;
private float oldY;
//布局的宽高
private int mwidth;
private int mheight;
//触摸模式
private int TOUCHMODE = 0;
private int DRAGMODE = 0;
private int ZOOMMODE = 1;
//布局各边到绝对坐标系的距离
private int left;
private int right;
private int top;
private int bottom;
//上次移动事件发生的坐标
private float premoveX;
private float premoveY;
private float oldrawX;
private float oldrawY;
//接口对象
private GetSizeInterface getsizeinterface;
private Context context;
//是否禁止触摸
private boolean disallowtouch;
private int screenwidth;
private int screenheight;
public MoveZoomRelativeLayout(Context context) {
super(context);
}
public MoveZoomRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private void init() {
//获取屏幕的宽高
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
screenwidth = displayMetrics.widthPixels;
screenheight = displayMetrics.heightPixels;
//获取布局的宽高
// int width = getWidth();
// int height = getHeight();
// int left = (widthPixels - width) / 2;
// int top = (heightPixels - height) / 2;
// LayoutParams layoutParams = (LayoutParams) getLayoutParams();
// layoutParams.setMargins(left,top,left + width, top + height);
// setLayoutParams(layoutParams);
// layout(left, top, left + width, top + height);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!disallowtouch) {
mwidth = getWidth();
mheight = getHeight();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
oldX = event.getX();
oldrawX = event.getRawX();
oldY = event.getY();
oldrawY = event.getRawY();
//设置布局的中间长宽各80%的区域为可移动区域,其余部分为可拉伸区域。
if (oldX < mwidth * 0.2 || oldX > mwidth * 0.8 || oldY < mheight * 0.2 || oldY > mheight * 0.8) {
TOUCHMODE = ZOOMMODE;
} else {
TOUCHMODE = DRAGMODE;
}
left = getLeft();
right = getRight();
top = getTop();
bottom = getBottom();
break;
case MotionEvent.ACTION_MOVE:
if (TOUCHMODE == DRAGMODE) {
float neweventX = event.getX();
float neweventY = event.getY();
int moveX = ((int) (neweventX - oldX));
int moveY = ((int) (neweventY - oldY));
Log.i(TAG, "onTouchEvent: drag" + moveX + ";" + moveY);
//该方法移动view,弹出输入法就会导致位置复原
// layout(getLeft() + moveX, getTop() + moveY, getRight() + moveX, getBottom() + moveY);
LayoutParams layoutParams = (LayoutParams) getLayoutParams();
layoutParams.setMargins(getLeft() + moveX, getTop() + moveY, 0, 0);
setLayoutParams(layoutParams);
left = getLeft();
right = getRight();
top = getTop();
bottom = getBottom();
}
if (TOUCHMODE == ZOOMMODE) {
float newrawX = event.getRawX();
float newrawY = event.getRawY();
//注释掉的方法应该也是可行的,但是未测试了
// float neweventX = event.getX();
// float neweventY = event.getY();
// if (premoveX == 0 && premoveY == 0) {
// int moveX = (int) (neweventX - oldX);
// int moveY = (int) (neweventY - oldY);
// Log.i(TAG, "onTouchEvent: 0zoom" + moveX + ";" + moveY);
// LayoutParams layoutParams = (LayoutParams) getLayoutParams();
// layoutParams.width = mwidth + moveX;
// layoutParams.height = mheight + moveY;
// setLayoutParams(layoutParams);
// layout(left, top, right, bottom);
// premoveX = neweventX;
// premoveY = neweventY;
if (premoveX == 0 && premoveY == 0)
//这里判断premoveX和premoveY来选择使用哪种方式计算缩放大小是因为,oldrawX和oldrawY
//只会在触发down时改变,所以连续滑动时这2个值是不准确的导致缩放的速度越来越快
int moveX = (int) (newrawX - oldrawX); int moveY = (int) (newrawY - oldrawY); Log.i(TAG, "onTouchEvent: 0zoom" + moveX + ";" + moveY); LayoutParams layoutParams = (LayoutParams) getLayoutParams();
//这里的判断有点问题,因为都是且判断,所以导致宽或者高不满足另外一者也不能改变
//当2个都不满足时(其实很难哦),只改变一者也无法改变布局了,但由于判断的是计算之后的大小
//是否符合条件,因此不会卡死.
if (mwidth + moveX > screenwidth * 0.2 && mwidth + moveX < screenwidth * 0.8 && mheight + moveY > screenheight * 0.2 && mheight + moveY < screenheight * 0.8) { layoutParams.width = mwidth + moveX; layoutParams.height = mheight + moveY; layoutParams.setMargins(getLeft(), getTop(), 0, 0); setLayoutParams(layoutParams);// layout(left, top, right, bottom); premoveX = newrawX; premoveY = newrawY; getsizeinterface.getSize(layoutParams.width, layoutParams.height); } } else { //注释掉的方法应该也是可行的,但是未测试了// int moveX = (int) (neweventX - premoveX);// int moveY = (int) (neweventY - premoveY);// Log.i(TAG, "onTouchEvent: zoom" + moveX + ";" + moveY);// LayoutParams layoutParams = (LayoutParams) getLayoutParams();// layoutParams.width = mwidth + moveX;// layoutParams.height = mheight + moveY;// setLayoutParams(layoutParams);// layout(left, top, right, bottom);// premoveX = neweventX;// premoveY = neweventY; int moveX = (int) (newrawX - premoveX); int moveY = (int) (newrawY - premoveY); Log.i(TAG, "onTouchEvent: zoom" + moveX + ";" + moveY); LayoutParams layoutParams = (LayoutParams) getLayoutParams(); if (mwidth + moveX > screenwidth * 0.2 && mwidth < screenwidth * 0.8 && mheight + moveY > screenheight * 0.2 && mheight + moveY < screenheight * 0.8) { layoutParams.width = mwidth + moveX; layoutParams.height = mheight + moveY; layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, 0, 0); setLayoutParams(layoutParams);// layout(left, top, right, bottom); premoveX = newrawX; premoveY = newrawY; getsizeinterface.getSize(layoutParams.width, layoutParams.height); } } } break; case MotionEvent.ACTION_UP: premoveY = 0; premoveX = 0; break; default: break; } return true; } return false; } @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (hasWindowFocus) { } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return false; } //通过该接口实时的把布局的宽高传递出去 public interface GetSizeInterface { void getSize(int width, int height); } public void setInterface(GetSizeInterface getsizeinterface) { this.getsizeinterface = getsizeinterface; } public void setdisallowtouch(boolean b) { this.disallowtouch = b; }}