Merge "New window cling for immersive mode." into klp-dev

This commit is contained in:
Daniel Sandler
2013-10-13 19:30:28 +00:00
committed by Android (Google) Code Review
21 changed files with 214 additions and 14 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View 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>

View 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>

View File

@ -4486,7 +4486,7 @@
<!-- 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>
<!-- Toast bar message when hiding the transient navigation bar [CHAR LIMIT=45] -->
<string name="transient_navigation_confirmation">Swipe down from the top to exit full screen</string>
<!-- 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>
</resources>

View File

@ -1094,6 +1094,9 @@
<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_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_title_item" />
@ -1197,6 +1200,7 @@
<java-symbol type="layout" name="app_not_authorized" />
<java-symbol type="layout" name="restrictions_pin_challenge" />
<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_right" />

View File

@ -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) {