首页 > 其他分享 >安卓-控件拖动

安卓-控件拖动

时间:2022-12-20 09:23:24浏览次数:46  
标签:控件 拖动 安卓 offsetX offsetY content 移动 view

一、安卓的当前控件移动可以通过: layout

            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);

如上所示,在View的控件里面的onTouchEvent函数的ACTION_MOVE 对当前的view进行设置getLeft(), getTop() 等函数是当前控件相对父控件的左上角原点的X和Y的位置,具体可以见:https://www.cnblogs.com/czwlinux/p/16986438.html

 

二、安卓的当前控件移动可以通过:offsetLeftAndRight 和 offsetTopAndBottom

在第一点的时候,在设置layout时候调用了多个函数并对offsetX和offsetY做加法,调用的函数和计算相对比较多;这里提供了这两个方法可以减少计算:相对左右位置的移动和相对上下位置的移动

            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;

                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);

只是调用两个函数,即可实现一中的效果

 

三、安卓的当前控件移动可以通过:LayoutParams

我们先看如何进行设置该参数

            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;

                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
                layoutParams.leftMargin = getLeft() + offsetX;
                layoutParams.topMargin = getTop() + offsetY;
                setLayoutParams(layoutParams);

通过设置该参数的方式能够正常移动当前的view,现象跟一和二是一样。但是如果在当前view增加一个button的兄弟节点(即当前view跟button有相同的父节点),然后拖动当前的view发现button也跟着移动了

通过查看getLayoutParams这个函数发现有这么一段描述,通过该描述大概可以知道是该view的父控件对应的所有子空间都会按照该layoutparams进行布局

    /**
     * Get the LayoutParams associated with this view. All views should have
     * layout parameters. These supply parameters to the <i>parent</i> of this
     * view specifying how it should be arranged. There are many subclasses of
     * ViewGroup.LayoutParams, and these correspond to the different subclasses
     * of ViewGroup that are responsible for arranging their children.
     */

所以如果只是想移动当前的view,而不移动它的兄弟view则不宜通过该函数

 

 

四、安卓的控件拖动可以通过 scrollBy 或者 scrollTo

两者的区别是:

scrollBy是相对当前的位置移动dx和dy的偏移量: scrollBy(dx, dy)

scrollTo是移动到指定的x和y: scrollTo(x, y)

我们用如下的来调用查看具体的表现

            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                scrollBy(offsetX, offsetY);

使用如上的函数进行拖动发现view没有进行移动;其实这两个函数移动的是当前View的content所以当前view没有移动是正常

这么说的话应该是要掉用父view的scrollBy,我们来试一下;

((View)getParent()).scrollBy(offsetX, offsetY);

使用如上的调用,当前的view确实移动了,但是却乱动。

我们刚才说这两个函数移动的是当前View的content,那么获取父节点移动的是父节点的content。那么content和当前的view是什么关系呢?

假设content在左上角(0, 0)的位置,view也是在左上角(0, 0)的位置,content移动(10, 10) 像素后,view相对content是像左上角移动了(因为view不动而content向右下角移动了)。content看到什么那么父节点显示的就是什么,所以我们看到view向左上角移动了。既然是往相反的位置移动,那么我们要让view跟随我们需要的方向移动那么就需要进行取反,如下所示

            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                ((View)getParent()).scrollBy(-offsetX, -offsetY);

因为是针对整个父节点的content,所以如果view有兄弟view,该兄弟view也会跟随一起移动

 

五、当我们move完松开手之后希望它回到原来的位置或者其他位置,并且有回弹效果则可以用scroller

我们这里让scroller回弹回原点,如下所示在ACTION_UP的时候执行startScroll

            case MotionEvent.ACTION_UP:
                View viewGroup = (View) getParent();
                mScroller.startScroll(viewGroup.getScrollX(), viewGroup.getScrollY(), -viewGroup.getScrollX(), -viewGroup.getScrollY());
                invalidate();

注意,这里的这个mScroller只是一个数值类似model,不会做具体的移动操作,需要在computeScroll做具体的操作

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

如上所示,通过parent的scallTo的方式进行移动,当然也可以用前面介绍的几种移动方式

 

标签:控件,拖动,安卓,offsetX,offsetY,content,移动,view
From: https://www.cnblogs.com/czwlinux/p/16993497.html

相关文章