blob: 658307a43793c1fb38ff48ca936bc3e03233fe75 [file] [log] [blame]
/*
* Copyright (C) 2008 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.cts;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.transition.Transition;
import android.transition.Transition.TransitionListener;
import android.transition.TransitionValues;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import android.widget.TextView;
import android.widget.cts.R;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class PopupWindowTest extends
ActivityInstrumentationTestCase2<MockPopupWindowCtsActivity> {
private Instrumentation mInstrumentation;
private Activity mActivity;
/** The popup window. */
private PopupWindow mPopupWindow;
/**
* Instantiates a new popup window test.
*/
public PopupWindowTest() {
super("android.widget.cts", MockPopupWindowCtsActivity.class);
}
/*
* (non-Javadoc)
*
* @see android.test.ActivityInstrumentationTestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
mInstrumentation = getInstrumentation();
mActivity = getActivity();
}
public void testConstructor() {
new PopupWindow(mActivity);
new PopupWindow(mActivity, null);
new PopupWindow(mActivity, null, android.R.attr.popupWindowStyle);
mPopupWindow = new PopupWindow();
assertEquals(0, mPopupWindow.getWidth());
assertEquals(0, mPopupWindow.getHeight());
mPopupWindow = new PopupWindow(50, 50);
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
mPopupWindow = new PopupWindow(-1, -1);
assertEquals(-1, mPopupWindow.getWidth());
assertEquals(-1, mPopupWindow.getHeight());
TextView contentView = new TextView(mActivity);
mPopupWindow = new PopupWindow(contentView);
assertSame(contentView, mPopupWindow.getContentView());
mPopupWindow = new PopupWindow(contentView, 0, 0);
assertEquals(0, mPopupWindow.getWidth());
assertEquals(0, mPopupWindow.getHeight());
assertSame(contentView, mPopupWindow.getContentView());
mPopupWindow = new PopupWindow(contentView, 50, 50);
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
assertSame(contentView, mPopupWindow.getContentView());
mPopupWindow = new PopupWindow(contentView, -1, -1);
assertEquals(-1, mPopupWindow.getWidth());
assertEquals(-1, mPopupWindow.getHeight());
assertSame(contentView, mPopupWindow.getContentView());
mPopupWindow = new PopupWindow(contentView, 0, 0, true);
assertEquals(0, mPopupWindow.getWidth());
assertEquals(0, mPopupWindow.getHeight());
assertSame(contentView, mPopupWindow.getContentView());
assertTrue(mPopupWindow.isFocusable());
mPopupWindow = new PopupWindow(contentView, 50, 50, false);
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
assertSame(contentView, mPopupWindow.getContentView());
assertFalse(mPopupWindow.isFocusable());
mPopupWindow = new PopupWindow(contentView, -1, -1, true);
assertEquals(-1, mPopupWindow.getWidth());
assertEquals(-1, mPopupWindow.getHeight());
assertSame(contentView, mPopupWindow.getContentView());
assertTrue(mPopupWindow.isFocusable());
}
public void testAccessEnterExitTransitions() {
PopupWindow w;
w = new PopupWindow(mActivity, null, 0, 0);
assertNull(w.getEnterTransition());
assertNull(w.getExitTransition());
w = new PopupWindow(mActivity, null, 0, R.style.PopupWindow_NullTransitions);
assertNull(w.getEnterTransition());
assertNull(w.getExitTransition());
w = new PopupWindow(mActivity, null, 0, R.style.PopupWindow_CustomTransitions);
assertTrue(w.getEnterTransition() instanceof CustomTransition);
assertTrue(w.getExitTransition() instanceof CustomTransition);
Transition enterTransition = new CustomTransition();
Transition exitTransition = new CustomTransition();
w = new PopupWindow(mActivity, null, 0, 0);
w.setEnterTransition(enterTransition);
w.setExitTransition(exitTransition);
assertEquals(enterTransition, w.getEnterTransition());
assertEquals(exitTransition, w.getExitTransition());
w.setEnterTransition(null);
w.setExitTransition(null);
assertNull(w.getEnterTransition());
assertNull(w.getExitTransition());
}
public static class CustomTransition extends Transition {
public CustomTransition() {
}
// This constructor is needed for reflection-based creation of a transition when
// the transition is defined in layout XML via attribute.
@SuppressWarnings("unused")
public CustomTransition(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void captureStartValues(TransitionValues transitionValues) {}
@Override
public void captureEndValues(TransitionValues transitionValues) {}
}
public void testAccessBackground() {
mPopupWindow = new PopupWindow(mActivity);
Drawable drawable = new ColorDrawable();
mPopupWindow.setBackgroundDrawable(drawable);
assertSame(drawable, mPopupWindow.getBackground());
mPopupWindow.setBackgroundDrawable(null);
assertNull(mPopupWindow.getBackground());
}
public void testAccessAnimationStyle() {
mPopupWindow = new PopupWindow(mActivity);
// default is -1
assertEquals(-1, mPopupWindow.getAnimationStyle());
mPopupWindow.setAnimationStyle(android.R.style.Animation_Toast);
assertEquals(android.R.style.Animation_Toast,
mPopupWindow.getAnimationStyle());
// abnormal values
mPopupWindow.setAnimationStyle(-100);
assertEquals(-100, mPopupWindow.getAnimationStyle());
}
public void testAccessContentView() {
mPopupWindow = new PopupWindow(mActivity);
assertNull(mPopupWindow.getContentView());
View view = new TextView(mActivity);
mPopupWindow.setContentView(view);
assertSame(view, mPopupWindow.getContentView());
mPopupWindow.setContentView(null);
assertNull(mPopupWindow.getContentView());
// can not set the content if the old content is shown
mPopupWindow.setContentView(view);
assertFalse(mPopupWindow.isShowing());
showPopup();
ImageView img = new ImageView(mActivity);
assertTrue(mPopupWindow.isShowing());
mPopupWindow.setContentView(img);
assertSame(view, mPopupWindow.getContentView());
dismissPopup();
}
public void testAccessFocusable() {
mPopupWindow = new PopupWindow(mActivity);
assertFalse(mPopupWindow.isFocusable());
mPopupWindow.setFocusable(true);
assertTrue(mPopupWindow.isFocusable());
mPopupWindow.setFocusable(false);
assertFalse(mPopupWindow.isFocusable());
}
public void testAccessHeight() {
mPopupWindow = new PopupWindow(mActivity);
assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getHeight());
int height = getDisplay().getHeight() / 2;
mPopupWindow.setHeight(height);
assertEquals(height, mPopupWindow.getHeight());
height = getDisplay().getHeight();
mPopupWindow.setHeight(height);
assertEquals(height, mPopupWindow.getHeight());
mPopupWindow.setHeight(0);
assertEquals(0, mPopupWindow.getHeight());
height = getDisplay().getHeight() * 2;
mPopupWindow.setHeight(height);
assertEquals(height, mPopupWindow.getHeight());
height = -getDisplay().getHeight() / 2;
mPopupWindow.setHeight(height);
assertEquals(height, mPopupWindow.getHeight());
}
/**
* Gets the display.
*
* @return the display
*/
private Display getDisplay() {
WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
return wm.getDefaultDisplay();
}
public void testAccessWidth() {
mPopupWindow = new PopupWindow(mActivity);
assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getWidth());
int width = getDisplay().getWidth() / 2;
mPopupWindow.setWidth(width);
assertEquals(width, mPopupWindow.getWidth());
width = getDisplay().getWidth();
mPopupWindow.setWidth(width);
assertEquals(width, mPopupWindow.getWidth());
mPopupWindow.setWidth(0);
assertEquals(0, mPopupWindow.getWidth());
width = getDisplay().getWidth() * 2;
mPopupWindow.setWidth(width);
assertEquals(width, mPopupWindow.getWidth());
width = - getDisplay().getWidth() / 2;
mPopupWindow.setWidth(width);
assertEquals(width, mPopupWindow.getWidth());
}
public void testShowAsDropDown() {
int[] anchorXY = new int[2];
int[] viewOnScreenXY = new int[2];
int[] viewInWindowXY = new int[2];
mPopupWindow = createPopupWindow(createPopupContent());
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
upperAnchor.getLocationOnScreen(anchorXY);
mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
assertEquals(anchorXY[0] + viewInWindowXY[0], viewOnScreenXY[0]);
assertEquals(anchorXY[1] + viewInWindowXY[1] + upperAnchor.getHeight(), viewOnScreenXY[1]);
dismissPopup();
}
public void testShowAtLocation() {
int[] popupContentViewInWindowXY = new int[2];
int[] popupContentViewOnScreenXY = new int[2];
mPopupWindow = createPopupWindow(createPopupContent());
// Do not attach within the decor; we will be measuring location
// with regard to screen coordinates.
mPopupWindow.setAttachedInDecor(false);
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
final int xOff = 10;
final int yOff = 21;
assertFalse(mPopupWindow.isShowing());
mPopupWindow.getContentView().getLocationInWindow(popupContentViewInWindowXY);
assertEquals(0, popupContentViewInWindowXY[0]);
assertEquals(0, popupContentViewInWindowXY[1]);
mInstrumentation.runOnMainSync(
() -> mPopupWindow.showAtLocation(upperAnchor, Gravity.NO_GRAVITY, xOff, yOff));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
mPopupWindow.getContentView().getLocationInWindow(popupContentViewInWindowXY);
mPopupWindow.getContentView().getLocationOnScreen(popupContentViewOnScreenXY);
assertTrue(popupContentViewInWindowXY[0] >= 0);
assertTrue(popupContentViewInWindowXY[1] >= 0);
assertEquals(popupContentViewInWindowXY[0] + xOff, popupContentViewOnScreenXY[0]);
assertEquals(popupContentViewInWindowXY[1] + yOff, popupContentViewOnScreenXY[1]);
dismissPopup();
}
public void testShowAsDropDownWithOffsets() {
int[] anchorXY = new int[2];
int[] viewOnScreenXY = new int[2];
int[] viewInWindowXY = new int[2];
mPopupWindow = createPopupWindow(createPopupContent());
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
upperAnchor.getLocationOnScreen(anchorXY);
int height = upperAnchor.getHeight();
final int xOff = 11;
final int yOff = 12;
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor, xOff, yOff));
mInstrumentation.waitForIdleSync();
mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
assertEquals(anchorXY[0] + xOff + viewInWindowXY[0], viewOnScreenXY[0]);
assertEquals(anchorXY[1] + height + yOff + viewInWindowXY[1], viewOnScreenXY[1]);
dismissPopup();
}
public void testOverlapAnchor() {
int[] anchorXY = new int[2];
int[] viewOnScreenXY = new int[2];
int[] viewInWindowXY = new int[2];
mPopupWindow = createPopupWindow(createPopupContent());
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
upperAnchor.getLocationOnScreen(anchorXY);
assertFalse(mPopupWindow.getOverlapAnchor());
mPopupWindow.setOverlapAnchor(true);
assertTrue(mPopupWindow.getOverlapAnchor());
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor, 0, 0));
mInstrumentation.waitForIdleSync();
mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
assertEquals(anchorXY[0] + viewInWindowXY[0], viewOnScreenXY[0]);
assertEquals(anchorXY[1] + viewInWindowXY[1], viewOnScreenXY[1]);
}
public void testAccessWindowLayoutType() {
mPopupWindow = createPopupWindow(createPopupContent());
assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
mPopupWindow.getWindowLayoutType());
mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
mPopupWindow.getWindowLayoutType());
}
public void testGetMaxAvailableHeight() {
mPopupWindow = createPopupWindow(createPopupContent());
View anchorView = mActivity.findViewById(R.id.anchor_upper);
int avaliable = getDisplay().getHeight() - anchorView.getHeight();
int maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
assertTrue(maxAvailableHeight > 0);
assertTrue(maxAvailableHeight <= avaliable);
int maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, 2);
assertEquals(maxAvailableHeight - 2, maxAvailableHeightWithOffset);
maxAvailableHeightWithOffset =
mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight);
assertTrue(maxAvailableHeightWithOffset > 0);
assertTrue(maxAvailableHeightWithOffset <= avaliable);
maxAvailableHeightWithOffset =
mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1);
assertTrue(maxAvailableHeightWithOffset > 0);
assertTrue(maxAvailableHeightWithOffset <= avaliable);
maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, -1);
assertTrue(maxAvailableHeightWithOffset > 0);
assertTrue(maxAvailableHeightWithOffset <= avaliable);
anchorView = mActivity.findViewById(R.id.anchor_lower);
// On some devices the view might actually have larger size than the physical display
// due to chin and content will be laid out as if outside of the display. We need to use
// larger from the display height and the main view height.
avaliable = Math.max(getDisplay().getHeight(),
mActivity.findViewById(android.R.id.content).getHeight()) - anchorView.getHeight();
maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
assertTrue(maxAvailableHeight > 0);
assertTrue(maxAvailableHeight <= avaliable);
anchorView = mActivity.findViewById(R.id.anchor_middle_left);
avaliable = getDisplay().getHeight() - anchorView.getHeight()
- mActivity.findViewById(R.id.anchor_upper).getHeight();
maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
assertTrue(maxAvailableHeight > 0);
assertTrue(maxAvailableHeight <= avaliable);
}
@UiThreadTest
public void testDismiss() {
mPopupWindow = createPopupWindow(createPopupContent());
assertFalse(mPopupWindow.isShowing());
View anchorView = mActivity.findViewById(R.id.anchor_upper);
mPopupWindow.showAsDropDown(anchorView);
mPopupWindow.dismiss();
assertFalse(mPopupWindow.isShowing());
mPopupWindow.dismiss();
assertFalse(mPopupWindow.isShowing());
}
public void testSetOnDismissListener() {
mPopupWindow = new PopupWindow(new TextView(mActivity));
mPopupWindow.setOnDismissListener(null);
OnDismissListener onDismissListener = mock(OnDismissListener.class);
mPopupWindow.setOnDismissListener(onDismissListener);
showPopup();
dismissPopup();
verify(onDismissListener, times(1)).onDismiss();
showPopup();
dismissPopup();
verify(onDismissListener, times(2)).onDismiss();
mPopupWindow.setOnDismissListener(null);
showPopup();
dismissPopup();
verify(onDismissListener, times(2)).onDismiss();
}
public void testUpdate() {
mPopupWindow = createPopupWindow(createPopupContent());
mPopupWindow.setBackgroundDrawable(null);
showPopup();
mPopupWindow.setIgnoreCheekPress();
mPopupWindow.setFocusable(true);
mPopupWindow.setTouchable(false);
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
mPopupWindow.setClippingEnabled(false);
mPopupWindow.setOutsideTouchable(true);
WindowManager.LayoutParams p = (WindowManager.LayoutParams)
mPopupWindow.getContentView().getRootView().getLayoutParams();
assertEquals(0, WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES & p.flags);
assertEquals(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE & p.flags);
assertEquals(0, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE & p.flags);
assertEquals(0, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH & p.flags);
assertEquals(0, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS & p.flags);
assertEquals(0, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
mInstrumentation.runOnMainSync(() -> mPopupWindow.update());
mInstrumentation.waitForIdleSync();
assertEquals(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES,
WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES & p.flags);
assertEquals(0, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE & p.flags);
assertEquals(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE & p.flags);
assertEquals(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH & p.flags);
assertEquals(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS & p.flags);
assertEquals(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
}
public void testEnterExitTransition() {
TransitionListener enterListener = mock(TransitionListener.class);
Transition enterTransition = new BaseTransition();
enterTransition.addListener(enterListener);
TransitionListener exitListener = mock(TransitionListener.class);
Transition exitTransition = new BaseTransition();
exitTransition.addListener(exitListener);
OnDismissListener dismissListener = mock(OnDismissListener.class);
mPopupWindow = createPopupWindow(createPopupContent());
mPopupWindow.setEnterTransition(enterTransition);
mPopupWindow.setExitTransition(exitTransition);
mPopupWindow.setOnDismissListener(dismissListener);
verify(enterListener, never()).onTransitionStart(any(Transition.class));
verify(exitListener, never()).onTransitionStart(any(Transition.class));
verify(dismissListener, never()).onDismiss();
final View anchorView = mActivity.findViewById(R.id.anchor_upper);
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(anchorView, 0, 0));
mInstrumentation.waitForIdleSync();
verify(enterListener, times(1)).onTransitionStart(any(Transition.class));
verify(exitListener, never()).onTransitionStart(any(Transition.class));
verify(dismissListener, never()).onDismiss();
mInstrumentation.runOnMainSync(() -> mPopupWindow.dismiss());
mInstrumentation.waitForIdleSync();
verify(enterListener, times(1)).onTransitionStart(any(Transition.class));
verify(exitListener, times(1)).onTransitionStart(any(Transition.class));
verify(dismissListener, times(1)).onDismiss();
}
public void testUpdatePositionAndDimension() {
int[] fstXY = new int[2];
int[] sndXY = new int[2];
int[] viewInWindowXY = new int[2];
mInstrumentation.runOnMainSync(() -> {
mPopupWindow = createPopupWindow(createPopupContent());
// Do not attach within the decor; we will be measuring location
// with regard to screen coordinates.
mPopupWindow.setAttachedInDecor(false);
});
mInstrumentation.waitForIdleSync();
// Do not update if it is not shown
assertFalse(mPopupWindow.isShowing());
assertEquals(100, mPopupWindow.getWidth());
assertEquals(100, mPopupWindow.getHeight());
showPopup();
mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
// update if it is not shown
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
mPopupWindow.getContentView().getLocationOnScreen(fstXY);
assertEquals(viewInWindowXY[0] + 20, fstXY[0]);
assertEquals(viewInWindowXY[1] + 50, fstXY[1]);
// ignore if width or height is -1
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(4, 0, -1, -1, true));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
mPopupWindow.getContentView().getLocationOnScreen(sndXY);
assertEquals(viewInWindowXY[0] + 4, sndXY[0]);
assertEquals(viewInWindowXY[1], sndXY[1]);
dismissPopup();
}
public void testUpdateDimensionAndAlignAnchorView() {
mInstrumentation.runOnMainSync(
() -> mPopupWindow = createPopupWindow(createPopupContent()));
mInstrumentation.waitForIdleSync();
final View anchorView = mActivity.findViewById(R.id.anchor_upper);
mPopupWindow.update(anchorView, 50, 50);
// Do not update if it is not shown
assertFalse(mPopupWindow.isShowing());
assertEquals(100, mPopupWindow.getWidth());
assertEquals(100, mPopupWindow.getHeight());
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(anchorView));
mInstrumentation.waitForIdleSync();
// update if it is shown
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 50, 50));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
// ignore if width or height is -1
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, -1, -1));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
mInstrumentation.runOnMainSync(() -> mPopupWindow.dismiss());
mInstrumentation.waitForIdleSync();
}
public void testUpdateDimensionAndAlignAnchorViewWithOffsets() {
int[] anchorXY = new int[2];
int[] viewInWindowOff = new int[2];
int[] viewXY = new int[2];
mPopupWindow = createPopupWindow(createPopupContent());
final View anchorView = mActivity.findViewById(R.id.anchor_upper);
// Do not update if it is not shown
assertFalse(mPopupWindow.isShowing());
assertEquals(100, mPopupWindow.getWidth());
assertEquals(100, mPopupWindow.getHeight());
showPopup();
anchorView.getLocationOnScreen(anchorXY);
mPopupWindow.getContentView().getLocationInWindow(viewInWindowOff);
// update if it is not shown
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 20, 50, 50, 50));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
mPopupWindow.getContentView().getLocationOnScreen(viewXY);
// The popup should appear below and to right with an offset.
assertEquals(anchorXY[0] + 20 + viewInWindowOff[0], viewXY[0]);
assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
// ignore width and height but change location
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 10, 50, -1, -1));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
assertEquals(50, mPopupWindow.getWidth());
assertEquals(50, mPopupWindow.getHeight());
mPopupWindow.getContentView().getLocationOnScreen(viewXY);
// The popup should appear below and to right with an offset.
assertEquals(anchorXY[0] + 10 + viewInWindowOff[0], viewXY[0]);
assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
final View anotherView = mActivity.findViewById(R.id.anchor_middle_left);
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anotherView, 0, 0, 60, 60));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isShowing());
assertEquals(60, mPopupWindow.getWidth());
assertEquals(60, mPopupWindow.getHeight());
int[] newXY = new int[2];
anotherView.getLocationOnScreen(newXY);
mPopupWindow.getContentView().getLocationOnScreen(viewXY);
// The popup should appear below and to the right.
assertEquals(newXY[0] + viewInWindowOff[0], viewXY[0]);
assertEquals(newXY[1] + anotherView.getHeight() + viewInWindowOff[1], viewXY[1]);
dismissPopup();
}
public void testAccessInputMethodMode() {
mPopupWindow = new PopupWindow(mActivity);
assertEquals(0, mPopupWindow.getInputMethodMode());
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE);
assertEquals(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE, mPopupWindow.getInputMethodMode());
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
assertEquals(PopupWindow.INPUT_METHOD_NEEDED, mPopupWindow.getInputMethodMode());
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
assertEquals(PopupWindow.INPUT_METHOD_NOT_NEEDED, mPopupWindow.getInputMethodMode());
mPopupWindow.setInputMethodMode(-1);
assertEquals(-1, mPopupWindow.getInputMethodMode());
}
public void testAccessClippingEnabled() {
mPopupWindow = new PopupWindow(mActivity);
assertTrue(mPopupWindow.isClippingEnabled());
mPopupWindow.setClippingEnabled(false);
assertFalse(mPopupWindow.isClippingEnabled());
}
public void testAccessOutsideTouchable() {
mPopupWindow = new PopupWindow(mActivity);
assertFalse(mPopupWindow.isOutsideTouchable());
mPopupWindow.setOutsideTouchable(true);
assertTrue(mPopupWindow.isOutsideTouchable());
}
public void testAccessTouchable() {
mPopupWindow = new PopupWindow(mActivity);
assertTrue(mPopupWindow.isTouchable());
mPopupWindow.setTouchable(false);
assertFalse(mPopupWindow.isTouchable());
}
public void testIsAboveAnchor() {
mInstrumentation.runOnMainSync(() -> mPopupWindow = createPopupWindow(createPopupContent()));
mInstrumentation.waitForIdleSync();
final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor));
mInstrumentation.waitForIdleSync();
assertFalse(mPopupWindow.isAboveAnchor());
dismissPopup();
mPopupWindow = createPopupWindow(createPopupContent());
final View lowerAnchor = mActivity.findViewById(R.id.anchor_lower);
mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(lowerAnchor, 0, 0));
mInstrumentation.waitForIdleSync();
assertTrue(mPopupWindow.isAboveAnchor());
dismissPopup();
}
public void testSetTouchInterceptor() {
mPopupWindow = new PopupWindow(new TextView(mActivity));
OnTouchListener onTouchListener = mock(OnTouchListener.class);
when(onTouchListener.onTouch(any(View.class), any(MotionEvent.class))).thenReturn(true);
mPopupWindow.setTouchInterceptor(onTouchListener);
mPopupWindow.setFocusable(true);
mPopupWindow.setOutsideTouchable(true);
Drawable drawable = new ColorDrawable();
mPopupWindow.setBackgroundDrawable(drawable);
showPopup();
int[] xy = new int[2];
mPopupWindow.getContentView().getLocationOnScreen(xy);
final int viewWidth = mPopupWindow.getContentView().getWidth();
final int viewHeight = mPopupWindow.getContentView().getHeight();
final float x = xy[0] + (viewWidth / 2.0f);
float y = xy[1] + (viewHeight / 2.0f);
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime,
MotionEvent.ACTION_DOWN, x, y, 0);
getInstrumentation().sendPointerSync(event);
verify(onTouchListener, times(1)).onTouch(any(View.class), any(MotionEvent.class));
downTime = SystemClock.uptimeMillis();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
getInstrumentation().sendPointerSync(event);
verify(onTouchListener, times(2)).onTouch(any(View.class), any(MotionEvent.class));
mPopupWindow.setTouchInterceptor(null);
downTime = SystemClock.uptimeMillis();
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
getInstrumentation().sendPointerSync(event);
verify(onTouchListener, times(2)).onTouch(any(View.class), any(MotionEvent.class));
}
public void testSetWindowLayoutMode() {
mPopupWindow = new PopupWindow(new TextView(mActivity));
showPopup();
ViewGroup.LayoutParams p = mPopupWindow.getContentView().getRootView().getLayoutParams();
assertEquals(0, p.width);
assertEquals(0, p.height);
mPopupWindow.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
assertEquals(LayoutParams.WRAP_CONTENT, p.width);
assertEquals(LayoutParams.MATCH_PARENT, p.height);
}
private static class BaseTransition extends Transition {
@Override
public void captureStartValues(TransitionValues transitionValues) {}
@Override
public void captureEndValues(TransitionValues transitionValues) {}
}
private View createPopupContent() {
View popupView = new View(mActivity);
popupView.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
popupView.setBackgroundColor(Color.MAGENTA);
return popupView;
}
private PopupWindow createPopupWindow() {
PopupWindow window = new PopupWindow(mActivity);
window.setWidth(100);
window.setHeight(100);
return window;
}
private PopupWindow createPopupWindow(View content) {
PopupWindow window = createPopupWindow();
window.setContentView(content);
return window;
}
private void showPopup() {
mInstrumentation.runOnMainSync(() -> {
if (mPopupWindow == null || mPopupWindow.isShowing()) {
return;
}
View anchor = mActivity.findViewById(R.id.anchor_upper);
mPopupWindow.showAsDropDown(anchor);
assertTrue(mPopupWindow.isShowing());
});
mInstrumentation.waitForIdleSync();
}
private void dismissPopup() {
mInstrumentation.runOnMainSync(() -> {
if (mPopupWindow == null || !mPopupWindow.isShowing()) {
return;
}
mPopupWindow.dismiss();
});
mInstrumentation.waitForIdleSync();
}
}