1. 实现滑动的三种方式
- 通过View本身提供的scrollTo/scrollBy方法
- 通过动画给View施加平移效果
- 通过改变View的LayoutParams使得View重新布局,实现滑动
2. scrollTo/scrollBy
使用:
view.scrollTo(200,200);
view.scrollBy(200,200);
源码:
public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
postInvalidateOnAnimation();
}
}
}
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}
scrollBy实际上是调用了scrollTo方法,他实现的是相对滑动;而scrollTo实现的是绝对滑动。
在滑动过程中,mScrollX的值总是等于View的左边缘和View的内容的左边缘在水平方向的距离,而mScrollY的值等于View上边缘和View内容的上边缘的竖直距离。
View的边缘指View的位置。内容边缘指View中的内容的边缘。scrollTo/scrollBy只能改变View的内容边缘,而不能改变View在布局中的位置。mScrollX和mScrollY的单位是像素,是有正负的。起始位置-终点位置的结果值就是scrollX和scrollY的值,是正就是正,是负就是负。也就是当View左边缘在View内容左边缘的右边时,mScrollX为正。反之为负。
3. 使用动画
objectAnimator = ObjectAnimator.ofFloat(view,"translationX",0,500).setDuration(5000);
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
Log.e("aaa", "x=" + view.getX() + ",y=" + view.getY() + ",translationX=" + view.getTranslationX() + ",translationY=" + view.getTranslationY());
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("aaa", "x=" + view.getX() + ",y=" + view.getY() + ",translationX=" + view.getTranslationX() + ",translationY=" + view.getTranslationY());
objectAnimator.start();
}
});
动画启动前打印x,translationX的值,动画结束后,也打印他们的值如下:
x=30.0,y=30.0,translationX=0.0,translationY=0.0
x=530.0,y=30.0,translationX=500.0,translationY=0.0
前文说过
x=left + translationX
3.0以上的属性动画其位置是随着动画移动了的,而3.0以下的机器由于不支持属性动画,所以位置不随着动画移动,这是动画的主要缺点。
4. 改变布局参数
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) view.getLayoutParams();
lp.width+=100;
lp.leftMargin+=100;
view.requestLayout();
// 或者 view.setLayoutParams(lp);
5. 三种方式的比较
- scrollTo/scrollBy:操作简单,适合对View内容的滑动
- 动画:操作简单,主要用于没有交互的View或者复杂动画。
- 改变参数布局:操作稍微复杂,适用于有交互的Veiw
6. 小栗子
public class DemoButton extends Button {
int mLastX, mLastY;
public DemoButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
int deltaX = x - mLastX;
int deltaY = y - mLastY;
int translationX = (int) getTranslationX() + deltaX;
int translationY = (int) getTranslationY() + deltaY;
setTranslationX(translationX);
setTranslationY(translationY);
break;
}
mLastX = x;
mLastY = y;
return true;
}
}
这个例子其实不用动画,因为move的响应非常快,已经达到了动画要求的梯度值,所以直接设置其值就可以。