Search code examples
androidtouchtouch-eventlayoutparams

Change view height in onTouch ACTION_MOVE


I would like to change view height when user move finger down on screen.

    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;
        }
    }

But view height changes only when user stops moving finger!

How to change view height immediately when ACTION_MOVE occurred?


Solution

  • First, you don't need to call invalidate() or requestLayout() because setLayoutParams() already does that so calling it manually again will only cause unnecessary overhead.

    Second, lose the mView.post() call: onTouch() is executed on the main (aka UI) thread anyway. Just do the layoutparams stuff in the onTouch() body along with everything else.

    Third, your mView.post() call is what's probably causing all the trouble because View.post() effectively posts the job to UI thread's Handler, which queues jobs until the time the UI thread is free to execute them, one by one. And in your case it's too busy running your onTouch() method on every event, so everything you post gets executed when you stop delivering touch events - i.e. stop dragging.

    Finally, here's a good reference on the subject that I used when I had to implement a resizeable view, it's also very likely to cover all the functionality you're trying to implement by hand: k9mail's own SplitView class on GitHub. Note how they just save the coordinates in ACTION_DOWN block and then just measure the height from there instead of calling getHeight() and incrementing it with last coordinate delta. This allows for one less operation + handling ACTION_DOWN and having the mDragging boolean flag will allow you to drop the obscure lastY = Float.MIN_VALUE; thing.