Merge "New window cling for immersive mode." into klp-dev
BIN
core/res/res/drawable-hdpi/cling_arrow_up.png
Normal file
After Width: | Height: | Size: 469 B |
BIN
core/res/res/drawable-hdpi/cling_bg.9.png
Normal file
After Width: | Height: | Size: 284 B |
BIN
core/res/res/drawable-hdpi/cling_button_normal.9.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
core/res/res/drawable-hdpi/cling_button_pressed.9.png
Normal file
After Width: | Height: | Size: 453 B |
BIN
core/res/res/drawable-mdpi/cling_arrow_up.png
Normal file
After Width: | Height: | Size: 428 B |
BIN
core/res/res/drawable-mdpi/cling_bg.9.png
Normal file
After Width: | Height: | Size: 236 B |
BIN
core/res/res/drawable-mdpi/cling_button_normal.9.png
Normal file
After Width: | Height: | Size: 356 B |
BIN
core/res/res/drawable-mdpi/cling_button_pressed.9.png
Normal file
After Width: | Height: | Size: 352 B |
BIN
core/res/res/drawable-xhdpi/cling_arrow_up.png
Normal file
After Width: | Height: | Size: 545 B |
BIN
core/res/res/drawable-xhdpi/cling_bg.9.png
Normal file
After Width: | Height: | Size: 327 B |
BIN
core/res/res/drawable-xhdpi/cling_button_normal.9.png
Normal file
After Width: | Height: | Size: 558 B |
BIN
core/res/res/drawable-xhdpi/cling_button_pressed.9.png
Normal file
After Width: | Height: | Size: 558 B |
BIN
core/res/res/drawable-xxhdpi/cling_arrow_up.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
core/res/res/drawable-xxhdpi/cling_bg.9.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
core/res/res/drawable-xxhdpi/cling_button_normal.9.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
core/res/res/drawable-xxhdpi/cling_button_pressed.9.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
21
core/res/res/drawable/cling_button.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2013 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.
|
||||||
|
-->
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_pressed="true"
|
||||||
|
android:drawable="@drawable/cling_button_pressed" />
|
||||||
|
<item
|
||||||
|
android:drawable="@drawable/cling_button_normal" />
|
||||||
|
</selector>
|
67
core/res/res/layout/transient_navigation_cling.xml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2013 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.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="12dp"
|
||||||
|
>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:padding="1dp"
|
||||||
|
>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:src="@drawable/cling_arrow_up"
|
||||||
|
/>
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/cling_bg"
|
||||||
|
android:paddingLeft="14dp"
|
||||||
|
android:paddingRight="14dp"
|
||||||
|
android:paddingTop="24dp"
|
||||||
|
android:paddingBottom="24dp">
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/transient_navigation_confirmation"
|
||||||
|
android:textColor="#80000000"
|
||||||
|
android:textSize="16sp"
|
||||||
|
/>
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/ok"
|
||||||
|
android:layout_width="160sp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:layout_marginTop="18dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/ok"
|
||||||
|
android:background="@drawable/cling_button"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
@ -4486,7 +4486,7 @@
|
|||||||
<!-- PIN entry dialog tells the user to not enter a PIN for a while. [CHAR LIMIT=none] -->
|
<!-- PIN entry dialog tells the user to not enter a PIN for a while. [CHAR LIMIT=none] -->
|
||||||
<string name="restr_pin_try_later">Try again later</string>
|
<string name="restr_pin_try_later">Try again later</string>
|
||||||
|
|
||||||
<!-- Toast bar message when hiding the transient navigation bar [CHAR LIMIT=45] -->
|
<!-- Cling help message when hiding the transient navigation bar [CHAR LIMIT=none] -->
|
||||||
<string name="transient_navigation_confirmation">Swipe down from the top to exit full screen</string>
|
<string name="transient_navigation_confirmation">Swipe down from the top to exit full screen.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1094,6 +1094,9 @@
|
|||||||
<java-symbol type="drawable" name="notification_template_icon_low_bg" />
|
<java-symbol type="drawable" name="notification_template_icon_low_bg" />
|
||||||
<java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
|
<java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
|
||||||
<java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
|
<java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
|
||||||
|
<java-symbol type="drawable" name="cling_button" />
|
||||||
|
<java-symbol type="drawable" name="cling_arrow_up" />
|
||||||
|
<java-symbol type="drawable" name="cling_bg" />
|
||||||
|
|
||||||
<java-symbol type="layout" name="action_bar_home" />
|
<java-symbol type="layout" name="action_bar_home" />
|
||||||
<java-symbol type="layout" name="action_bar_title_item" />
|
<java-symbol type="layout" name="action_bar_title_item" />
|
||||||
@ -1197,6 +1200,7 @@
|
|||||||
<java-symbol type="layout" name="app_not_authorized" />
|
<java-symbol type="layout" name="app_not_authorized" />
|
||||||
<java-symbol type="layout" name="restrictions_pin_challenge" />
|
<java-symbol type="layout" name="restrictions_pin_challenge" />
|
||||||
<java-symbol type="layout" name="restrictions_pin_setup" />
|
<java-symbol type="layout" name="restrictions_pin_setup" />
|
||||||
|
<java-symbol type="layout" name="transient_navigation_cling" />
|
||||||
|
|
||||||
<java-symbol type="anim" name="slide_in_child_bottom" />
|
<java-symbol type="anim" name="slide_in_child_bottom" />
|
||||||
<java-symbol type="anim" name="slide_in_right" />
|
<java-symbol type="anim" name="slide_in_right" />
|
||||||
|
@ -16,18 +16,31 @@
|
|||||||
|
|
||||||
package com.android.internal.policy.impl;
|
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.content.Context;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.view.animation.Animation;
|
import android.view.animation.Animation;
|
||||||
import android.view.animation.AnimationUtils;
|
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;
|
import com.android.internal.R;
|
||||||
|
|
||||||
@ -40,6 +53,7 @@ import java.util.Arrays;
|
|||||||
public class TransientNavigationConfirmation {
|
public class TransientNavigationConfirmation {
|
||||||
private static final String TAG = "TransientNavigationConfirmation";
|
private static final String TAG = "TransientNavigationConfirmation";
|
||||||
private static final boolean DEBUG = false;
|
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 Context mContext;
|
||||||
private final H mHandler;
|
private final H mHandler;
|
||||||
@ -47,11 +61,12 @@ public class TransientNavigationConfirmation {
|
|||||||
private final long mShowDelayMs;
|
private final long mShowDelayMs;
|
||||||
private final long mPanicThresholdMs;
|
private final long mPanicThresholdMs;
|
||||||
|
|
||||||
private Toast mToast;
|
private ClingWindowView mClingWindow;
|
||||||
private String mLastPackage;
|
private String mLastPackage;
|
||||||
private String mPromptPackage;
|
private String mPromptPackage;
|
||||||
private long mPanicTime;
|
private long mPanicTime;
|
||||||
private String mPanicPackage;
|
private String mPanicPackage;
|
||||||
|
private WindowManager mWindowManager;
|
||||||
|
|
||||||
public TransientNavigationConfirmation(Context context) {
|
public TransientNavigationConfirmation(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
@ -59,6 +74,8 @@ public class TransientNavigationConfirmation {
|
|||||||
mShowDelayMs = getNavBarExitDuration() * 3;
|
mShowDelayMs = getNavBarExitDuration() * 3;
|
||||||
mPanicThresholdMs = context.getResources()
|
mPanicThresholdMs = context.getResources()
|
||||||
.getInteger(R.integer.config_transient_navigation_confirmation_panic);
|
.getInteger(R.integer.config_transient_navigation_confirmation_panic);
|
||||||
|
mWindowManager = (WindowManager)
|
||||||
|
mContext.getSystemService(Context.WINDOW_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getNavBarExitDuration() {
|
private long getNavBarExitDuration() {
|
||||||
@ -104,7 +121,7 @@ public class TransientNavigationConfirmation {
|
|||||||
mHandler.removeMessages(H.SHOW);
|
mHandler.removeMessages(H.SHOW);
|
||||||
if (isNavTransient) {
|
if (isNavTransient) {
|
||||||
mLastPackage = pkg;
|
mLastPackage = pkg;
|
||||||
if (!mConfirmedPackages.contains(pkg)) {
|
if (DEBUG_SHOW_EVERY_TIME || !mConfirmedPackages.contains(pkg)) {
|
||||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs);
|
mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -141,11 +158,90 @@ public class TransientNavigationConfirmation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleHide() {
|
private void handleHide() {
|
||||||
if (mToast != null) {
|
if (mClingWindow != null) {
|
||||||
if (DEBUG) Slog.d(TAG,
|
if (DEBUG) Slog.d(TAG,
|
||||||
"Hiding transient navigation confirmation for " + mPromptPackage);
|
"Hiding transient navigation confirmation for " + mPromptPackage);
|
||||||
mToast.cancel();
|
mWindowManager.removeView(mClingWindow);
|
||||||
mToast = null;
|
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;
|
mPromptPackage = pkg;
|
||||||
if (DEBUG) Slog.d(TAG, "Showing transient navigation confirmation for " + pkg);
|
if (DEBUG) Slog.d(TAG, "Showing transient navigation confirmation for " + pkg);
|
||||||
|
|
||||||
// create the confirmation toast bar
|
mClingWindow = new ClingWindowView(mContext);
|
||||||
final int msg = R.string.transient_navigation_confirmation;
|
|
||||||
mToast = Toast.makeBar(mContext, msg, Toast.LENGTH_INFINITE);
|
|
||||||
mToast.setAction(R.string.ok, confirmAction(pkg));
|
|
||||||
|
|
||||||
// we will be hiding the nav bar, so layout as if it's already hidden
|
// 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
|
// 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) {
|
private Runnable confirmAction(final String pkg) {
|
||||||
|