lorensiuswlt / NewQuickAction3D

Gallery3D like quickaction
http://www.londatiga.net/it/how-to-create-quickaction-dialog-in-android/
Apache License 2.0
400 stars 236 forks source link

The container moves at each show #1

Closed galex closed 12 years ago

galex commented 13 years ago

Hi, awesome lib but there's an annoying major bug :

Each time the QuickAction is showed, the container (not the arrow) moves to the left for some pixels. After few openings, the QuickAction is not even under the arrow.

I used it with a button (in an action bar) at the maximum right of the screen.

Best regards, Alex.

Screenshot : http://hpics.li/b1da65e

jeacott commented 13 years ago

A related problem is that the arrow position also gets messed up if you add different sized content to an existing quickaction object or try right aligning the control on a very small button. the reason is because of the way the arrow left margin is calculated. would be nice if it were fixed.

TheVaan commented 12 years ago

Dudes, I solved your problem and I think this could be fixed in the main release too:

Replace the show function of the class QuickAction with the following:

public void show (View anchor) {
    preShow();

    int xPos, yPos, arrowPos; // int arrowPos is needed cause position of arrow has to be diffrent for buttons that are small and aligned to the right

    int[] location      = new int[2];

    anchor.getLocationOnScreen(location);

    Rect anchorRect     = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1] 
                        + anchor.getHeight());

    //mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

    int rootHeight      = mRootView.getMeasuredHeight();
    int rootWidth       = mRootView.getMeasuredWidth();

    int screenWidth     = mWindowManager.getDefaultDisplay().getWidth();
    int screenHeight    = mWindowManager.getDefaultDisplay().getHeight();

    //automatically get X coord of popup (top left)
    if ((anchorRect.left + rootWidth) > screenWidth) {
        xPos = anchorRect.right - (rootWidth-anchor.getWidth());
        arrowPos = anchorRect.right-xPos; // normally it is anchorRect.left-xPos but then there is a gap which is getting bigger on pressing the button a few times.
    } else {
        if (anchor.getWidth() > rootWidth) {
            xPos = anchorRect.centerX() - (rootWidth/2);
        } else {
            xPos = anchorRect.left;
        }
        arrowPos = anchorRect.centerX()-xPos; // that is the developers default
    }

    int dyTop           = anchorRect.top;
    int dyBottom        = screenHeight - anchorRect.bottom;

    boolean onTop       = (dyTop > dyBottom) ? true : false;

    if (onTop) {
        if (rootHeight > dyTop) {
            yPos            = 15;
            LayoutParams l  = mScroller.getLayoutParams();
            l.height        = dyTop - anchor.getHeight();
        } else {
            yPos = anchorRect.top - rootHeight;
        }
    } else {
        yPos = anchorRect.bottom;

        if (rootHeight > dyBottom) { 
            LayoutParams l  = mScroller.getLayoutParams();
            l.height        = dyBottom;
        }
    }

    showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos); // replaced developers default value with the var so in special cases the popup AND the arrow are displayed constrained to the right

    setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);

    mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
}

You can see a screenshot here: http://twitpic.com/6w4lnj (sorry for motion blur but I'm not allowed to show the layout of the app currently :/)

Hope I could help you!

lorensiuswlt commented 12 years ago

This bug has been fixed on current update, thanx TheVaan for giving me the clue..

jeacott commented 12 years ago

2 things - the existing update to the main line doesnt work properly for me.

  1. on rotation it calculates the arrow location incorrectly. I did this to fix :

//automatically get X coord of popup (top left) //if ((anchorRect.left + rootWidth) > screenWidth) { xPos = anchorRect.left - (rootWidth-anchor.getWidth()); xPos = (xPos < 0) ? 0 : xPos; arrowPos = anchorRect.centerX()-xPos; /} else { if (anchor.getWidth() > rootWidth) { xPos = anchorRect.centerX() - (rootWidth/2); } else { xPos = anchorRect.left; } arrowPos = anchorRect.centerX()-xPos; }/

  1. on my devices I needed to restore the line: mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

without it I just get exceptions.