2

私の 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 と重なった場合にその位置を更新する必要があります。

どんな助けでも大歓迎です。

4

0 に答える 0