1、Android中获取坐标的方法
1)View提供的方法
getTop:view自身的顶边到父布局顶边的距离
getLeft:view的左边到父布局的左边
getRight:view的右边到父布局的左边
getBottom:view底边到父布局的顶边
2)MotionEvent提供的方法
getX:点击事件到控件左边
getY:点击事件到控件顶边
getRawX:获取点击事件的绝对X坐标
getRawY:获取点击事件的绝对Y坐标
2、实现滑动的七种方法
1)layout方法
修改上下左右四个坐标
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
//在当前left、top、right、bottom家上偏移量
layout(getLeft()+offsetX, getTop()+offsetY, getRight()+offsetX,getBottom()+offsetY);
//重设初始坐标
lastX = rawX;
lastY = rawY;
break;
}
return true;
}
2)offsetLestAndRight与offsetTopAndBottom
同理layout方法,改变上下左右四个坐标
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
//offsetLeftAndRight和offsetTopAndBottom方法
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
//重设初始坐标
lastX = rawX;
lastY = rawY;
break;
}
return true;
}
3)LayoutParams
改变左外边距和右外边距来实现滑动
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft() + offsetX;
layoutParams.topMargin = getTop() + offsetY;
setLayoutParams(layoutParams);
/**
* 不用考虑父布局类型的写法
* ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
* layoutParams.leftMargin = getLeft() + offestX;
* layoutParams.topMargin = getTop() + offsetY;
* setLayoutParams(layoutParams);
*/
//重设初始坐标
lastX = rawX;
lastY = rawY;
break;
}
return true;
}
4)scrollTo和scrollBy
指的是view的内容的移动,也就是说对于TextView就是移动里面的文字,想要移动TextView本身就要让其父布局调用此方法。scrollTo一般传入绝对坐标,scrollBy一般传入偏移量。另外,记住,这两个方法都是进行反向移动,想要达到自己目的,就要对参数进行变换。
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
//scrollTo适用于绝对坐标,scrollBy适用于偏移量,并且都是移动View的内容
//偏移量取反
((View) getParent()).scrollBy(-offsetX, -offsetY);
//重设初始坐标
lastX = rawX;
lastY = rawY;
break;
}
return true;
}
5)Scroller
平滑移动,主要重写了View的computeScroll方法
下面的代码,不仅实现滑动,也实现了松手后滑回原位置
final Scroller mScroller = new Scroller(this);
View view5 = new View(this) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(200, 100);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.GREEN);
}
@Override
public void computeScroll() {
super.computeScroll();
//判断Scroller是否执行完毕
if (mScroller.computeScrollOffset()) {
((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//通过不断重绘来不断调用computeScroll
invalidate();
}
}
int lastX, lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录触摸点坐标
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
//计算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
((View) getParent()).scrollBy(-offsetX, -offsetY);
//重设初始坐标
lastX = rawX;
lastY = rawY;
break;
//加入效果,手指离开时,执行滑动过程
case MotionEvent.ACTION_UP:
View viewGroup = (View) getParent();
mScroller.startScroll(viewGroup.getScrollX(), viewGroup.getScrollY(), -viewGroup.getScrollX(), -viewGroup.getScrollY());
invalidate();
break;
}
return true;
}
};
6)属性动画实现
推荐阅读:Android动画
7)ViewDragHelper
非常强大,侧滑组件就是用此来实现的。
- 初始化ViewDragHelper
第一个参数为父布局,第二个参数为回调,是核心所在
mViewDragHelper = ViewDragHelper.create(this, callBack);
- 接下来就实现回调
private ViewDragHelper.Callback callBack = new ViewDragHelper.Callback() {
//何时开始检测触摸事件
@Override
public boolean tryCaptureView(View child, int pointerId) {
//如果当前触摸的child是mMainView时开始检测
return mMainView == child;
}
//处理垂直滑动
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
//处理水平滑动
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
//拖动结束后调用
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//手抬起后缓慢移动到指定位置
if (mMainView.getLeft() < 500) {
//关闭菜单
//相当于Scroller的startScroll方法
mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
} else {
//打开菜单
mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}
};
- 拦截事件。因为滑动效果,总是会事件分发机制相关,所以ViewDragHelper会处理相应的事件。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mViewDragHelper.processTouchEvent(event);
return true;
}
- 最后处理computeScroll,因为ViewDragHelper内部也是用scroller实现平滑移动
@Override
public void computeScroll() {
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}