坐标系与视图坐标系相辅相成
-
坐标系:描述了view在屏幕中的位置关系(以屏幕最左上角的顶点作为android坐标系的原点)
-
视图坐标系:描述了子视图在父视图中的位置关系(以父视图最左上角为坐标系原点)
获取坐标值的方法
1.view提供的获取坐标方法
- gettop():获取到的是view自身的顶边到其父布局顶边的距离
- getleft():获取到的是view自身的左边到其父布局顶边的距离
- getright():获取到的是view自身的右边到其父布局顶边的距离
- getbottom():获取到的是view自身的底边到其父布局顶边的距离
2. motionevent提供的方法
- getx():获取点击事件距离控件左边的距离,即视图坐标
- gety():获取点击事件距离控件顶边的距离,即视图坐标
- getrawx():获取点击事件距离整个屏幕左边的距离,即绝对坐标
- getrawy():获取点击事件距离整个屏幕右边的距离,即绝对坐标
实现滑动的七种方法
1.layout方法
case motionevent.action_move:
//计算偏移量
int offsetx=x-lastx;
int offsety=y-lasty;
layout(getleft()offsetx,gettop()offsety,getright()offsetx,getbottom()offsety);
break;
2.offsetleftandright()与 offsettopandbottom()
offsetleftandright(offsetx);
offsettopandbottom(offsety);
3.layoutparams
linearlayout.layoutparams params= (linearlayout.layoutparams) getlayoutparams();
params.leftmargin= getleft()offsetx;
params.topmargin= gettop()offsety;
setlayoutparams(params);
4.scrollby()与scrollto()
- scrollby(x,y)表示移动到一个具体的位置
- scrollto(dx,dy)表示移动的增量为dx,dy
int offsetx=x-lastx;
int offsety=y-lasty;
view parent= (view) getparent();
parent.scrollby(-offsetx,-offsety);
5.scroller
通过scroller类可以实现平滑移动的效果,而不是瞬间完成的效果,与动画的实现原理基本相似
@override
public void computescroll() {
super.computescroll();
//判断scroller是否执行完毕
if (scroller.computescrolloffset()){
view view= (view) getparent();
//获得当前的滑动坐标
view.scrollto(scroller.getcurrx(),scroller.getcurry());
//通过重绘来不断调用computescroll
invalidate();
//invalidate()--->draw()---->computescroll()
}
}
case motionevent.action_up:
//手指离开时,执行滑动过程
view viewgroup= (view) getparent();
scroller.startscroll(
viewgroup.getscrollx(),
viewgroup.getscrolly(),
-viewgroup.getscrollx(),
-viewgroup.getscrolly(),500);
invalidate();
break;
6.属性动画
7.viewdraghelper 类
public class drawgroup extends framelayout {
private viewdraghelper helper;
private view mainview,menuview;
public drawgroup(@nonnull context context) {
super(context);
inview();
}
public drawgroup(@nonnull context context, @nullable attributeset attrs) {
super(context, attrs);
inview();
}
public drawgroup(@nonnull context context, @nullable attributeset attrs, int defstyleattr) {
super(context, attrs, defstyleattr);
inview();
}
private void inview(){
helper=viewdraghelper.create(this, new viewdraghelper.callback() {
@override
public boolean trycaptureview(@nonnull view child, int pointerid) {
//如果当前触摸的child是mainview时开始检测
return child==mainview;
}
@override
public int clampviewpositionhorizontal(@nonnull view child, int left, int dx) {
//水平方向上的滑动
return left;
}
@override
public int clampviewpositionvertical(@nonnull view child, int top, int dy) {
//垂直方向上的滑动
return 0;
}
@override
public void onviewreleased(@nonnull view releasedchild, float xvel, float yvel) {
//拖动结束后调用
super.onviewreleased(releasedchild, xvel, yvel);
//手指抬起后缓慢移动到指定位置
if (mainview.getleft()<300){
//关闭菜单
helper.smoothslideviewto(mainview,0,0);
//相当于scroller的startscroll方法
}else {
//打开菜单
helper.smoothslideviewto(mainview,300,0);
}
viewcompat.postinvalidateonanimation(drawgroup.this);
}
});
}
@override
public boolean onintercepttouchevent(motionevent ev) {
return helper.shouldintercepttouchevent(ev);
}
@override
public boolean ontouchevent(motionevent event) {
//将触摸事件传递给viewdraghelper,此操作必不可少
helper.processtouchevent(event);
return true;
}
@override
public void computescroll() {
if (helper.continuesettling(true)){
viewcompat.postinvalidateonanimation(this);
}
}
@override
protected void onfinishinflate() {
super.onfinishinflate();
//加载完布局调用
menuview=getchildat(0);
mainview=getchildat(1);
}
@override
protected void onsizechanged(int w, int h, int oldw, int oldh) {
super.onsizechanged(w, h, oldw, oldh);
}
}
- onviewcaptured():在用户触摸到view后回调
- onviewdragstatechanged():在拖拽状态改变时回调(idle,dragging…)
- onviewpositionchanged():在位置改变时回调,常用于滑动时更改scale进行缩放等效果