Android自定义View

实现View滑动的6种方式

2018-05-04  本文已影响32人  Doikki
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()方法来重新放置控件的位置
            layout(getLeft() + offsetX, getTop() + offsetY,
                    getRight() + offsetX, getBottom() + offsetY);
            break;
    }
    return true;
}
case MotionEvent.ACTION_MOVE:
    //计算移动的距离
    int offsetX = x - lastX;
    int offsetY = y - lastY;
    offsetLeftAndRight(offsetX);
    offsetTopAndBottom(offsetY);
    break;
case MotionEvent.ACTION_MOVE:
    //计算移动的距离
    int offsetX = x - lastX;
    int offsetY = y - lastY;
    LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
    layoutParams.leftMargin = getLeft() + offsetX;
    layoutParams.topMargin = getTop() + offsetY;
    setLayoutParams(layoutParams);
    break;

因为父控件是LinearLayout,所以我们使用了LinearLayout.LayoutParams。如果父控件是RelativeLayout,则要使用RelativeLayout.LayoutParams。除了使用布局的LayoutParams外,我们还可以使用ViewGroup.MarginLayoutParams来实现:

case MotionEvent.ACTION_MOVE:
    //计算移动的距离
    int offsetX = x - lastX;
    int offsetY = y - lastY;
    ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
    layoutParams.leftMargin = getLeft() + offsetX;
    layoutParams.topMargin = getTop() + offsetY;
    setLayoutParams(layoutParams);
    break;
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fillAfter="true">
    <translate
        android:fromXDelta="0"
        android:toXDelta="300" />
</set>

接下来在Java代码中调用:

mCustomView.setAnimation(AnimationUtils.loadAnimation(this, R.anim.anim_translate));

运行程序,控件会向右平移300个像素,并停留在当前位置。
需要注意的是View动画并不能改变View的位置参数。如果对控件设置一个点击事件,此时对控件执行如上操作,点击控件停留的位置并不会触发点击事件,但我们点击控件初始位置却触发了点击事件。对于系统来说这个控件并没有改变原有的位置,所以就出现上述问题。在Android3.0的时候推出的属性动画可以解决上述问题,它不仅执行了动画,还改变了控件的位置参数。代码如下:

ObjectAnimator.ofFloat(mCustomView, "translationX", 0, 300).setDuration(1000).start();
case MotionEvent.ACTION_MOVE:
    //计算移动的距离
    int offsetX = x - lastX;
    int offsetY = y - lastY;
    ((View)getParent()).scrollBy(-offsetX, -offsetY);
    break;
public class CustomView extends View {
    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mScroller = new Scroller(context);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private Scroller mScroller;

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            ((View)getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }

    public void smoothScrollTo(int destX, int destY) {
        int scrollX = getScrollX();
        int delta = destX - scrollX;
        mScroller.startScroll(scrollX, 0, delta, 0, 2000);
        invalidate();
    }
}

最后我们在activity中调用smoothScrollTo()方法:

mCustomView.smoothScrollTo(-400, 0);
上一篇 下一篇

猜你喜欢

热点阅读