0

I had to create a popup window which is a square (400dp height and 400dp width). Now I want to drag it when I tap a button which is positioned on the top left of the popup. I set onTouch() on the layout which is placed on the popup and this is the code I use in order to drag it:

@Override
public boolean onTouch(View v, MotionEvent event) {
    int eventAction = event.getAction();

    switch (eventAction) {
        case MotionEvent.ACTION_MOVE: // Drag event

            xRow = (int) event.getRawX() - rootView.getWidth();
            yRow = (int) event.getRawY() - rootView.getHeight();             

            /* Updates the position of the popup on the screen */
            update(xRow, yRow, -1, -1);
            break;
    }

    return true;
}

The problem is that this seems to work only for Nexus 7. On a tablet of 10 inch, it is not working properly. When I drag it on the larger tablet, there is a space between my finger and popup. So I assume that the units of measurement I use are not the right ones. I have tried to use the Metrics but no success.

halfer
  • 19,824
  • 17
  • 99
  • 186
Laura
  • 2,653
  • 7
  • 37
  • 59
  • I can't see how the width of the rootView has anything to do with the getRawX() value. There shouldn't be any unit issues here because everything is in raw pixels, but I'm not sure the logic of your calculations makes sense. – SDJMcHattie Mar 02 '14 at 09:50
  • Usually, when I handle dragging an object I note the original X and original Y positions of the touch in `MotionEvent.ACTION_DOWN`. At the same time, I note the original location of the view that will be moving. Then in `MotionEvent.ACTION_MOVE` I subtract the original X position from the new X position to get the deltaX value. I do the same for Y to get deltaY. I then add those to the original position of the view being moved and you get a smooth movement that tracks your finger perfectly. – SDJMcHattie Mar 02 '14 at 09:52
  • in down action compute two deltas dx and dy: dx = currentx - event_raw_x, the same for dy and use them in move actions new_x = event_raw_x + dx and the same for new_y – pskink Mar 02 '14 at 09:58
  • I subtract the rootView which is the whole popup's width because I noticed that the origins of the popup are on the bottom left, which means that when the update method is called, the x and y coordinates will apply to that, and because the dragButton is on top left and it must follow my finger I have to subtract the width of the popup. – Laura Mar 02 '14 at 10:04
  • belive me it has nothing to do with the width – pskink Mar 02 '14 at 10:10
  • I believe you, I know there is something wrong with my logic. I will try your suggestions :) – Laura Mar 02 '14 at 10:20
  • @SDJMcHattie Thank you too for your answer. It helped me to understand how I should have thought :) – Laura Mar 02 '14 at 11:58

1 Answers1

14

Laura, try this (place it in onCreate):

    final View cv = new View(this);
    setContentView(cv);

    TextView tv = new TextView(this);
    tv.setBackgroundColor(0xffeeeeee);
    tv.setTextColor(0xff000000);
    tv.setTextSize(24);
    tv.setText("click me\nthen drag me");
    tv.setPadding(8, 8, 8, 8);
    mPopup = new PopupWindow(tv, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    OnTouchListener otl = new OnTouchListener() {
        private float mDx;
        private float mDy;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int action = event.getAction();
            if (action == MotionEvent.ACTION_DOWN) {
                mDx = mCurrentX - event.getRawX();
                mDy = mCurrentY - event.getRawY();
            } else
            if (action == MotionEvent.ACTION_MOVE) {
                mCurrentX = (int) (event.getRawX() + mDx);
                mCurrentY = (int) (event.getRawY() + mDy);
                mPopup.update(mCurrentX, mCurrentY, -1, -1);
            }
            return true;
        }
    };
    tv.setOnTouchListener(otl);

    mCurrentX = 20;
    mCurrentY = 50;
    cv.post(new Runnable() {
        @Override
        public void run() {
            mPopup.showAtLocation(cv, Gravity.NO_GRAVITY, mCurrentX, mCurrentY);
        }
    });
pskink
  • 23,874
  • 6
  • 66
  • 77
  • Thank you very, very, very much :) It works!! I knew that was something wrong with my logic, but I got stuck onto that idea and no matter how much I tried other things my mind was thinking only on that. Thanks again for enlightening me :) – Laura Mar 02 '14 at 11:56