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> ...@@ -465,7 +465,9 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
getTabModelSelector(), getControlContainerHeightResource()); getTabModelSelector(), getControlContainerHeightResource());
} }
((BottomContainer) findViewById(R.id.bottom_container)).initialize(mFullscreenManager); ((BottomContainer) findViewById(R.id.bottom_container))
.initialize(mFullscreenManager,
mManualFillingController.getKeyboardExtensionSizeManager());
mModalDialogManager = createModalDialogManager(); mModalDialogManager = createModalDialogManager();
......
...@@ -8,6 +8,7 @@ import android.content.Context; ...@@ -8,6 +8,7 @@ import android.content.Context;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.FrameLayout; 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;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
...@@ -17,10 +18,14 @@ import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver; ...@@ -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 * The container that holds both infobars and snackbars. It will be translated up and down when the
* bottom controls' offset changes. * 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. */ /** The {@link ChromeFullscreenManager} to listen for controls offset changes. */
private ChromeFullscreenManager mFullscreenManager; 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. */ /** The desired Y offset if unaffected by other UI. */
private float mBaseYOffset; private float mBaseYOffset;
...@@ -37,9 +42,12 @@ public class BottomContainer extends FrameLayout implements FullscreenListener { ...@@ -37,9 +42,12 @@ public class BottomContainer extends FrameLayout implements FullscreenListener {
/** /**
* Initializes this container. * Initializes this container.
*/ */
public void initialize(ChromeFullscreenManager fullscreenManager) { public void initialize(ChromeFullscreenManager fullscreenManager,
KeyboardExtensionSizeManager keyboardExtensionSizeManager) {
mFullscreenManager = fullscreenManager; mFullscreenManager = fullscreenManager;
mFullscreenManager.addListener(this); mFullscreenManager.addListener(this);
mKeyboardExtensionSizeManager = keyboardExtensionSizeManager;
mKeyboardExtensionSizeManager.addObserver(this);
setTranslationY(mBaseYOffset); setTranslationY(mBaseYOffset);
} }
...@@ -62,6 +70,12 @@ public class BottomContainer extends FrameLayout implements FullscreenListener { ...@@ -62,6 +70,12 @@ public class BottomContainer extends FrameLayout implements FullscreenListener {
}); });
} }
// KeyboardExtensionSizeManager methods
@Override
public void onKeyboardExtensionHeightChanged(int keyboardHeight) {
setTranslationY(mBaseYOffset);
}
// FullscreenListener methods // FullscreenListener methods
@Override @Override
public void onControlsOffsetChanged(float topOffset, float bottomOffset, boolean needsAnimate) { public void onControlsOffsetChanged(float topOffset, float bottomOffset, boolean needsAnimate) {
...@@ -74,6 +88,7 @@ public class BottomContainer extends FrameLayout implements FullscreenListener { ...@@ -74,6 +88,7 @@ public class BottomContainer extends FrameLayout implements FullscreenListener {
float offsetFromControls = mFullscreenManager.getBottomControlOffset() float offsetFromControls = mFullscreenManager.getBottomControlOffset()
- mFullscreenManager.getBottomControlsHeight(); - mFullscreenManager.getBottomControlsHeight();
offsetFromControls -= mKeyboardExtensionSizeManager.getKeyboardExtensionHeight();
// Sit on top of either the bottom sheet or the bottom toolbar depending on which is larger // Sit on top of either the bottom sheet or the bottom toolbar depending on which is larger
// (offsets are negative). // (offsets are negative).
......
...@@ -8,6 +8,7 @@ import static android.support.test.espresso.Espresso.onView; ...@@ -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.doesNotExist;
import static android.support.test.espresso.assertion.ViewAssertions.matches; 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.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.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText; import static android.support.test.espresso.matcher.ViewMatchers.withText;
...@@ -40,6 +41,8 @@ import org.chromium.chrome.browser.autofill.AutofillTestHelper; ...@@ -40,6 +41,8 @@ import org.chromium.chrome.browser.autofill.AutofillTestHelper;
import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.infobar.InfoBarIdentifier; import org.chromium.chrome.browser.infobar.InfoBarIdentifier;
import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; 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.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.InfoBarTestAnimationListener; import org.chromium.chrome.test.util.InfoBarTestAnimationListener;
...@@ -428,4 +431,40 @@ public class ManualFillingIntegrationTest { ...@@ -428,4 +431,40 @@ public class ManualFillingIntegrationTest {
whenDisplayed(withText(kInfoBarText)); 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 { ...@@ -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 * Pauses/Unpauses VSync. When VSync is paused the compositor for this window will idle, and
* requestAnimationFrame callbacks won't fire, etc. * 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