summaryrefslogtreecommitdiff
path: root/library/main/src/com/android/setupwizardlib/util/SystemBarHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'library/main/src/com/android/setupwizardlib/util/SystemBarHelper.java')
-rw-r--r--library/main/src/com/android/setupwizardlib/util/SystemBarHelper.java599
1 files changed, 298 insertions, 301 deletions
diff --git a/library/main/src/com/android/setupwizardlib/util/SystemBarHelper.java b/library/main/src/com/android/setupwizardlib/util/SystemBarHelper.java
index 7e3e885..42350cc 100644
--- a/library/main/src/com/android/setupwizardlib/util/SystemBarHelper.java
+++ b/library/main/src/com/android/setupwizardlib/util/SystemBarHelper.java
@@ -24,6 +24,7 @@ import android.content.res.TypedArray;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
+import androidx.annotation.RequiresPermission;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -31,331 +32,327 @@ import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
-import androidx.annotation.RequiresPermission;
-
/**
* A helper class to manage the system navigation bar and status bar. This will add various
* systemUiVisibility flags to the given Window or View to make them follow the Setup Wizard style.
*
- * When the useImmersiveMode intent extra is true, a screen in Setup Wizard should hide the system
- * bars using methods from this class. For Lollipop, {@link #hideSystemBars(android.view.Window)}
- * will completely hide the system navigation bar and change the status bar to transparent, and
- * layout the screen contents (usually the illustration) behind it.
+ * <p>When the useImmersiveMode intent extra is true, a screen in Setup Wizard should hide the
+ * system bars using methods from this class. For Lollipop, {@link
+ * #hideSystemBars(android.view.Window)} will completely hide the system navigation bar and change
+ * the status bar to transparent, and layout the screen contents (usually the illustration) behind
+ * it.
*/
public class SystemBarHelper {
- private static final String TAG = "SystemBarHelper";
-
- @SuppressLint("InlinedApi")
- private static final int DEFAULT_IMMERSIVE_FLAGS =
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-
- @SuppressLint("InlinedApi")
- private static final int DIALOG_IMMERSIVE_FLAGS =
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-
- /**
- * Needs to be equal to View.STATUS_BAR_DISABLE_BACK
- */
- private static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
-
- /**
- * The maximum number of retries when peeking the decor view. When polling for the decor view,
- * waiting it to be installed, set a maximum number of retries.
- */
- private static final int PEEK_DECOR_VIEW_RETRIES = 3;
-
- /**
- * Hide the navigation bar for a dialog.
- *
- * <p>This will only take effect in versions Lollipop or above. Otherwise this is a no-op.
- */
- public static void hideSystemBars(final Dialog dialog) {
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- final Window window = dialog.getWindow();
- temporarilyDisableDialogFocus(window);
- addVisibilityFlag(window, DIALOG_IMMERSIVE_FLAGS);
- addImmersiveFlagsToDecorView(window, DIALOG_IMMERSIVE_FLAGS);
-
- // Also set the navigation bar and status bar to transparent color. Note that this
- // doesn't work if android.R.boolean.config_enableTranslucentDecor is false.
- window.setNavigationBarColor(0);
- window.setStatusBarColor(0);
- }
+ private static final String TAG = "SystemBarHelper";
+
+ @SuppressLint("InlinedApi")
+ private static final int DEFAULT_IMMERSIVE_FLAGS =
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+
+ @SuppressLint("InlinedApi")
+ private static final int DIALOG_IMMERSIVE_FLAGS =
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+
+ /** Needs to be equal to View.STATUS_BAR_DISABLE_BACK */
+ private static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
+
+ /**
+ * The maximum number of retries when peeking the decor view. When polling for the decor view,
+ * waiting it to be installed, set a maximum number of retries.
+ */
+ private static final int PEEK_DECOR_VIEW_RETRIES = 3;
+
+ /**
+ * Hide the navigation bar for a dialog.
+ *
+ * <p>This will only take effect in versions Lollipop or above. Otherwise this is a no-op.
+ */
+ public static void hideSystemBars(final Dialog dialog) {
+ if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ final Window window = dialog.getWindow();
+ temporarilyDisableDialogFocus(window);
+ addVisibilityFlag(window, DIALOG_IMMERSIVE_FLAGS);
+ addImmersiveFlagsToDecorView(window, DIALOG_IMMERSIVE_FLAGS);
+
+ // Also set the navigation bar and status bar to transparent color. Note that this
+ // doesn't work if android.R.boolean.config_enableTranslucentDecor is false.
+ window.setNavigationBarColor(0);
+ window.setStatusBarColor(0);
}
-
- /**
- * Hide the navigation bar, make the color of the status and navigation bars transparent, and
- * specify {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} flag so that the content is laid-out
- * behind the transparent status bar. This is commonly used with
- * {@link android.app.Activity#getWindow()} to make the navigation and status bars follow the
- * Setup Wizard style.
- *
- * <p>This will only take effect in versions Lollipop or above. Otherwise this is a no-op.
- */
- public static void hideSystemBars(final Window window) {
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- addVisibilityFlag(window, DEFAULT_IMMERSIVE_FLAGS);
- addImmersiveFlagsToDecorView(window, DEFAULT_IMMERSIVE_FLAGS);
-
- // Also set the navigation bar and status bar to transparent color. Note that this
- // doesn't work if android.R.boolean.config_enableTranslucentDecor is false.
- window.setNavigationBarColor(0);
- window.setStatusBarColor(0);
- }
+ }
+
+ /**
+ * Hide the navigation bar, make the color of the status and navigation bars transparent, and
+ * specify {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} flag so that the content is laid-out
+ * behind the transparent status bar. This is commonly used with {@link
+ * android.app.Activity#getWindow()} to make the navigation and status bars follow the Setup
+ * Wizard style.
+ *
+ * <p>This will only take effect in versions Lollipop or above. Otherwise this is a no-op.
+ */
+ public static void hideSystemBars(final Window window) {
+ if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ addVisibilityFlag(window, DEFAULT_IMMERSIVE_FLAGS);
+ addImmersiveFlagsToDecorView(window, DEFAULT_IMMERSIVE_FLAGS);
+
+ // Also set the navigation bar and status bar to transparent color. Note that this
+ // doesn't work if android.R.boolean.config_enableTranslucentDecor is false.
+ window.setNavigationBarColor(0);
+ window.setStatusBarColor(0);
}
-
- /**
- * Revert the actions of hideSystemBars. Note that this will remove the system UI visibility
- * flags regardless of whether it is originally present. You should also manually reset the
- * navigation bar and status bar colors, as this method doesn't know what value to revert it to.
- */
- public static void showSystemBars(final Dialog dialog, final Context context) {
- showSystemBars(dialog.getWindow(), context);
+ }
+
+ /**
+ * Revert the actions of hideSystemBars. Note that this will remove the system UI visibility flags
+ * regardless of whether it is originally present. You should also manually reset the navigation
+ * bar and status bar colors, as this method doesn't know what value to revert it to.
+ */
+ public static void showSystemBars(final Dialog dialog, final Context context) {
+ showSystemBars(dialog.getWindow(), context);
+ }
+
+ /**
+ * Revert the actions of hideSystemBars. Note that this will remove the system UI visibility flags
+ * regardless of whether it is originally present. You should also manually reset the navigation
+ * bar and status bar colors, as this method doesn't know what value to revert it to.
+ */
+ public static void showSystemBars(final Window window, final Context context) {
+ if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ removeVisibilityFlag(window, DEFAULT_IMMERSIVE_FLAGS);
+ removeImmersiveFlagsFromDecorView(window, DEFAULT_IMMERSIVE_FLAGS);
+
+ if (context != null) {
+ //noinspection AndroidLintInlinedApi
+ final TypedArray typedArray =
+ context.obtainStyledAttributes(
+ new int[] {android.R.attr.statusBarColor, android.R.attr.navigationBarColor});
+ final int statusBarColor = typedArray.getColor(0, 0);
+ final int navigationBarColor = typedArray.getColor(1, 0);
+ window.setStatusBarColor(statusBarColor);
+ window.setNavigationBarColor(navigationBarColor);
+ typedArray.recycle();
+ }
}
+ }
- /**
- * Revert the actions of hideSystemBars. Note that this will remove the system UI visibility
- * flags regardless of whether it is originally present. You should also manually reset the
- * navigation bar and status bar colors, as this method doesn't know what value to revert it to.
- */
- public static void showSystemBars(final Window window, final Context context) {
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- removeVisibilityFlag(window, DEFAULT_IMMERSIVE_FLAGS);
- removeImmersiveFlagsFromDecorView(window, DEFAULT_IMMERSIVE_FLAGS);
-
- if (context != null) {
- //noinspection AndroidLintInlinedApi
- final TypedArray typedArray = context.obtainStyledAttributes(new int[]{
- android.R.attr.statusBarColor, android.R.attr.navigationBarColor});
- final int statusBarColor = typedArray.getColor(0, 0);
- final int navigationBarColor = typedArray.getColor(1, 0);
- window.setStatusBarColor(statusBarColor);
- window.setNavigationBarColor(navigationBarColor);
- typedArray.recycle();
- }
- }
+ /** Convenience method to add a visibility flag in addition to the existing ones. */
+ public static void addVisibilityFlag(final View view, final int flag) {
+ if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
+ final int vis = view.getSystemUiVisibility();
+ view.setSystemUiVisibility(vis | flag);
}
-
- /**
- * Convenience method to add a visibility flag in addition to the existing ones.
- */
- public static void addVisibilityFlag(final View view, final int flag) {
- if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
- final int vis = view.getSystemUiVisibility();
- view.setSystemUiVisibility(vis | flag);
- }
+ }
+
+ /** Convenience method to add a visibility flag in addition to the existing ones. */
+ public static void addVisibilityFlag(final Window window, final int flag) {
+ if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
+ WindowManager.LayoutParams attrs = window.getAttributes();
+ attrs.systemUiVisibility |= flag;
+ window.setAttributes(attrs);
}
-
- /**
- * Convenience method to add a visibility flag in addition to the existing ones.
- */
- public static void addVisibilityFlag(final Window window, final int flag) {
- if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
- WindowManager.LayoutParams attrs = window.getAttributes();
- attrs.systemUiVisibility |= flag;
- window.setAttributes(attrs);
- }
+ }
+
+ /**
+ * Convenience method to remove a visibility flag from the view, leaving other flags that are not
+ * specified intact.
+ */
+ public static void removeVisibilityFlag(final View view, final int flag) {
+ if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
+ final int vis = view.getSystemUiVisibility();
+ view.setSystemUiVisibility(vis & ~flag);
}
-
- /**
- * Convenience method to remove a visibility flag from the view, leaving other flags that are
- * not specified intact.
- */
- public static void removeVisibilityFlag(final View view, final int flag) {
- if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
- final int vis = view.getSystemUiVisibility();
- view.setSystemUiVisibility(vis & ~flag);
- }
+ }
+
+ /**
+ * Convenience method to remove a visibility flag from the window, leaving other flags that are
+ * not specified intact.
+ */
+ public static void removeVisibilityFlag(final Window window, final int flag) {
+ if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
+ WindowManager.LayoutParams attrs = window.getAttributes();
+ attrs.systemUiVisibility &= ~flag;
+ window.setAttributes(attrs);
}
-
- /**
- * Convenience method to remove a visibility flag from the window, leaving other flags that are
- * not specified intact.
- */
- public static void removeVisibilityFlag(final Window window, final int flag) {
- if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
- WindowManager.LayoutParams attrs = window.getAttributes();
- attrs.systemUiVisibility &= ~flag;
- window.setAttributes(attrs);
- }
+ }
+
+ /**
+ * Sets whether the back button on the software navigation bar is visible. This only works if you
+ * have the STATUS_BAR permission. Otherwise framework will filter out this flag and this method
+ * call will not have any effect.
+ *
+ * <p>IMPORTANT: Do not assume that users have no way to go back when the back button is hidden.
+ * Many devices have physical back buttons, and accessibility services like TalkBack may have
+ * gestures mapped to back. Please use onBackPressed, onKeyDown, or other similar ways to make
+ * sure back button events are still handled (or ignored) properly.
+ */
+ @RequiresPermission("android.permission.STATUS_BAR")
+ public static void setBackButtonVisible(final Window window, final boolean visible) {
+ if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
+ if (visible) {
+ removeVisibilityFlag(window, STATUS_BAR_DISABLE_BACK);
+ removeImmersiveFlagsFromDecorView(window, STATUS_BAR_DISABLE_BACK);
+ } else {
+ addVisibilityFlag(window, STATUS_BAR_DISABLE_BACK);
+ addImmersiveFlagsToDecorView(window, STATUS_BAR_DISABLE_BACK);
+ }
}
-
- /**
- * Sets whether the back button on the software navigation bar is visible. This only works if
- * you have the STATUS_BAR permission. Otherwise framework will filter out this flag and this
- * method call will not have any effect.
- *
- * <p>IMPORTANT: Do not assume that users have no way to go back when the back button is hidden.
- * Many devices have physical back buttons, and accessibility services like TalkBack may have
- * gestures mapped to back. Please use onBackPressed, onKeyDown, or other similar ways to
- * make sure back button events are still handled (or ignored) properly.
- */
- @RequiresPermission("android.permission.STATUS_BAR")
- public static void setBackButtonVisible(final Window window, final boolean visible) {
- if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) {
- if (visible) {
- removeVisibilityFlag(window, STATUS_BAR_DISABLE_BACK);
- removeImmersiveFlagsFromDecorView(window, STATUS_BAR_DISABLE_BACK);
- } else {
- addVisibilityFlag(window, STATUS_BAR_DISABLE_BACK);
- addImmersiveFlagsToDecorView(window, STATUS_BAR_DISABLE_BACK);
- }
- }
+ }
+
+ /**
+ * Set a view to be resized when the keyboard is shown. This will set the bottom margin of the
+ * view to be immediately above the keyboard, and assumes that the view sits immediately above the
+ * navigation bar.
+ *
+ * <p>Note that you must set {@link android.R.attr#windowSoftInputMode} to {@code adjustResize}
+ * for this class to work. Otherwise window insets are not dispatched and this method will have no
+ * effect.
+ *
+ * <p>This will only take effect in versions Lollipop or above. Otherwise this is a no-op.
+ *
+ * @param view The view to be resized when the keyboard is shown.
+ */
+ public static void setImeInsetView(final View view) {
+ if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ view.setOnApplyWindowInsetsListener(new WindowInsetsListener());
}
-
- /**
- * Set a view to be resized when the keyboard is shown. This will set the bottom margin of the
- * view to be immediately above the keyboard, and assumes that the view sits immediately above
- * the navigation bar.
- *
- * <p>Note that you must set {@link android.R.attr#windowSoftInputMode} to {@code adjustResize}
- * for this class to work. Otherwise window insets are not dispatched and this method will have
- * no effect.
- *
- * <p>This will only take effect in versions Lollipop or above. Otherwise this is a no-op.
- *
- * @param view The view to be resized when the keyboard is shown.
- */
- public static void setImeInsetView(final View view) {
- if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
- view.setOnApplyWindowInsetsListener(new WindowInsetsListener());
- }
- }
-
- /**
- * Add the specified immersive flags to the decor view of the window, because
- * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} only takes effect when it is added to a view
- * instead of the window.
- */
- @TargetApi(VERSION_CODES.HONEYCOMB)
- private static void addImmersiveFlagsToDecorView(final Window window, final int vis) {
- getDecorView(window, new OnDecorViewInstalledListener() {
- @Override
- public void onDecorViewInstalled(View decorView) {
- addVisibilityFlag(decorView, vis);
- }
+ }
+
+ /**
+ * Add the specified immersive flags to the decor view of the window, because {@link
+ * View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} only takes effect when it is added to a view instead of
+ * the window.
+ */
+ @TargetApi(VERSION_CODES.HONEYCOMB)
+ private static void addImmersiveFlagsToDecorView(final Window window, final int vis) {
+ getDecorView(
+ window,
+ new OnDecorViewInstalledListener() {
+ @Override
+ public void onDecorViewInstalled(View decorView) {
+ addVisibilityFlag(decorView, vis);
+ }
});
- }
-
- @TargetApi(VERSION_CODES.HONEYCOMB)
- private static void removeImmersiveFlagsFromDecorView(final Window window, final int vis) {
- getDecorView(window, new OnDecorViewInstalledListener() {
- @Override
- public void onDecorViewInstalled(View decorView) {
- removeVisibilityFlag(decorView, vis);
- }
+ }
+
+ @TargetApi(VERSION_CODES.HONEYCOMB)
+ private static void removeImmersiveFlagsFromDecorView(final Window window, final int vis) {
+ getDecorView(
+ window,
+ new OnDecorViewInstalledListener() {
+ @Override
+ public void onDecorViewInstalled(View decorView) {
+ removeVisibilityFlag(decorView, vis);
+ }
});
- }
-
- private static void getDecorView(Window window, OnDecorViewInstalledListener callback) {
- new DecorViewFinder().getDecorView(window, callback, PEEK_DECOR_VIEW_RETRIES);
- }
-
- private static class DecorViewFinder {
-
- private final Handler mHandler = new Handler();
- private Window mWindow;
- private int mRetries;
- private OnDecorViewInstalledListener mCallback;
-
- private Runnable mCheckDecorViewRunnable = new Runnable() {
- @Override
- public void run() {
- // Use peekDecorView instead of getDecorView so that clients can still set window
- // features after calling this method.
- final View decorView = mWindow.peekDecorView();
- if (decorView != null) {
- mCallback.onDecorViewInstalled(decorView);
- } else {
- mRetries--;
- if (mRetries >= 0) {
- // If the decor view is not installed yet, try again in the next loop.
- mHandler.post(mCheckDecorViewRunnable);
- } else {
- Log.w(TAG, "Cannot get decor view of window: " + mWindow);
- }
- }
+ }
+
+ private static void getDecorView(Window window, OnDecorViewInstalledListener callback) {
+ new DecorViewFinder().getDecorView(window, callback, PEEK_DECOR_VIEW_RETRIES);
+ }
+
+ private static class DecorViewFinder {
+
+ private final Handler handler = new Handler();
+ private Window window;
+ private int retries;
+ private OnDecorViewInstalledListener callback;
+
+ private final Runnable checkDecorViewRunnable =
+ new Runnable() {
+ @Override
+ public void run() {
+ // Use peekDecorView instead of getDecorView so that clients can still set window
+ // features after calling this method.
+ final View decorView = window.peekDecorView();
+ if (decorView != null) {
+ callback.onDecorViewInstalled(decorView);
+ } else {
+ retries--;
+ if (retries >= 0) {
+ // If the decor view is not installed yet, try again in the next loop.
+ handler.post(checkDecorViewRunnable);
+ } else {
+ Log.w(TAG, "Cannot get decor view of window: " + window);
+ }
}
+ }
};
- public void getDecorView(Window window, OnDecorViewInstalledListener callback,
- int retries) {
- mWindow = window;
- mRetries = retries;
- mCallback = callback;
- mCheckDecorViewRunnable.run();
- }
+ public void getDecorView(Window window, OnDecorViewInstalledListener callback, int retries) {
+ this.window = window;
+ this.retries = retries;
+ this.callback = callback;
+ checkDecorViewRunnable.run();
}
-
- private interface OnDecorViewInstalledListener {
-
- void onDecorViewInstalled(View decorView);
- }
-
- /**
- * Apply a hack to temporarily set the window to not focusable, so that the navigation bar
- * will not show up during the transition.
- */
- private static void temporarilyDisableDialogFocus(final Window window) {
- window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
- // Add the SOFT_INPUT_IS_FORWARD_NAVIGATION_FLAG. This is normally done by the system when
- // FLAG_NOT_FOCUSABLE is not set. Setting this flag allows IME to be shown automatically
- // if the dialog has editable text fields.
- window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION);
- new Handler().post(new Runnable() {
- @Override
- public void run() {
+ }
+
+ private interface OnDecorViewInstalledListener {
+
+ void onDecorViewInstalled(View decorView);
+ }
+
+ /**
+ * Apply a hack to temporarily set the window to not focusable, so that the navigation bar will
+ * not show up during the transition.
+ */
+ private static void temporarilyDisableDialogFocus(final Window window) {
+ window.setFlags(
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+ // Add the SOFT_INPUT_IS_FORWARD_NAVIGATION_FLAG. This is normally done by the system when
+ // FLAG_NOT_FOCUSABLE is not set. Setting this flag allows IME to be shown automatically
+ // if the dialog has editable text fields.
+ window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION);
+ new Handler()
+ .post(
+ new Runnable() {
+ @Override
+ public void run() {
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
- }
- });
+ }
+ });
+ }
+
+ @TargetApi(VERSION_CODES.LOLLIPOP)
+ private static class WindowInsetsListener implements View.OnApplyWindowInsetsListener {
+ private int bottomOffset;
+ private boolean hasCalculatedBottomOffset = false;
+
+ @Override
+ public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
+ if (!hasCalculatedBottomOffset) {
+ bottomOffset = getBottomDistance(view);
+ hasCalculatedBottomOffset = true;
+ }
+
+ int bottomInset = insets.getSystemWindowInsetBottom();
+
+ final int bottomMargin = Math.max(insets.getSystemWindowInsetBottom() - bottomOffset, 0);
+
+ final ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
+ // Check that we have enough space to apply the bottom margins before applying it.
+ // Otherwise the framework may think that the view is empty and exclude it from layout.
+ if (bottomMargin < lp.bottomMargin + view.getHeight()) {
+ lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, bottomMargin);
+ view.setLayoutParams(lp);
+ bottomInset = 0;
+ }
+
+ return insets.replaceSystemWindowInsets(
+ insets.getSystemWindowInsetLeft(),
+ insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(),
+ bottomInset);
}
+ }
- @TargetApi(VERSION_CODES.LOLLIPOP)
- private static class WindowInsetsListener implements View.OnApplyWindowInsetsListener {
- private int mBottomOffset;
- private boolean mHasCalculatedBottomOffset = false;
-
- @Override
- public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
- if (!mHasCalculatedBottomOffset) {
- mBottomOffset = getBottomDistance(view);
- mHasCalculatedBottomOffset = true;
- }
-
- int bottomInset = insets.getSystemWindowInsetBottom();
-
- final int bottomMargin = Math.max(
- insets.getSystemWindowInsetBottom() - mBottomOffset, 0);
-
- final ViewGroup.MarginLayoutParams lp =
- (ViewGroup.MarginLayoutParams) view.getLayoutParams();
- // Check that we have enough space to apply the bottom margins before applying it.
- // Otherwise the framework may think that the view is empty and exclude it from layout.
- if (bottomMargin < lp.bottomMargin + view.getHeight()) {
- lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, bottomMargin);
- view.setLayoutParams(lp);
- bottomInset = 0;
- }
-
-
- return insets.replaceSystemWindowInsets(
- insets.getSystemWindowInsetLeft(),
- insets.getSystemWindowInsetTop(),
- insets.getSystemWindowInsetRight(),
- bottomInset
- );
- }
- }
-
- private static int getBottomDistance(View view) {
- int[] coords = new int[2];
- view.getLocationInWindow(coords);
- return view.getRootView().getHeight() - coords[1] - view.getHeight();
- }
+ private static int getBottomDistance(View view) {
+ int[] coords = new int[2];
+ view.getLocationInWindow(coords);
+ return view.getRootView().getHeight() - coords[1] - view.getHeight();
+ }
}