Get Absolute View Position in ListView
Asked Answered
M

3

6

I am trying to make a popup window appear above/below an item that is clicked inside of a ListView. However, the problem is that the View that is coming in from the OnItemClick method is only giving me its X & Y values relative to the ListView itself. I also checked the ListView and that is also giving me x=0 y=0 despite the fact that there are other views above it.

I ran through all the values in hierarchyviewer, but didn't see the values I was looking for. (And not I'm having major problems getting it to work again).

Any advice?

@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
    LayoutInflater inflater = getLayoutInflater(null);
    PopupWindow quickRail = new PopupWindow(
            inflater.inflate(R.layout.quanitity_controls, null), view.getMeasuredWidth(),
            view.getMeasuredHeight());

    int[] location = {
            0, 0
    };

    // This doesn't place this window right on top of the view
    quickRail.showAtLocation(view, Gravity.CENTER, 0, location[1]);
}

Both items in the list are making the Popup appear in the same place. Popup Not Appearing In desired positions

Movement answered 24/7, 2012 at 14:17 Comment(0)
D
9

This should work

//Activity windows height
int totalHeight = getWindowManager().getDefaultDisplay().getHeight();
int[] location = new int[2];
v.getLocationOnScreen(location);

The location array should have the x and y values of the view. 'v' is the view object passed on the onItemClickListener.

Im adding some parts I used for my project. It might be helpful. I had an actionbar on the top of the listview and this code seemed to work fine.

The requirement was to bring a small menu either on top or below a list item. So when an item is selected, I check if the selected list item is in the upper half of the screen, if so put the menu below the list item otherwise put it on top of the list item. Here's the code

ListItem click code

listView.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position
           , long id) {
        showQuickActionMenu(position,view);
    }   
});

private void showQuickActionMenu(int pos, View v){
    LayoutInflater inflater = 
            (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    //This is just a view with buttons that act as a menu.  
    View popupView = inflater.inflate(R.layout.ticket_list_menu, null);
    popupView.findViewById(R.id.menu_view).setTag(pos);
    popupView.findViewById(R.id.menu_change_status).setTag(pos);
    popupView.findViewById(R.id.menu_add_note).setTag(pos);
    popupView.findViewById(R.id.menu_add_attachment).setTag(pos);

    window = PopupHelper.newBasicPopupWindow(TicketList.this);
    window.setContentView(popupView);
    int totalHeight = getWindowManager().getDefaultDisplay().getHeight();
    int[] location = new int[2];
    v.getLocationOnScreen(location);

    if (location[1] < (totalHeight / 2.0)) {
        PopupHelper.showLikeQuickAction(window, popupView, v
                , getWindowManager(),0,0,PopupHelper.UPPER_HALF);
    } else {
        PopupHelper.showLikeQuickAction(window, popupView, v
                , getWindowManager(),0, 0,PopupHelper.LOWER_HALF);
    }   
}

This the PopupHelper class I use

public class PopupHelper {
    public static final int UPPER_HALF = 0;
    public static final int LOWER_HALF = 1;

    public static PopupWindow newBasicPopupWindow(Context context) {
        final PopupWindow window = new PopupWindow(context);

        // when a touch even happens outside of the window
        // make the window go away
        window.setTouchInterceptor(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                    window.dismiss();
                    return true;
                }
                return false;
            }
        });

        window.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
        window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
        window.setTouchable(true);
        window.setFocusable(true);
        window.setOutsideTouchable(true);

        window.setBackgroundDrawable(
                new ColorDrawable(android.R.color.darker_gray));        
        return window;
    }

    /**
     * Displays like a QuickAction from the anchor view.
     * 
     * @param xOffset
     *            offset in the X direction
     * @param yOffset
     *            offset in the Y direction
     */
     public static void showLikeQuickAction(PopupWindow window, View root, 
             View anchor, WindowManager windowManager, int xOffset
             ,int yOffset,int section) {

         //window.setAnimationStyle(R.style.Animations_GrowFromBottomRight);

         int[] location = new int[2];
         anchor.getLocationOnScreen(location);

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

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

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

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

         int xPos = ((screenWidth - rootWidth) / 2) + xOffset;
         int yPos = anchorRect.top - rootHeight + yOffset;

         xPos = (screenWidth - rootWidth);
         if(section == UPPER_HALF){
             yPos = anchorRect.top + anchor.getMeasuredHeight();    
         } else {
             yPos = anchorRect.top - rootHeight;
         }
         window.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
    }

}
Dashed answered 24/7, 2012 at 14:53 Comment(4)
Thanks for this, but I tried this and it only gives me the relative position. So the first item is the list is 0,0. It's close, because I thought that was the solution as well. I believe I'm having some translation problems somewhere.Movement
can u put ur layout xml. i kinda had the same requirement but my layout only had a listview.Dashed
Blah. Sadly enough that looks like the code I need. I was hoping for something prettier, but expected this, lol. Thanks.Movement
Yes. This worked and was exactly what I was looking for. If I could do more than upvote and accept I would. Thanks.Movement
M
1

for those who stick on this issue try use this code snippet

popWindow.showAsDropDown(v);//v is your listview or recyclerview item Element that clicked.

hope this help.

Madgemadhouse answered 14/10, 2015 at 11:41 Comment(0)
C
0

Try this and see if it works..

private  void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        // pre-condition
        return;
    }
    int totalHeight = 0;
    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
        totalHeight += listItem.getMeasuredHeight();
    }

}

//here listItem.getMeasuredHeight() will get u the height of each list item...U can get ur y position by height*clickedPosition

Counterpart answered 24/7, 2012 at 14:31 Comment(1)
Thanks for the response. I don't have a problem getting the height of the listview. I'm trying to get the screen coordinates of a view so I can show a PopupWindow right by it.Movement

© 2022 - 2024 — McMap. All rights reserved.