PopupWindowCompat.java revision 44918a92e1d66a01a03063e2c5e68b2570f64b03
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.widget;
18
19import android.view.View;
20import android.widget.PopupWindow;
21
22/**
23 * Helper for accessing features in PopupWindow introduced after API level 4
24 * in a backwards compatible fashion.
25 */
26public class PopupWindowCompat {
27    /**
28     * Interface for the full API.
29     */
30    interface PopupWindowImpl {
31        public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
32                int gravity);
33        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor);
34        public boolean getOverlapAnchor(PopupWindow popupWindow);
35    }
36
37    /**
38     * Interface implementation that doesn't use anything above v4 APIs.
39     */
40    static class BasePopupWindowImpl implements PopupWindowImpl {
41        @Override
42        public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
43                int gravity) {
44            popup.showAsDropDown(anchor, xoff, yoff);
45        }
46
47        @Override
48        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
49            // noop
50        }
51
52        @Override
53        public boolean getOverlapAnchor(PopupWindow popupWindow) {
54            return false;
55        }
56    }
57
58    /**
59     * Interface implementation for devices with at least KitKat APIs.
60     */
61    static class KitKatPopupWindowImpl extends BasePopupWindowImpl {
62        @Override
63        public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
64                int gravity) {
65            PopupWindowCompatKitKat.showAsDropDown(popup, anchor, xoff, yoff, gravity);
66        }
67    }
68
69    static class Api21PopupWindowImpl extends KitKatPopupWindowImpl {
70        @Override
71        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
72            PopupWindowCompatApi21.setOverlapAnchor(popupWindow, overlapAnchor);
73        }
74
75        @Override
76        public boolean getOverlapAnchor(PopupWindow popupWindow) {
77            return PopupWindowCompatApi21.getOverlapAnchor(popupWindow);
78        }
79    }
80
81    static class Api23PopupWindowImpl extends Api21PopupWindowImpl {
82        @Override
83        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
84            PopupWindowCompatApi23.setOverlapAnchor(popupWindow, overlapAnchor);
85        }
86
87        @Override
88        public boolean getOverlapAnchor(PopupWindow popupWindow) {
89            return PopupWindowCompatApi23.getOverlapAnchor(popupWindow);
90        }
91    }
92
93    /**
94     * Select the correct implementation to use for the current platform.
95     */
96    static final PopupWindowImpl IMPL;
97    static {
98        final int version = android.os.Build.VERSION.SDK_INT;
99        if (version >= 23) {
100            IMPL = new Api23PopupWindowImpl();
101        } else if (version >= 21) {
102            IMPL = new Api21PopupWindowImpl();
103        } else if (version >= 19) {
104            IMPL = new KitKatPopupWindowImpl();
105        } else {
106            IMPL = new BasePopupWindowImpl();
107        }
108    }
109
110    private PopupWindowCompat() {
111        // This class is not publicly instantiable.
112    }
113
114    /**
115     * <p>Display the content view in a popup window anchored to the bottom-left
116     * corner of the anchor view offset by the specified x and y coordinates.
117     * If there is not enough room on screen to show
118     * the popup in its entirety, this method tries to find a parent scroll
119     * view to scroll. If no parent scroll view can be scrolled, the bottom-left
120     * corner of the popup is pinned at the top left corner of the anchor view.</p>
121     * <p>If the view later scrolls to move <code>anchor</code> to a different
122     * location, the popup will be moved correspondingly.</p>
123     *
124     * @param popup the PopupWindow to show
125     * @param anchor the view on which to pin the popup window
126     * @param xoff A horizontal offset from the anchor in pixels
127     * @param yoff A vertical offset from the anchor in pixels
128     * @param gravity Alignment of the popup relative to the anchor
129     */
130    public static void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
131            int gravity) {
132        IMPL.showAsDropDown(popup, anchor, xoff, yoff, gravity);
133    }
134
135    /**
136     * Sets whether the popup window should overlap its anchor view when
137     * displayed as a drop-down.
138     *
139     * @param overlapAnchor Whether the popup should overlap its anchor.
140     */
141    public static void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
142        IMPL.setOverlapAnchor(popupWindow, overlapAnchor);
143    }
144
145    /**
146     * Returns whether the popup window should overlap its anchor view when
147     * displayed as a drop-down.
148     *
149     * @return Whether the popup should overlap its anchor.
150     */
151    public static boolean getOverlapAnchor(PopupWindow popupWindow) {
152        return IMPL.getOverlapAnchor(popupWindow);
153    }
154}
155