美文网首页
[Android]通过setOnTouchListener实现移

[Android]通过setOnTouchListener实现移

作者: storyteller_F | 来源:发表于2020-02-23 21:16 被阅读0次

    [Android]通过setOnTouchListener实现移动View功能

    需求

    有时需要移动View,以前写的代码不太好,就上网上找,也不好用,和我自己写的都有的问题是View 会比光标的位置靠右下方。以前都忍了,偏就偏吧,现在决心要改,也可能是因为在这个特殊时期比较闲吧。

    实现

    正如上面所说,靠右下方,而且相比于靠右,靠下的程度更大。这很难不让人想到是状态栏造成的影响,而且单单是状态栏都还不够,还有一个ToolBar,所以要点在于如何去除这个高度。

    
        /**
         * Returns the original raw Y coordinate of this event.  For touch
         * events on the screen, this is the original location of the event
         * on the screen, before it had been adjusted for the containing   window
         * and views.
         *
         * @see #getY(int)
         * @see #AXIS_Y
         */
        public final float getRawY() {
            return nativeGetRawAxisValue(mNativePtr, AXIS_Y, 0, HISTORY_CURRENT);
        }
    

    getRawX 或者getRawY 返回的都是相对于整个屏幕的,在测试时,如果不加限制,甚至可以滑动到状态栏,事件一直有效。

        /**
         * {@link #getY(int)} for the first pointer index (may be an
         * arbitrary pointer identifier).
         *
         * @see #AXIS_Y
         */
        public final float getY() {
            return nativeGetAxisValue(mNativePtr, AXIS_Y, 0, HISTORY_CURRENT);
        }
    

    可是看这个getX 函数根本不明白说的什么意思,甚至它们的实现完全一样,可能是mNativePtr 或者HISTORY_CURRENT 有什么不同吧,不管了。到网上查,是相对这个我们设置触摸事件的View 的位置。

    在每次设定位置时,需要的是设置当前的View 相对于父View 的坐标,在每次移动时getRawY 的值需要减去getY 的值,得到的值就是当前view相对整个屏幕的位置,在减去当前view 相对于父窗体的位置,这样得到的值就是父窗体相对于整个屏幕的位置,最后得到的值是跟我们没有关系的,在获得当前view 需要的位置时在减去这个值。父窗体是不会动的,所以后者的这个位置可以在MotionEvent.ACTION_DOWN 时获取,同样的,getY 的值也需要在这个时候获取,因为光标相对于当前的View 的位置也是不能改变的。
    像这样:

    case MotionEvent.ACTION_DOWN:
        x = event.getX();
        y = event.getY();
        left = event.getRawX() - view.getLeft() - x;
        top = event.getRawY() - view.getTop() - y;
        return true;
    

    当用户只是点击时,是不会有MotionEvent.ACTION_MOVE 事件的,所以在这个事件下记录当前用户是否进行的是移动操作,而不是在上面的。

    case MotionEvent.ACTION_MOVE:
        if (!moved) {
            moved = true;
        }
        setXPosition(event.getRawX() - x - left);
        setYPosition(event.getRawY() - y - top);
        return true;
    

    我们用光标相对于整个屏幕的位置减去父窗体的位置,减去光标相对于父窗体的位置,就是当前view 的左上角相对于父窗体的位置。

    当用户抬手时,判断是否是移动了,如果移动了,那就不是点击事件,而且这个移动操作也结束了,恢复原样,如果不是,那就是点击事件,就调用performClick 函数。

    case MotionEvent.ACTION_UP:
        if (moved) {
            moved = false;
        } else {
            v.performClick();
        }
        return true;
    

    至于那个performClick

        /**
         * Call this view's OnClickListener, if it is defined.  Performs all normal
         * actions associated with clicking: reporting accessibility event, playing
         * a sound, etc.
         *
         * @return True there was an assigned OnClickListener that was called, false
         *         otherwise is returned.
         */
    
    

    这样onClickListener 就能够正常运行了,而不是被我们阻止了。

    这还没有完:

        /**
         * Entry point for {@link #performClick()} - other methods on View should call it instead of
         * {@code performClick()} directly to make sure the autofill manager is notified when
         * necessary (as subclasses could extend {@code performClick()} without calling the parent's
         * method).
         */
        private boolean performClickInternal() {
            // Must notify autofill manager before performing the click actions to avoid scenarios where
            // the app has a click listener that changes the state of views the autofill service might
            // be interested on.
            notifyAutofillManagerOnClick();
    
            return performClick();
        }
    

    他提醒我不让我直接调用performClick ,而是使用performClickInternal ,说是为了保证autofill manager 工作。可是这个函数是个私有函数,可能说的不是我的这种情况吧。

    至于perfomClick 的返回值,感觉不重要就不管了。

    最后

    如果是悬浮窗,view.getTop() 返回的总是0,所以需要通过LayoutParams来获取这个top 的值,并且left不再需要。

    
        WindowManager.LayoutParams layoutParams= (WindowManager.LayoutParams) v.getLayoutParams();
        top = event.getRawY() -layoutParams.y- y;
    
    

    相关文章

      网友评论

          本文标题:[Android]通过setOnTouchListener实现移

          本文链接:https://www.haomeiwen.com/subject/neteqhtx.html