diff --git a/core/res/res/drawable-hdpi/cling_arrow_up.png b/core/res/res/drawable-hdpi/cling_arrow_up.png
new file mode 100644
index 0000000000000..8ef20506c0563
Binary files /dev/null and b/core/res/res/drawable-hdpi/cling_arrow_up.png differ
diff --git a/core/res/res/drawable-hdpi/cling_bg.9.png b/core/res/res/drawable-hdpi/cling_bg.9.png
new file mode 100644
index 0000000000000..36fbfc8b6d22f
Binary files /dev/null and b/core/res/res/drawable-hdpi/cling_bg.9.png differ
diff --git a/core/res/res/drawable-hdpi/cling_button_normal.9.png b/core/res/res/drawable-hdpi/cling_button_normal.9.png
new file mode 100644
index 0000000000000..e30838241de0e
Binary files /dev/null and b/core/res/res/drawable-hdpi/cling_button_normal.9.png differ
diff --git a/core/res/res/drawable-hdpi/cling_button_pressed.9.png b/core/res/res/drawable-hdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000000000..4f9ca6f7a6123
Binary files /dev/null and b/core/res/res/drawable-hdpi/cling_button_pressed.9.png differ
diff --git a/core/res/res/drawable-mdpi/cling_arrow_up.png b/core/res/res/drawable-mdpi/cling_arrow_up.png
new file mode 100644
index 0000000000000..ee6c378d18090
Binary files /dev/null and b/core/res/res/drawable-mdpi/cling_arrow_up.png differ
diff --git a/core/res/res/drawable-mdpi/cling_bg.9.png b/core/res/res/drawable-mdpi/cling_bg.9.png
new file mode 100644
index 0000000000000..4c0f139eeb5a8
Binary files /dev/null and b/core/res/res/drawable-mdpi/cling_bg.9.png differ
diff --git a/core/res/res/drawable-mdpi/cling_button_normal.9.png b/core/res/res/drawable-mdpi/cling_button_normal.9.png
new file mode 100644
index 0000000000000..a0b6f97352519
Binary files /dev/null and b/core/res/res/drawable-mdpi/cling_button_normal.9.png differ
diff --git a/core/res/res/drawable-mdpi/cling_button_pressed.9.png b/core/res/res/drawable-mdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000000000..986e669443f1e
Binary files /dev/null and b/core/res/res/drawable-mdpi/cling_button_pressed.9.png differ
diff --git a/core/res/res/drawable-xhdpi/cling_arrow_up.png b/core/res/res/drawable-xhdpi/cling_arrow_up.png
new file mode 100644
index 0000000000000..280315596e59a
Binary files /dev/null and b/core/res/res/drawable-xhdpi/cling_arrow_up.png differ
diff --git a/core/res/res/drawable-xhdpi/cling_bg.9.png b/core/res/res/drawable-xhdpi/cling_bg.9.png
new file mode 100644
index 0000000000000..1cb468159f14f
Binary files /dev/null and b/core/res/res/drawable-xhdpi/cling_bg.9.png differ
diff --git a/core/res/res/drawable-xhdpi/cling_button_normal.9.png b/core/res/res/drawable-xhdpi/cling_button_normal.9.png
new file mode 100644
index 0000000000000..4192563b509f8
Binary files /dev/null and b/core/res/res/drawable-xhdpi/cling_button_normal.9.png differ
diff --git a/core/res/res/drawable-xhdpi/cling_button_pressed.9.png b/core/res/res/drawable-xhdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000000000..d3ce46977d68d
Binary files /dev/null and b/core/res/res/drawable-xhdpi/cling_button_pressed.9.png differ
diff --git a/core/res/res/drawable-xxhdpi/cling_arrow_up.png b/core/res/res/drawable-xxhdpi/cling_arrow_up.png
new file mode 100644
index 0000000000000..1983f133c659b
Binary files /dev/null and b/core/res/res/drawable-xxhdpi/cling_arrow_up.png differ
diff --git a/core/res/res/drawable-xxhdpi/cling_bg.9.png b/core/res/res/drawable-xxhdpi/cling_bg.9.png
new file mode 100644
index 0000000000000..7beae03bf43c8
Binary files /dev/null and b/core/res/res/drawable-xxhdpi/cling_bg.9.png differ
diff --git a/core/res/res/drawable-xxhdpi/cling_button_normal.9.png b/core/res/res/drawable-xxhdpi/cling_button_normal.9.png
new file mode 100644
index 0000000000000..e41287613ea8e
Binary files /dev/null and b/core/res/res/drawable-xxhdpi/cling_button_normal.9.png differ
diff --git a/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png b/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000000000..55e89da08ca08
Binary files /dev/null and b/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png differ
diff --git a/core/res/res/drawable/cling_button.xml b/core/res/res/drawable/cling_button.xml
new file mode 100644
index 0000000000000..9ce191c181f2d
--- /dev/null
+++ b/core/res/res/drawable/cling_button.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
diff --git a/core/res/res/layout/transient_navigation_cling.xml b/core/res/res/layout/transient_navigation_cling.xml
new file mode 100644
index 0000000000000..d33d96569d867
--- /dev/null
+++ b/core/res/res/layout/transient_navigation_cling.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d57c232b3bb39..92a6e52b46230 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4486,7 +4486,7 @@
Try again later
-
- Swipe down from the top to exit full screen
+
+ Swipe down from the top to exit full screen.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cc1cfd33853ca..675fe21b9d8ad 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1094,6 +1094,9 @@
+
+
+
@@ -1197,6 +1200,7 @@
+
diff --git a/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java b/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
index 8613088fc09ee..a6381a7581dad 100644
--- a/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
+++ b/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
@@ -16,18 +16,31 @@
package com.android.internal.policy.impl;
+import android.animation.Animator;
+import android.animation.ArgbEvaluator;
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.DisplayMetrics;
import android.util.Slog;
+import android.view.Gravity;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.widget.Toast;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.Button;
+import android.widget.FrameLayout;
import com.android.internal.R;
@@ -40,6 +53,7 @@ import java.util.Arrays;
public class TransientNavigationConfirmation {
private static final String TAG = "TransientNavigationConfirmation";
private static final boolean DEBUG = false;
+ private static final boolean DEBUG_SHOW_EVERY_TIME = false; // super annoying, use with caution
private final Context mContext;
private final H mHandler;
@@ -47,11 +61,12 @@ public class TransientNavigationConfirmation {
private final long mShowDelayMs;
private final long mPanicThresholdMs;
- private Toast mToast;
+ private ClingWindowView mClingWindow;
private String mLastPackage;
private String mPromptPackage;
private long mPanicTime;
private String mPanicPackage;
+ private WindowManager mWindowManager;
public TransientNavigationConfirmation(Context context) {
mContext = context;
@@ -59,6 +74,8 @@ public class TransientNavigationConfirmation {
mShowDelayMs = getNavBarExitDuration() * 3;
mPanicThresholdMs = context.getResources()
.getInteger(R.integer.config_transient_navigation_confirmation_panic);
+ mWindowManager = (WindowManager)
+ mContext.getSystemService(Context.WINDOW_SERVICE);
}
private long getNavBarExitDuration() {
@@ -104,7 +121,7 @@ public class TransientNavigationConfirmation {
mHandler.removeMessages(H.SHOW);
if (isNavTransient) {
mLastPackage = pkg;
- if (!mConfirmedPackages.contains(pkg)) {
+ if (DEBUG_SHOW_EVERY_TIME || !mConfirmedPackages.contains(pkg)) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs);
}
} else {
@@ -141,11 +158,90 @@ public class TransientNavigationConfirmation {
}
private void handleHide() {
- if (mToast != null) {
+ if (mClingWindow != null) {
if (DEBUG) Slog.d(TAG,
"Hiding transient navigation confirmation for " + mPromptPackage);
- mToast.cancel();
- mToast = null;
+ mWindowManager.removeView(mClingWindow);
+ mClingWindow = null;
+ }
+ }
+
+ private class ClingWindowView extends FrameLayout {
+ private static final int BGCOLOR = 0x80000000;
+ private static final int OFFSET_DP = 48;
+
+ private final ColorDrawable mColor = new ColorDrawable(0);
+ private ValueAnimator mColorAnim;
+
+ public ClingWindowView(Context context) {
+ super(context);
+ setClickable(true);
+ setBackground(mColor);
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ mWindowManager.getDefaultDisplay().getMetrics(metrics);
+ float density = metrics.density;
+
+ // create the confirmation cling
+ final ViewGroup clingLayout = (ViewGroup)
+ View.inflate(getContext(), R.layout.transient_navigation_cling, null);
+
+ final Button ok = (Button) clingLayout.findViewById(R.id.ok);
+ ok.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ handleHide();
+ }
+ });
+ addView(clingLayout, new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT
+ ));
+
+ if (ActivityManager.isHighEndGfx()) {
+ final View bubble = clingLayout.findViewById(R.id.text);
+ bubble.setAlpha(0f);
+ bubble.setTranslationY(-OFFSET_DP*density);
+ bubble.animate()
+ .alpha(1f)
+ .translationY(0)
+ .setDuration(300)
+ .setInterpolator(new DecelerateInterpolator())
+ .start();
+
+ ok.setAlpha(0f);
+ ok.setTranslationY(-OFFSET_DP*density);
+ ok.animate().alpha(1f)
+ .translationY(0)
+ .setDuration(300)
+ .setStartDelay(200)
+ .setInterpolator(new DecelerateInterpolator())
+ .start();
+
+ mColorAnim = ValueAnimator.ofObject(new ArgbEvaluator(), 0, BGCOLOR);
+ mColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final int c = (Integer) animation.getAnimatedValue();
+ mColor.setColor(c);
+ }
+ });
+ mColorAnim.setDuration(1000);
+ mColorAnim.start();
+ } else {
+ mColor.setColor(BGCOLOR);
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent motion) {
+ Slog.v(TAG, "ClingWindowView.onTouchEvent");
+ return true;
}
}
@@ -153,16 +249,28 @@ public class TransientNavigationConfirmation {
mPromptPackage = pkg;
if (DEBUG) Slog.d(TAG, "Showing transient navigation confirmation for " + pkg);
- // create the confirmation toast bar
- final int msg = R.string.transient_navigation_confirmation;
- mToast = Toast.makeBar(mContext, msg, Toast.LENGTH_INFINITE);
- mToast.setAction(R.string.ok, confirmAction(pkg));
+ mClingWindow = new ClingWindowView(mContext);
// we will be hiding the nav bar, so layout as if it's already hidden
- mToast.getView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+ mClingWindow.setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
// show the confirmation
- mToast.show();
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_TOAST,
+ 0
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+ ,
+ PixelFormat.TRANSLUCENT);
+ lp.setTitle("TransientNavigationConfirmation");
+ lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
+ lp.gravity = Gravity.FILL;
+ mWindowManager.addView(mClingWindow, lp);
}
private Runnable confirmAction(final String pkg) {