|
Android example source code file (PopupWindow.java)
The PopupWindow.java Android example source code/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.widget; import com.android.internal.R; import android.content.Context; import android.content.res.TypedArray; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.Gravity; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnScrollChangedListener; import android.view.View.OnTouchListener; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; import android.os.IBinder; import android.util.AttributeSet; import java.lang.ref.WeakReference; /** * <p>A popup window that can be used to display an arbitrary view. The popup * windows is a floating container that appears on top of the current * activity.</p> * * @see android.widget.AutoCompleteTextView * @see android.widget.Spinner */ public class PopupWindow { /** * Mode for {@link #setInputMethodMode(int)}: the requirements for the * input method should be based on the focusability of the popup. That is * if it is focusable than it needs to work with the input method, else * it doesn't. */ public static final int INPUT_METHOD_FROM_FOCUSABLE = 0; /** * Mode for {@link #setInputMethodMode(int)}: this popup always needs to * work with an input method, regardless of whether it is focusable. This * means that it will always be displayed so that the user can also operate * the input method while it is shown. */ public static final int INPUT_METHOD_NEEDED = 1; /** * Mode for {@link #setInputMethodMode(int)}: this popup never needs to * work with an input method, regardless of whether it is focusable. This * means that it will always be displayed to use as much space on the * screen as needed, regardless of whether this covers the input method. */ public static final int INPUT_METHOD_NOT_NEEDED = 2; private Context mContext; private WindowManager mWindowManager; private boolean mIsShowing; private boolean mIsDropdown; private View mContentView; private View mPopupView; private boolean mFocusable; private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE; private int mSoftInputMode; private boolean mTouchable = true; private boolean mOutsideTouchable = false; private boolean mClippingEnabled = true; private OnTouchListener mTouchInterceptor; private int mWidthMode; private int mWidth; private int mLastWidth; private int mHeightMode; private int mHeight; private int mLastHeight; private int mPopupWidth; private int mPopupHeight; private int[] mDrawingLocation = new int[2]; private int[] mScreenLocation = new int[2]; private Rect mTempRect = new Rect(); private Drawable mBackground; private Drawable mAboveAnchorBackgroundDrawable; private Drawable mBelowAnchorBackgroundDrawable; private boolean mAboveAnchor; private OnDismissListener mOnDismissListener; private boolean mIgnoreCheekPress = false; private int mAnimationStyle = -1; private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] { com.android.internal.R.attr.state_above_anchor }; private WeakReference<View> mAnchor; private OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() { public void onScrollChanged() { View anchor = mAnchor.get(); if (anchor != null && mPopupView != null) { WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams(); updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff)); update(p.x, p.y, -1, -1, true); } } }; private int mAnchorXoff, mAnchorYoff; /** * <p>Create a new empty, non focusable popup window of dimension (0,0). * * <p>The popup does provide a background. */ public PopupWindow(Context context) { this(context, null); } /** * <p>Create a new empty, non focusable popup window of dimension (0,0). * * <p>The popup does provide a background. */ public PopupWindow(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.popupWindowStyle); } /** * <p>Create a new empty, non focusable popup window of dimension (0,0). * * <p>The popup does provide a background. */ public PopupWindow(Context context, AttributeSet attrs, int defStyle) { mContext = context; mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.PopupWindow, defStyle, 0); mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground); // If this is a StateListDrawable, try to find and store the drawable to be // used when the drop-down is placed above its anchor view, and the one to be // used when the drop-down is placed below its anchor view. We extract // the drawables ourselves to work around a problem with using refreshDrawableState // that it will take into account the padding of all drawables specified in a // StateListDrawable, thus adding superfluous padding to drop-down views. // // We assume a StateListDrawable will have a drawable for ABOVE_ANCHOR_STATE_SET and // at least one other drawable, intended for the 'below-anchor state'. if (mBackground instanceof StateListDrawable) { StateListDrawable background = (StateListDrawable) mBackground; // Find the above-anchor view - this one's easy, it should be labeled as such. int aboveAnchorStateIndex = background.getStateDrawableIndex(ABOVE_ANCHOR_STATE_SET); // Now, for the below-anchor view, look for any other drawable specified in the // StateListDrawable which is not for the above-anchor state and use that. int count = background.getStateCount(); int belowAnchorStateIndex = -1; for (int i = 0; i < count; i++) { if (i != aboveAnchorStateIndex) { belowAnchorStateIndex = i; break; } } // Store the drawables we found, if we found them. Otherwise, set them both // to null so that we'll just use refreshDrawableState. if (aboveAnchorStateIndex != -1 && belowAnchorStateIndex != -1) { mAboveAnchorBackgroundDrawable = background.getStateDrawable(aboveAnchorStateIndex); mBelowAnchorBackgroundDrawable = background.getStateDrawable(belowAnchorStateIndex); } else { mBelowAnchorBackgroundDrawable = null; mAboveAnchorBackgroundDrawable = null; } } a.recycle(); } /** * <p>Create a new empty, non focusable popup window of dimension (0,0). * * <p>The popup does not provide any background. This should be handled * by the content view.</p> */ public PopupWindow() { this(null, 0, 0); } /** * <p>Create a new non focusable popup window which can display the * <tt>contentView. The dimension of the window are (0,0). * * <p>The popup does not provide any background. This should be handled * by the content view.</p> * * @param contentView the popup's content */ public PopupWindow(View contentView) { this(contentView, 0, 0); } /** * <p>Create a new empty, non focusable popup window. The dimension of the * window must be passed to this constructor.</p> * * <p>The popup does not provide any background. This should be handled * by the content view.</p> * * @param width the popup's width * @param height the popup's height */ public PopupWindow(int width, int height) { this(null, width, height); } /** * <p>Create a new non focusable popup window which can display the * <tt>contentView. The dimension of the window must be passed to * this constructor.</p> * * <p>The popup does not provide any background. This should be handled * by the content view.</p> * * @param contentView the popup's content * @param width the popup's width * @param height the popup's height */ public PopupWindow(View contentView, int width, int height) { this(contentView, width, height, false); } /** * <p>Create a new popup window which can display the contentView. * The dimension of the window must be passed to this constructor.</p> * * <p>The popup does not provide any background. This should be handled * by the content view.</p> * * @param contentView the popup's content * @param width the popup's width * @param height the popup's height * @param focusable true if the popup can be focused, false otherwise */ public PopupWindow(View contentView, int width, int height, boolean focusable) { if (contentView != null) { mContext = contentView.getContext(); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } setContentView(contentView); setWidth(width); setHeight(height); setFocusable(focusable); } /** * <p>Return the drawable used as the popup window's background. * * @return the background drawable or null */ public Drawable getBackground() { return mBackground; } /** * <p>Change the background drawable for this popup window. The background * can be set to null.</p> * * @param background the popup's background */ public void setBackgroundDrawable(Drawable background) { mBackground = background; } /** * <p>Return the animation style to use the popup appears and disappears * * @return the animation style to use the popup appears and disappears */ public int getAnimationStyle() { return mAnimationStyle; } /** * Set the flag on popup to ignore cheek press eventt; by default this flag * is set to false * which means the pop wont ignore cheek press dispatch events. * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @see #update() */ public void setIgnoreCheekPress() { mIgnoreCheekPress = true; } /** * <p>Change the animation style resource for this popup. * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @param animationStyle animation style to use when the popup appears * and disappears. Set to -1 for the default animation, 0 for no * animation, or a resource identifier for an explicit animation. * * @see #update() */ public void setAnimationStyle(int animationStyle) { mAnimationStyle = animationStyle; } /** * <p>Return the view used as the content of the popup window. * * @return a {@link android.view.View} representing the popup's content * * @see #setContentView(android.view.View) */ public View getContentView() { return mContentView; } /** * <p>Change the popup's content. The content is represented by an instance * of {@link android.view.View}.</p> * * <p>This method has no effect if called when the popup is showing. To * apply it while a popup is showing, call </p> * * @param contentView the new content for the popup * * @see #getContentView() * @see #isShowing() */ public void setContentView(View contentView) { if (isShowing()) { return; } mContentView = contentView; if (mContext == null) { mContext = mContentView.getContext(); } if (mWindowManager == null) { mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } } /** * Set a callback for all touch events being dispatched to the popup * window. */ public void setTouchInterceptor(OnTouchListener l) { mTouchInterceptor = l; } /** * <p>Indicate whether the popup window can grab the focus. * * @return true if the popup is focusable, false otherwise * * @see #setFocusable(boolean) */ public boolean isFocusable() { return mFocusable; } /** * <p>Changes the focusability of the popup window. When focusable, the * window will grab the focus from the current focused widget if the popup * contains a focusable {@link android.view.View}. By default a popup * window is not focusable.</p> * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @param focusable true if the popup should grab focus, false otherwise. * * @see #isFocusable() * @see #isShowing() * @see #update() */ public void setFocusable(boolean focusable) { mFocusable = focusable; } /** * Return the current value in {@link #setInputMethodMode(int)}. * * @see #setInputMethodMode(int) */ public int getInputMethodMode() { return mInputMethodMode; } /** * Control how the popup operates with an input method: one of * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED}, * or {@link #INPUT_METHOD_NOT_NEEDED}. * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @see #getInputMethodMode() * @see #update() */ public void setInputMethodMode(int mode) { mInputMethodMode = mode; } /** * Sets the operating mode for the soft input area. * * @param mode The desired mode, see * {@link android.view.WindowManager.LayoutParams#softInputMode} * for the full list * * @see android.view.WindowManager.LayoutParams#softInputMode * @see #getSoftInputMode() */ public void setSoftInputMode(int mode) { mSoftInputMode = mode; } /** * Returns the current value in {@link #setSoftInputMode(int)}. * * @see #setSoftInputMode(int) * @see android.view.WindowManager.LayoutParams#softInputMode */ public int getSoftInputMode() { return mSoftInputMode; } /** * <p>Indicates whether the popup window receives touch events. * * @return true if the popup is touchable, false otherwise * * @see #setTouchable(boolean) */ public boolean isTouchable() { return mTouchable; } /** * <p>Changes the touchability of the popup window. When touchable, the * window will receive touch events, otherwise touch events will go to the * window below it. By default the window is touchable.</p> * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @param touchable true if the popup should receive touch events, false otherwise * * @see #isTouchable() * @see #isShowing() * @see #update() */ public void setTouchable(boolean touchable) { mTouchable = touchable; } /** * <p>Indicates whether the popup window will be informed of touch events * outside of its window.</p> * * @return true if the popup is outside touchable, false otherwise * * @see #setOutsideTouchable(boolean) */ public boolean isOutsideTouchable() { return mOutsideTouchable; } /** * <p>Controls whether the pop-up will be informed of touch events outside * of its window. This only makes sense for pop-ups that are touchable * but not focusable, which means touches outside of the window will * be delivered to the window behind. The default is false.</p> * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @param touchable true if the popup should receive outside * touch events, false otherwise * * @see #isOutsideTouchable() * @see #isShowing() * @see #update() */ public void setOutsideTouchable(boolean touchable) { mOutsideTouchable = touchable; } /** * <p>Indicates whether clipping of the popup window is enabled. * * @return true if the clipping is enabled, false otherwise * * @see #setClippingEnabled(boolean) */ public boolean isClippingEnabled() { return mClippingEnabled; } /** * <p>Allows the popup window to extend beyond the bounds of the screen. By default the * window is clipped to the screen boundaries. Setting this to false will allow windows to be * accurately positioned.</p> * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @param enabled false if the window should be allowed to extend outside of the screen * @see #isShowing() * @see #isClippingEnabled() * @see #update() */ public void setClippingEnabled(boolean enabled) { mClippingEnabled = enabled; } /** * <p>Change the width and height measure specs that are given to the * window manager by the popup. By default these are 0, meaning that * the current width or height is requested as an explicit size from * the window manager. You can supply * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or * {@link ViewGroup.LayoutParams#MATCH_PARENT} to have that measure * spec supplied instead, replacing the absolute width and height that * has been set in the popup.</p> * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown.</p> * * @param widthSpec an explicit width measure spec mode, either * {@link ViewGroup.LayoutParams#WRAP_CONTENT}, * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute * width. * @param heightSpec an explicit height measure spec mode, either * {@link ViewGroup.LayoutParams#WRAP_CONTENT}, * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute * height. */ public void setWindowLayoutMode(int widthSpec, int heightSpec) { mWidthMode = widthSpec; mHeightMode = heightSpec; } /** * <p>Return this popup's height MeasureSpec * * @return the height MeasureSpec of the popup * * @see #setHeight(int) */ public int getHeight() { return mHeight; } /** * <p>Change the popup's height MeasureSpec * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown.</p> * * @param height the height MeasureSpec of the popup * * @see #getHeight() * @see #isShowing() */ public void setHeight(int height) { mHeight = height; } /** * <p>Return this popup's width MeasureSpec * * @return the width MeasureSpec of the popup * * @see #setWidth(int) */ public int getWidth() { return mWidth; } /** * <p>Change the popup's width MeasureSpec * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown.</p> * * @param width the width MeasureSpec of the popup * * @see #getWidth() * @see #isShowing() */ public void setWidth(int width) { mWidth = width; } /** * <p>Indicate whether this popup window is showing on screen. * * @return true if the popup is showing, false otherwise */ public boolean isShowing() { return mIsShowing; } /** * <p> * Display the content view in a popup window at the specified location. If the popup window * cannot fit on screen, it will be clipped. See {@link android.view.WindowManager.LayoutParams} * for more information on how gravity and the x and y parameters are related. Specifying * a gravity of {@link android.view.Gravity#NO_GRAVITY} is similar to specifying * <code>Gravity.LEFT | Gravity.TOP. * </p> * * @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from * @param gravity the gravity which controls the placement of the popup window * @param x the popup's x location offset * @param y the popup's y location offset */ public void showAtLocation(View parent, int gravity, int x, int y) { if (isShowing() || mContentView == null) { return; } unregisterForScrollChanged(); mIsShowing = true; mIsDropdown = false; WindowManager.LayoutParams p = createPopupLayout(parent.getWindowToken()); p.windowAnimations = computeAnimationResource(); preparePopup(p); if (gravity == Gravity.NO_GRAVITY) { gravity = Gravity.TOP | Gravity.LEFT; } p.gravity = gravity; p.x = x; p.y = y; invokePopup(p); } /** * <p>Display the content view in a popup window anchored to the bottom-left * corner of the anchor view. If there is not enough room on screen to show * the popup in its entirety, this method tries to find a parent scroll * view to scroll. If no parent scroll view can be scrolled, the bottom-left * corner of the popup is pinned at the top left corner of the anchor view.</p> * * @param anchor the view on which to pin the popup window * * @see #dismiss() */ public void showAsDropDown(View anchor) { showAsDropDown(anchor, 0, 0); } /** * <p>Display the content view in a popup window anchored to the bottom-left * corner of the anchor view offset by the specified x and y coordinates. * If there is not enough room on screen to show * the popup in its entirety, this method tries to find a parent scroll * view to scroll. If no parent scroll view can be scrolled, the bottom-left * corner of the popup is pinned at the top left corner of the anchor view.</p> * <p>If the view later scrolls to move Other Android examples (source code examples)Here is a short list of links related to this Android PopupWindow.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.