安卓 实现滑动效果
实现滑动效果有下面几种方式
1.layout(int l, int t, int r, int b):
1).参数:分别代表左上右下四个点的坐标
2).View绘制时,会通过onLayout方法设置显示位置,我们也可用通过layout函数调用onLayout方法
2.offsetLeftAndRight(int offset)与offsetTopAndBottom(int offset)
1).参数:offset分别代表左右和上下的的偏移量
2).这两个函数分别是同时对左右和上下偏移
3.scrollTo(int x, int y)
1).参数:移动到(x,y) 坐标点
scrollBy(int x, int y)
1).参数:移动增量为dx,dy
注意:
1)scrollTo和scrollBy移动的是View的内容content,如果是TextView则移动文本,如果是ImageView则移动drawable
2)这两者填写的参数都要为负值,图解如下
4.Scroller:实现了View从移动的过度动画,而不是一瞬间完成,其实scrollBy和scrollTo都是瞬间完成的,由于我们在ACTION_MOVE中不断获取手指位移量,所以看上去有过度效果
下面来分别实现
一、重写触摸事件
要实现滑动、触摸等效果,都要重写触摸事件onTouchEvent
几个获取坐标的方法:
View提供的方法
MotionEvent提供的方法geTop: 得到View自身顶边到父布局顶边的距离
getBottom: 得到View自身底边到父布局顶边的距离
getLeft: 等到VIew自身左边到父布局左边的距离
getRight: 等到VIew自身右边到父布局左边的距离
getX: 得到点击事件距离View左边的距离,视图坐标
getY 得到点击事件距离View顶边的距离,视图坐标
getRawX 得到点击事件距离屏幕顶边的距离 ,绝对坐标
getRawY: 得到点击事件距离屏幕顶边的距离,绝对坐标
@Override public boolean onTouchEvent(MotionEvent event) { //得到当前坐标 //视图坐标 int x = (int)event.getX(); int y = (int)event.getY(); //绝对坐标 int rawX = (int)event.getRawX(); int rawY = (int)event.getRawY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: //记录按下的坐标点 lastX = x; lastY = y; //lastX = rawX; //lastY = rawY; Log.e(TAG, "ACTION_DOWN: X="+x+";Y="+y ); break; case MotionEvent.ACTION_MOVE: //用最新坐标(滑动触摸的坐标)减去第一次按下的坐标 //这样就得到了最新的偏移量 int offsetX = x - lastX; int offsetY = y - lastY; //int offsetX = rawX - lastX; //int offsetY = rawY - lastY; //之后通过偏移量更新视图位置 。。。下面介绍 Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY ); break; case MotionEvent.ACTION_UP: Toast.makeText(getContext(),"Up",Toast.LENGTH_SHORT).show(); break; } return true; }
二、实现移动
1.layout(int l, int t, int r, int b):
更改上面代码:
case MotionEvent.ACTION_MOVE:
//用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
//这样就得到了最新的偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
//之后通过偏移量更新视图位置
layout(
getLeft() + offsetX,
getTop() + offsetY,
getRight() + offsetX,
getBottom() + offsetY
);
Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
break;
2.offsetLeftAndRight(int offset)与offsetTopAndBottom(int offset)
更改上面代码:
case MotionEvent.ACTION_MOVE:
//用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
//这样就得到了最新的偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
//同时对左右、上下移动
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
break;
初始界面:
方法一二的效果一致:如下
当然同样也可以使用绝对坐标,不过要注意绝对坐标中,要在ACTION_MOVE中重置初始坐标
代码:
@Override
public boolean onTouchEvent(MotionEvent event) {
//得到当前坐标
//视图坐标
int x = (int)event.getX();
int y = (int)event.getY();
//绝对坐标
int rawX = (int)event.getRawX();
int rawY = (int)event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//记录按下的坐标点
lastX = rawX;
lastY = rawY;
Log.e(TAG, "ACTION_DOWN: X="+x+";Y="+y );
break;
case MotionEvent.ACTION_MOVE:
//用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
//这样就得到了最新的偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
//之后通过偏移量更新视图位置
//同时对左右、上下移动
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
//更新初始坐标
lastX = rawX;
lastY = rawY;
Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
break;
case MotionEvent.ACTION_UP:
Toast.makeText(getContext(),"Up",Toast.LENGTH_SHORT).show();
break;
}
return true;
}
3.scrollTo(int x, int y)和scrollBy
这个就不一样了,因为移动的是内容
更改代码如下:View内容移动
case MotionEvent.ACTION_MOVE:
//用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
//这样就得到了最新的偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
//View的内容移动
scrollTo(-offsetX,-offsetY);
Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
break;
效果:
更改代码如下:View父布局移动
case MotionEvent.ACTION_MOVE:
//用最新坐标(滑动触摸的坐标)减去第一次按下的坐标
//这样就得到了最新的偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
//移动View的父布局
((View)getParent()).scrollBy(-offsetX,-offsetY);
Log.e(TAG, "ACTION_MOVE: offsetX="+offsetX+";offsetY="+offsetY );
break;
效果:
4.Scroller:实现过渡动画,在ACTION_UP中实现抬起手指,控件自己返回的效果
1)首先实例化Scroller
scroller = new Scroller(context);
2)重写computeScroll
系统在绘制View的draw方法中会调用这个方法
重写computeScroll实现模拟移动
@Override
public void computeScroll() {
super.computeScroll();
//判断Scrolle是否执行完毕
if (scroller.computeScrollOffset()){
((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
//重绘
invalidate();
}
}
computeScrollOffset: 判断是否完成了整个滑动
getCurrX: 得到当前的互动坐标X
getCurrY: 得到当前的互动坐标Y
由于computeScroll不会自己调用,所以需要invalidate来实现从invalidate->draw->computeScroll的间接调用
3)开始模拟滑动
startScroll(int startX, int startY, int dx, int dy, int duration) :
参数:(startX,startY)起始坐标,dx,dy分别是x轴和y轴的偏移量,最后是滑动完成的时间,可以省略
在ACTION_UP中开始,实现手指抬起,View返回原坐标位置
case MotionEvent.ACTION_UP:
Toast.makeText(getContext(),"Up",Toast.LENGTH_SHORT).show();
View view = ((View)getParent());
scroller.startScroll(
view.getScrollX(),
view.getScrollY(),
-view.getScrollX(),
-view.getScrollY(),
3000
);
invalidate();
break;
invalidate();发出重绘信号
效果;
上一篇: opencv形态学操作,提取水平与垂直线
下一篇: 安卓轮播图片的实现