在 onTouch ACTION_MOVE 中更改视图高度

Nik*_*Nik 4 android touch touch-event layoutparams

当用户在屏幕上向下移动手指时,我想更改视图高度。

    new OnTouchListener() {
        float lastY = Float.MIN_VALUE;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE) {
                if (lastY != Float.MIN_VALUE) {
                    final float dist = event.getRawY() - lastY;

                    myView.post(new Runnable() {
                        @Override
                        public void run() {
                            ViewGroup.LayoutParams lp = myView.getLayoutParams();
                            lp.height += dist;
                            myView.setLayoutParams(lp);
                        }
                    });

                    view.invalidate();
                }
                lastY = event.getRawY();
            }

            if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
                lastY = Float.MIN_VALUE;
            }

            return true;
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是只有当用户停止移动手指时,视图高度才会改变!

发生 ACTION_MOVE 时如何立即更改视图高度?

Iva*_*sov 5

首先,您不需要调用invalidate()或者requestLayout()因为setLayoutParams() 已经这样做了所以再次手动调用它只会导致不必要的开销。

其次,失去mView.post()调用:onTouch()无论如何都在主(又名 UI)线程上执行。只需在正文中执行 layoutparamsonTouch()和其他所有内容即可。

第三,您的mView.post()调用可能是导致所有麻烦的原因,因为View.post()有效地将作业发布到 UI 线程的Handler,该线程将作业排入队列,直到 UI 线程可以自由执行它们,一个接一个。在您的情况下,它太忙onTouch()于在每个事件上运行您的方法,因此当您停止提供触摸事件时,您发布的所有内容都会被执行 - 即停止拖动。

最后,这是我在必须实现可调整大小的视图时使用的主题的一个很好的参考,它也很可能涵盖您尝试手动实现的所有功能:GitHub 上的k9mail 自己的SplitView。请注意他们如何将坐标保存在ACTION_DOWN块中,然后从那里测量高度,而不是调用getHeight()并使用最后一个坐标增量来增加它。这允许减少一个操作 + 处理,ACTION_DOWN并且具有 mDragging 布尔标志将允许您删除晦涩的lastY = Float.MIN_VALUE;东西。