Commit ed34d0a0 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Android] Ensure accessory doesn't overlay snackbars

Bottom containers and snackbars try to infer on their own how large the
keyboard is. This CL makes them consider extensions and replacements as
well -- long-term, we probably want to use a keyboard delegate there.

Bug: 898468
Change-Id: Iae8a68b2f868015f64d8e1361fe46b1d7740921f
Reviewed-on: https://chromium-review.googlesource.com/c/1309791Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Commit-Queue: Friedrich Horschig [CET] <fhorschig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605307}
parent 6d6f2996
......@@ -465,7 +465,9 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
getTabModelSelector(), getControlContainerHeightResource());
}
((BottomContainer) findViewById(R.id.bottom_container)).initialize(mFullscreenManager);
((BottomContainer) findViewById(R.id.bottom_container))
.initialize(mFullscreenManager,
mManualFillingController.getKeyboardExtensionSizeManager());
mModalDialogManager = createModalDialogManager();
......
......@@ -8,6 +8,7 @@ import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardExtensionSizeManager;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
......@@ -17,10 +18,14 @@ import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver;
* The container that holds both infobars and snackbars. It will be translated up and down when the
* bottom controls' offset changes.
*/
public class BottomContainer extends FrameLayout implements FullscreenListener {
public class BottomContainer
extends FrameLayout implements FullscreenListener, KeyboardExtensionSizeManager.Observer {
/** The {@link ChromeFullscreenManager} to listen for controls offset changes. */
private ChromeFullscreenManager mFullscreenManager;
/** A {@link KeyboardExtensionSizeManager} to listen to for keyboard extension size changes. */
private KeyboardExtensionSizeManager mKeyboardExtensionSizeManager;
/** The desired Y offset if unaffected by other UI. */
private float mBaseYOffset;
......@@ -37,9 +42,12 @@ public class BottomContainer extends FrameLayout implements FullscreenListener {
/**
* Initializes this container.
*/
public void initialize(ChromeFullscreenManager fullscreenManager) {
public void initialize(ChromeFullscreenManager fullscreenManager,
KeyboardExtensionSizeManager keyboardExtensionSizeManager) {
mFullscreenManager = fullscreenManager;
mFullscreenManager.addListener(this);
mKeyboardExtensionSizeManager = keyboardExtensionSizeManager;
mKeyboardExtensionSizeManager.addObserver(this);
setTranslationY(mBaseYOffset);
}
......@@ -62,6 +70,12 @@ public class BottomContainer extends FrameLayout implements FullscreenListener {
});
}
// KeyboardExtensionSizeManager methods
@Override
public void onKeyboardExtensionHeightChanged(int keyboardHeight) {
setTranslationY(mBaseYOffset);
}
// FullscreenListener methods
@Override
public void onControlsOffsetChanged(float topOffset, float bottomOffset, boolean needsAnimate) {
......@@ -74,6 +88,7 @@ public class BottomContainer extends FrameLayout implements FullscreenListener {
float offsetFromControls = mFullscreenManager.getBottomControlOffset()
- mFullscreenManager.getBottomControlsHeight();
offsetFromControls -= mKeyboardExtensionSizeManager.getKeyboardExtensionHeight();
// Sit on top of either the bottom sheet or the bottom toolbar depending on which is larger
// (offsets are negative).
......
......@@ -8,6 +8,7 @@ import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
......@@ -40,6 +41,8 @@ import org.chromium.chrome.browser.autofill.AutofillTestHelper;
import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.infobar.InfoBarIdentifier;
import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder;
import org.chromium.chrome.browser.snackbar.Snackbar;
import org.chromium.chrome.browser.snackbar.SnackbarManager;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.InfoBarTestAnimationListener;
......@@ -428,4 +431,40 @@ public class ManualFillingIntegrationTest {
whenDisplayed(withText(kInfoBarText));
}
@Test
@SmallTest
public void testMovesUpSnackbar() throws InterruptedException, TimeoutException {
final String kSnackbarText = "snackbar";
mHelper.loadTestPage(false);
mHelper.createTestTab();
// Create a simple, persistent snackbar and verify it's displayed.
SnackbarManager manager = mActivityTestRule.getActivity().getSnackbarManager();
ThreadUtils.runOnUiThread(
()
-> manager.showSnackbar(Snackbar.make(kSnackbarText,
new SnackbarManager.SnackbarController() {},
Snackbar.TYPE_PERSISTENT, Snackbar.UMA_TEST_SNACKBAR)));
CriteriaHelper.pollUiThread(manager::isShowing);
CriteriaHelper.pollUiThread(
mActivityTestRule.getActivity().getWindowAndroid()::haveAnimationsEnded);
// Click in a field to open keyboard and accessory -- this shouldn't hide the snackbar.
mHelper.clickPasswordField();
mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.keyboard_accessory));
onView(withText(kSnackbarText)).check(matches(isCompletelyDisplayed()));
// Open a keyboard accessory sheet -- this also shouldn't hide the snackbar.
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
whenDisplayed(withId(R.id.keyboard_accessory_sheet));
onView(withText(kSnackbarText)).check(matches(isCompletelyDisplayed()));
// Click into the email field to dismiss the keyboard accessory.
mHelper.clickEmailField(false);
mHelper.waitToBeHidden(withId(R.id.keyboard_accessory));
onView(withText(kSnackbarText)).check(matches(isCompletelyDisplayed()));
}
}
......@@ -796,6 +796,15 @@ public class WindowAndroid implements AndroidPermissionDelegate {
}
}
/**
* As long as there are still animations which haven't ended, this will return false.
* @return True if all known animations have ended.
*/
@VisibleForTesting
public boolean haveAnimationsEnded() {
return mAnimationsOverContent.isEmpty();
}
/**
* Pauses/Unpauses VSync. When VSync is paused the compositor for this window will idle, and
* requestAnimationFrame callbacks won't fire, etc.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment