私の Android アプリには、マーカー付きのゲーム マップがあります。ユーザーがマーカーをタップすると、マップ マーカーに合わせて PopupWindow が表示されます (Google マップと同様)。私が抱えている問題は、マーカーが画面の上部に近い場合、PopupWindow が ActionBar (およびマーカーが十分に高い場合はステータス バーの下) と重なることです。
showAtLocation() を呼び出して PopupWindow を表示しています。これにより、ビューが "Map" フラグメント内に制限されることを期待していました (左側と右側で行われます) が、うまくいきません。
ポップアップ内のテキストが複数行を占めていることを考慮して、ビューがレイアウトされた後にポップアップの Y 位置を更新する調整を既に実装していました。それは問題なく機能しましたが、この状況で別の垂直方向の調整を追加しようとすると、PopupWindow の位置が変わりません。
PopupWindow 実装のコードは次のとおりです。
/**
* Displays a PopupWindow.
*/
public class MyPopupWindow extends PopupWindow
{
private Fragment m_fragment;
private int m_x;
private int m_y;
/**
* Displays a PopupWindow at a certain offset (x, y) from the center of fragment's view.
*/
public static MyPopupWindow createPopup (Context context, Fragment fragment, int x, int y)
{
// Create the PopupWindow's content view
LayoutInflater inflater = LayoutInflater.from (context);
View popupView = inflater.inflate (R.layout.view_map_popup, null);
MyPopupWindow popupWindow = new MyPopupWindow (popupView, x, y);
popupWindow.m_fragment = fragment;
popupWindow.showAtLocation (fragment.getView (), Gravity.CENTER, x, y);
return popupWindow;
}
private MyPopupWindow (View view, int x, int y)
{
super (view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
m_x = x;
m_y = y;
TextView title = (TextView) view.findViewById (R.id.lblMapPopupTitle);
title.setText ("Exercise Title");
TextView description = (TextView) view.findViewById (R.id.lblMapPopupDescription);
description.setText ("Exercise Description\nSecond Line\nThird Line\nFourth Line\nAnd one more...");
view.setVisibility (View.INVISIBLE);
view.addOnLayoutChangeListener (layoutChangeListener);
}
// If the tapped map location is too close to the edge, determine the
// delta-x and delta-y needed to align it with the PopupWindow
private int getHorizontalAdjustment (int popupWidth)
{
int horizontalAdjustment = 0;
int parentWidth = m_fragment.getView ().getWidth ();
if ((parentWidth / 2) + m_x + (popupWidth / 2) > parentWidth)
{
horizontalAdjustment = parentWidth - ((parentWidth / 2) + m_x + (popupWidth / 2));
}
else if ((parentWidth / 2) + m_x - (popupWidth / 2) < 0)
{
horizontalAdjustment = 0 - ((parentWidth / 2) + m_x - (popupWidth / 2));
}
return horizontalAdjustment;
}
private int getVerticalAdjustment (int popupHeight)
{
int verticalAdjustment = 0;
int parentHeight = m_fragment.getView ().getHeight ();
int y = m_y - (popupHeight / 2);
if ((parentHeight / 2) + y + (popupHeight / 2) > parentHeight)
{
verticalAdjustment = parentHeight - ((parentHeight / 2) + y + (popupHeight / 2));
}
else if ((parentHeight / 2) + y - (popupHeight / 2) < 20)
{
verticalAdjustment = 20 - ((parentHeight / 2) + y - (popupHeight / 2));
}
return verticalAdjustment;
}
private View.OnLayoutChangeListener layoutChangeListener = new View.OnLayoutChangeListener ()
{
@Override
public void onLayoutChange (View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)
{
int height = bottom - top;
int width = right - left;
// Adjust the y-position for the inflated height of the view
// (so the popup's bottom edge lines up with the tapped marker's top edge)
int y = m_y - (height / 2);
int x = m_x;
// Determine any adjustments that need to be made to line up the tapped marker with the popup
int horizontalAdjustment = getHorizontalAdjustment (width);
int verticalAdjustment = getVerticalAdjustment (height);
y -= verticalAdjustment;
// Update our position with the re-calculated position
update (x, y, -1, -1);
view.setVisibility (View.VISIBLE);
}
};
}
この問題は、次のスクリーンショットで確認できます。PopupWindow が ActionBar と重なっています。
基本的に、(1) PopupWindow を Fragment のビューにクリップして ActionBar と重ならないようにするか、(2) PopupWindow を取得して ActionBar と重なった場合にその位置を更新する必要があります。
どんな助けでも大歓迎です。