4

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?

Machavity
  • 30,841
  • 27
  • 92
  • 100
Nik
  • 7,114
  • 8
  • 51
  • 75

2 Answers2

5

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.

Ivan Bartsov
  • 19,664
  • 7
  • 61
  • 59
  • I look at SplitView and make my touch listener like there. Height not increase immediately whatever! May be due that view which I need change height, is anchor for other view in my layout and android must re-layout all view hierarchy? – Nik Mar 07 '13 at 09:11
  • @Nik well, that shouldn't be a problem, since `setLayoutParams()` does call `requestLayout()` internally. Hmm. Why don't you update your question and add the new code, the one inspired by SplitView, then we can have a look at what may be the problem there – Ivan Bartsov Mar 07 '13 at 09:19
0

Instead of view.invalidate() you could use view.requestLayout().

This wont be super fast though, as it will cause a lot of layout events. It's hard to give more advice without seeing your layout and knowing what kind of effect you are aiming for.

alex
  • 6,359
  • 1
  • 23
  • 21