在ListView中获取绝对视图位置

6
我正在尝试使一个弹出窗口出现在ListView中点击的项目的上方/下方。但问题是从OnItemClick方法传入的View仅给出相对于ListView本身的X和Y值。我还检查了ListView,即使它上面有其他视图,也仍然给我x=0 y=0。我通过层次结构查看器运行了所有值,但没有看到我需要的值。(现在我遇到了重大问题,无法再让它正常工作)。有什么建议吗?
@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]);
}

列表中的两个项目使得弹出窗口出现在同一位置。 弹出窗口未出现在所需位置

3个回答

9

这应该可以运行

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

定位数组应该包含视图的x和y值。'v'是传递给onItemClickListener的视图对象。
我添加了一些我在项目中使用的部分,这可能有所帮助。我在listview的顶部添加了一个操作栏,并且这段代码似乎运行良好。
要求是在列表项上方或下方带一个小菜单。因此,当选择了一个项目时,我会检查所选的列表项是否在屏幕的上半部分,如果是,则将菜单放在列表项下方,否则将其放在列表项上方。这是代码:
列表项点击代码
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);
    }   
}

这是我使用的PopupHelper类。
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);
    }

}

谢谢您的回复,但我已经尝试过这个方法,它只给出了相对位置。所以列表中的第一项是0,0。虽然很接近,因为我也认为这是解决方案。但我相信我在某个地方遇到了一些翻译问题。 - Frank Sposaro
你能放一下你的布局XML吗?我有类似的需求,但我的布局只有一个ListView。 - blessanm86
啊。可悲的是,那看起来像我需要的代码。我本来希望有更漂亮的东西,但却料到会是这样,哈哈。谢谢。 - Frank Sposaro
是的。这个方法可行,正是我所需要的。如果我能做更多的赞和接受,我一定会的。谢谢。 - Frank Sposaro

1

对于那些遇到这个问题的人,请尝试使用以下代码片段

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

希望这有所帮助。

0

试一下,看看是否有效。

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

}

//这里的listItem.getMeasuredHeight()将会获取每个列表项的高度...您可以通过高度*点击位置来获取您的y位置


谢谢回复。我没有问题获取ListView的高度。我正在尝试获取视图的屏幕坐标,以便可以在其旁边显示PopupWindow。 - Frank Sposaro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接