getTop(): 获取到的是View自身的顶边到其父布局顶边的距离
getLeft(): 获取到的是View自身的左边到其父布局左边的距离
getRight(): 获取到的是View自身的右边到其父布局左边的距离
getBottom(): 获取到的是View自身的底边到其父布局顶边的距离
getX(): 获取点击事件距离控件左边的距离,即视图坐标
getY(): 获取点击事件距离控件顶边的距离,即视图坐标
getRawX(): 获取点击事件距离整个屏幕左边的距离,即绝对坐标
getRawY(): 获取点击事件距离整个屏幕顶边的距离,即绝对坐标
在View进行绘制时,会调用onLayout()方法来设置显示的位置。可以通过修改View的left、top、right、bottom四个属性来控制View的坐标。
layout(left+offsetX,top+offsetY,right+offsetX,bottom+offsetY) = offsetLeftAndRight(offsetX), offsetTopAndBottom(offsetY)。
通过getLayoutParams()获取LayoutParams时,需要根据view所在父布局的类型来设置不同的类型。如果父布局是LinearLayout,就可以使用LinearLayout.LayoutParams。如果父布局是RelativeLayout,就可以使用RelativeLayout.LayoutParams。前提是有一个父布局,不然系统无法获取LayoutParams。
使用ViewGroup.MarginLayoutParams更加的方便,不需要考虑父布局的类型,当然他们的本质都是一样的。
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)getLayoutParams();
layoutParams.leftMargin = getLeft() + offsetX;
layoutParams.topMargin = getTop() + offsetY;
setLayoutParams(layoutParams);
scrollTo(x,y)表示移动到一个具体的坐标点(x,y),而scrollBy(dx,dy)表示移动的增量为dx,dy。
scrollTo、scrollBy方法移动的是View的content,即让View的内容移动。如果在ViewGroup中使用scrollTo、scrollBy方法,那么移动的将是所有子View。

当我们调用scrollBy(20,10)移动的时候,效果如下:

这是为什么呢?
虽然设置scrollBy(20,10),偏移量均为X轴,Y轴正方向的正数,但是在屏幕的可视区域内,Button却向X轴,Y轴负方向上移动了,这就是因为参考下选择的不同,而产生的不同效果。
scrollTo还是scrollBy,子View的移动都是瞬时完成的,Scroller就是为了实现平滑移动的效果,而不是瞬间完成的移动。使用Scroller需要如下三个步骤:
mScroller = new Scroller(context);
重写computeScroll()方法,实现模拟滑动
@Override
public void computeScroll(){
super.computeScroll();
if(mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getSurrY(),mScroller.getCurrY());
invalidate();
}
}
startScroll开启模拟过程
public void startScroll(int startX,int startY,int dx,int dy,int duration)
public void startScroll(int startX,int startY,int dx,int dy)
初始化ViewDragHelper
mViewDragHelper = ViewDragHelper.create(this,callback);
拦截事件
@Override
public boolean onInterceptTouchEvent(MotionEvent ev){
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event){
mViewDragHelper.processTouchEvent(event);
return true;
}
处理computeScroll()
@Override
public void computeScroll(){
if(mViewDragHelper.continueSettling(true)){
ViewCompat.postInvalidateOnAnimation(this);
}
}
处理回调Callback
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback(){
@Override
public boolean tryCaptureView(View child,int pointerId){
//如果当前触摸的child是mMainView时开始检测
return mMainView == child;
}
};
clampViewPositionHorizontal(View child,int left,int dx)和clampViewPositionVertical(View child,int top,int dy)。