实现view滑动的方法:
一、layout方法
在View绘制的时候,系统都会调用layout(int l, int t, int r, int b)
方法来确定View的具体位置。既然这样来,那么我们也可以通过调用layout(int l, int t, int r, int b)`方法修改left,top,right,bottom这四个属性来控制View的位置。
首先写一个自定义类继承view,重写onToucnEvent()
方法;
public class LayoutView extends View {
private int lastX,lastY;
public LayoutView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LayoutView(Context context) {
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 记录触摸点坐标
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
// 计算偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
break;
}
return true;
}
}
然后再布局中使用LayouView,最后效果如图:
二、offsetLeftAndRight和offsetTopAndBottom
这两个方法是系统提供对左右,上下移动api的封装,当计算出偏移量后,只需要调用一下两个方法就可以完场重新布局,
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
//同时对left和right进行偏移
offsetLeftAndRight(offsetX);
//同时对top和bottom进行偏移
offsetTopAndBottom(offsetY);
break;
这里的offsetX,和offsetY的计算方法和第一种方法相同,这里就不多解释
三、LayoutParams
通过改变View的LayoutParams布局参数,就可以移动View的位置,这里通常修改View的Margin属性,代码如下:
private int lastX,lastY;
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
params.leftMargin = getLeft() + offsetX;
params.topMargin = getTop() + offsetY;
break;
}
return true;
}
四、ScrollTo 和ScrollBy
上面的方法都是移动View自己本身,而第四种方法移动的是view的内容,如果放在ViewGroup中使用,则移动的是ViewGroup里面所有的子View。
scrollTo(x,y) : 移动到 (x,y) 这个坐标点
scrlollBy(dx,dy) : 移动的增量为 dx,dy。
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
//scroll方法移动的是View的父布局,因此,子View相对于父布局移动,相当于父布局取反移动
((View)getParent()).scrollBy(-offsetX,-offsetY);
break;
五、Scroller
Scroll本身无法让View滑动,它需要和View的computeScroll方法配合才能使用
//(1)创建Scroller类
Scroller scroller =new Scroller(mContext);
//(2)重写computeScroll方法
@Override
public void computeScroll(){
// 判断Scroller滑动是否执行完毕
if(mSroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX().mScroller.getCurrY());
// 通过重绘让系统调用onDraw,onDraw中又会调用computeScroll,如此不断循环,直到Scroller执行完毕
postInvalidate();
}
}
//(3)调用Scroller类的startScroll方法开启滚动过程
private void smoothScrollTo(int destX,int destY) {
int scrollX=getScrollX();
int delta = destX - scrollX;
mSroller.startScroll(scrollX,0,delta,0,1000);
invalidate();// 必须调用该方法通知View重绘以便computeScroll方法被调用。
}
接下来就开始模拟滑动过程了,重写onTouchEvent方法,代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_UP:
int offX = x - lastX;
int offY = y -lastY;
smoothScrollBy(-offX,-offY);
break;
}
return true;
}
六、动画
使用动画来实现View的滑动主要通过改变View的translationX和translationY参数来实现,使用动画的好处在于滑动效果是平滑的。
1.使用补间动画
先定义一个动画的xml文件(R.anim.anim),再在代码中调用,不过补这种方式只是移动view的影像,真正的view并没有移动。
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<translate
android:duration="100"
android:fromXDelta="0"
android:fromYDelta="0"
android:interpolator="@android:anim/linear_interpolator"
android:toXDelta="100"
android:toYDelta="100"/>
</set>
final Animation anim = AnimationUtils.loadAnimation(this, R.anim.anim);
targetView.startAnimation(anim);
2.属性动画
属性动画很简单,一句代码即可:
ObjectAnimator.ofFloat(targetView, "translationX", 0, 100).setDuration(100).start();