summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui/statusbar
diff options
context:
space:
mode:
authorJoe Onorato <joeo@google.com>2010-12-14 01:22:23 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-12-14 01:22:23 -0800
commit4738da2e30272ceeec7e065be3ce4b2838a22d07 (patch)
tree3f517f14411baa9ca3e3274d49d123c19f05424e /packages/SystemUI/src/com/android/systemui/statusbar
parentf2e69a911aa4d8ebaa3ffb6bc025a5ea5fea4bac (diff)
parent7c270fab75c2f4529e45ea80b31d4017ab516482 (diff)
downloadframeworks_base-4738da2e30272ceeec7e065be3ce4b2838a22d07.zip
frameworks_base-4738da2e30272ceeec7e065be3ce4b2838a22d07.tar.gz
frameworks_base-4738da2e30272ceeec7e065be3ce4b2838a22d07.tar.bz2
Merge "notification panel animations"
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/statusbar')
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java193
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java27
3 files changed, 293 insertions, 19 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
new file mode 100644
index 0000000..9ecb2e4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationLinearLayout.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.android.systemui.statusbar.tablet;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+public class NotificationLinearLayout extends LinearLayout {
+ private static final String TAG = "NotificationLinearLayout";
+
+ Drawable mItemGlow;
+ int mInsetLeft;
+ Rect mTmp = new Rect();
+
+ public NotificationLinearLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public NotificationLinearLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final Resources res = context.getResources();
+
+ mItemGlow = res.getDrawable(R.drawable.notify_item_glow_bottom);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NotificationLinearLayout,
+ defStyle, 0);
+ mInsetLeft = a.getDimensionPixelSize(R.styleable.NotificationLinearLayout_insetLeft, 0);
+ a.recycle();
+ }
+
+ @Override
+ public void onFinishInflate() {
+ super.onFinishInflate();
+ setWillNotDraw(false);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ final Rect padding = mTmp;
+ final Drawable glow = mItemGlow;
+ glow.getPadding(padding);
+ final int glowHeight = glow.getIntrinsicHeight();
+ final int insetLeft = mInsetLeft;
+
+ final int N = getChildCount();
+ for (int i=0; i<N; i++) {
+ final View child = getChildAt(i);
+
+ final int childBottom = child.getBottom();
+
+ glow.setBounds(child.getLeft() - padding.left + insetLeft, childBottom,
+ child.getRight() - padding.right, childBottom + glowHeight);
+ glow.draw(canvas);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index baf4a0f..82c1d17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -16,11 +16,20 @@
package com.android.systemui.statusbar.tablet;
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -32,12 +41,20 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
View.OnClickListener {
static final String TAG = "NotificationPanel";
+ boolean mShowing;
View mTitleArea;
View mSettingsButton;
View mNotificationButton;
View mNotificationScroller;
- FrameLayout mContentFrame;
+ ViewGroup mContentFrame;
+ Rect mContentArea;
View mSettingsView;
+ ViewGroup mContentParent;
+
+ Choreographer mChoreo = new Choreographer();
+ int mStatusBarHeight;
+ Drawable mBgDrawable;
+ Drawable mGlowDrawable;
public NotificationPanel(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -45,12 +62,22 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
public NotificationPanel(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+
+ final Resources res = context.getResources();
+
+ mStatusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ mBgDrawable = res.getDrawable(R.drawable.notify_panel_bg_protect);
+ mGlowDrawable = res.getDrawable(R.drawable.notify_glow_back);
}
@Override
public void onFinishInflate() {
super.onFinishInflate();
+ setWillNotDraw(false);
+
+ mContentParent = (ViewGroup)findViewById(R.id.content_parent);
mTitleArea = findViewById(R.id.title_area);
mSettingsButton = (ImageView)findViewById(R.id.settings_button);
@@ -59,7 +86,31 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
mNotificationButton.setOnClickListener(this);
mNotificationScroller = findViewById(R.id.notificationScroller);
- mContentFrame = (FrameLayout)findViewById(R.id.content_frame);
+ mContentFrame = (ViewGroup)findViewById(R.id.content_frame);
+ }
+
+ public void show(boolean show, boolean animate) {
+ if (animate) {
+ if (mShowing != show) {
+ mShowing = show;
+ if (show) {
+ setVisibility(View.VISIBLE);
+ }
+ mChoreo.startAnimation(show);
+ }
+ } else {
+ mShowing = show;
+ setVisibility(show ? View.VISIBLE : View.GONE);
+ mChoreo.jumpTo(show);
+ }
+ }
+
+ /**
+ * Whether the panel is showing, or, if it's animating, whether it will be
+ * when the animation is done.
+ */
+ public boolean isShowing() {
+ return mShowing;
}
@Override
@@ -93,6 +144,34 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
final View c = getChildAt(i);
c.layout(c.getLeft(), c.getTop() + shift, c.getRight(), c.getBottom() + shift);
}
+
+ mChoreo.setPanelHeight(mContentParent.getHeight());
+ }
+
+ @Override
+ public void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mContentArea = null;
+ mBgDrawable.setBounds(0, 0, w, h-mStatusBarHeight);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ int saveCount;
+ final int w = getWidth();
+ final int h = getHeight();
+
+ super.onDraw(canvas);
+
+ // Background protection
+ mBgDrawable.draw(canvas);
+
+ // The panel glow (behind status bar)
+
+ saveCount = canvas.save();
+ canvas.clipRect(0, 0, w, h-mStatusBarHeight);
+ mGlowDrawable.draw(canvas);
+ canvas.restoreToCount(saveCount);
}
public void onClick(View v) {
@@ -119,11 +198,14 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
}
public boolean isInContentArea(int x, int y) {
- final int l = mContentFrame.getLeft();
- final int r = mContentFrame.getRight();
- final int t = mTitleArea.getTop();
- final int b = mContentFrame.getBottom();
- return x >= l && x < r && y >= t && y < b;
+ if (mContentArea == null) {
+ mContentArea = new Rect(mContentFrame.getLeft(),
+ mTitleArea.getTop(),
+ mContentFrame.getRight(),
+ mContentFrame.getBottom());
+ offsetDescendantRectToMyCoords(mContentParent, mContentArea);
+ }
+ return mContentArea.contains(x, y);
}
void removeSettingsView() {
@@ -138,5 +220,102 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
mSettingsView = infl.inflate(R.layout.status_bar_settings_view, mContentFrame, false);
mContentFrame.addView(mSettingsView);
}
+
+ private class Choreographer implements Animator.AnimatorListener {
+ int mBgAlpha;
+ ValueAnimator mBgAnim;
+ int mPanelHeight;
+ int mPanelBottom;
+ ValueAnimator mPositionAnim;
+
+ // should group this into a multi-property animation
+ final int OPEN_DURATION = 200;
+
+ Choreographer() {
+ }
+
+ void createAnimation(boolean visible) {
+ mBgAnim = ObjectAnimator.ofInt(this, "bgAlpha", mBgAlpha, visible ? 255 : 0)
+ .setDuration(OPEN_DURATION);
+ mBgAnim.addListener(this);
+
+ mPositionAnim = ObjectAnimator.ofInt(this, "panelBottom", mPanelBottom,
+ visible ? mPanelHeight : 0)
+ .setDuration(OPEN_DURATION);
+ }
+
+ void startAnimation(boolean visible) {
+ if (mBgAnim == null) {
+ createAnimation(visible);
+ mBgAnim.start();
+ mPositionAnim.start();
+ } else {
+ mBgAnim.reverse();
+ mPositionAnim.reverse();
+ }
+ }
+
+ void jumpTo(boolean visible) {
+ setBgAlpha(visible ? 255 : 0);
+ setPanelBottom(visible ? mPanelHeight : 0);
+ }
+
+ public void setBgAlpha(int alpha) {
+ mBgAlpha = alpha;
+ mBgDrawable.setAlpha((int)(alpha));
+ invalidate();
+ }
+
+ // 0 is closed, the height of the panel is open
+ public void setPanelBottom(int y) {
+ mPanelBottom = y;
+ int translationY = mPanelHeight - y;
+ mContentParent.setTranslationY(translationY);
+
+ final int glowXOffset = 100;
+ final int glowYOffset = 100;
+ int glowX = mContentParent.getLeft() - glowXOffset;
+ int glowY = mContentParent.getTop() - glowYOffset + translationY;
+ mGlowDrawable.setBounds(glowX, glowY, glowX + mGlowDrawable.getIntrinsicWidth(),
+ glowY + mGlowDrawable.getIntrinsicHeight());
+
+ float alpha;
+ if (mPanelBottom > glowYOffset) {
+ alpha = 1;
+ } else {
+ alpha = ((float)mPanelBottom) / glowYOffset;
+ }
+ mContentParent.setAlpha(alpha);
+ mGlowDrawable.setAlpha((int)(255 * alpha));
+
+ if (false) {
+ Slog.d(TAG, "mPanelBottom=" + mPanelBottom + "translationY=" + translationY
+ + " alpha=" + alpha + " glowY=" + glowY);
+ }
+ }
+
+ public void setPanelHeight(int h) {
+ mPanelHeight = h;
+ setPanelBottom(mPanelBottom);
+ }
+
+ public void onAnimationCancel(Animator animation) {
+ //Slog.d(TAG, "onAnimationCancel mBgAlpha=" + mBgAlpha);
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ //Slog.d(TAG, "onAnimationEnd mBgAlpha=" + mBgAlpha);
+ if (mBgAlpha == 0) {
+ setVisibility(View.GONE);
+ }
+ mBgAnim = null;
+ }
+
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ public void onAnimationStart(Animator animation) {
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 8b80e50..7a7976a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -161,7 +161,7 @@ public class TabletStatusBar extends StatusBar {
// Notification Panel
mNotificationPanel = (NotificationPanel)View.inflate(context,
R.layout.status_bar_notification_panel, null);
- mNotificationPanel.setVisibility(View.GONE);
+ mNotificationPanel.show(false, false);
mNotificationPanel.setOnTouchListener(
new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
@@ -186,10 +186,14 @@ public class TabletStatusBar extends StatusBar {
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
lp.setTitle("NotificationPanel");
+ lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
+ | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+ lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
@@ -391,7 +395,7 @@ public class TabletStatusBar extends StatusBar {
mNotificationPeekRow.addView(copy.row);
mNotificationPeekWindow.setVisibility(View.VISIBLE);
- mNotificationPanel.setVisibility(View.GONE);
+ mNotificationPanel.show(false, true);
mNotificationPeekIndex = peekIndex;
mNotificationPeekKey = entry.key;
@@ -413,9 +417,9 @@ public class TabletStatusBar extends StatusBar {
break;
case MSG_OPEN_NOTIFICATION_PANEL:
if (DEBUG) Slog.d(TAG, "opening notifications panel");
- if (mNotificationPanel.getVisibility() == View.GONE) {
+ if (!mNotificationPanel.isShowing()) {
mNotificationPeekWindow.setVisibility(View.GONE);
- mNotificationPanel.setVisibility(View.VISIBLE);
+ mNotificationPanel.show(true, true);
// synchronize with current shadow state
mShadowController.hideElement(mNotificationArea);
mTicker.halt();
@@ -423,8 +427,8 @@ public class TabletStatusBar extends StatusBar {
break;
case MSG_CLOSE_NOTIFICATION_PANEL:
if (DEBUG) Slog.d(TAG, "closing notifications panel");
- if (mNotificationPanel.getVisibility() == View.VISIBLE) {
- mNotificationPanel.setVisibility(View.GONE);
+ if (mNotificationPanel.isShowing()) {
+ mNotificationPanel.show(false, true);
// synchronize with current shadow state
mShadowController.showElement(mNotificationArea);
}
@@ -459,8 +463,7 @@ public class TabletStatusBar extends StatusBar {
if (mNotificationTrigger == null) return;
int resId;
- boolean panel = (mNotificationPanel != null
- && mNotificationPanel.getVisibility() == View.VISIBLE);
+ boolean panel = (mNotificationPanel != null && mNotificationPanel.isShowing();
if (!mNotificationsOn) {
resId = R.drawable.ic_sysbar_noti_dnd;
} else if (mNotns.size() > 0) {
@@ -658,7 +661,7 @@ public class TabletStatusBar extends StatusBar {
private void tick(IBinder key, StatusBarNotification n) {
// Don't show the ticker when the windowshade is open.
- if (mNotificationPanel.getVisibility() == View.VISIBLE) {
+ if (mNotificationPanel.isShowing()) {
return;
}
// Show the ticker if one is requested. Also don't do this
@@ -786,7 +789,7 @@ public class TabletStatusBar extends StatusBar {
mIconLayout.setVisibility(View.VISIBLE); // TODO: animation
refreshNotificationTrigger();
} else {
- int msg = (mNotificationPanel.getVisibility() == View.GONE)
+ int msg = !mNotificationPanel.isShowing()
? MSG_OPEN_NOTIFICATION_PANEL
: MSG_CLOSE_NOTIFICATION_PANEL;
mHandler.removeMessages(msg);
@@ -895,7 +898,7 @@ public class TabletStatusBar extends StatusBar {
public boolean onTouch(View v, MotionEvent event) {
boolean peeking = mNotificationPeekWindow.getVisibility() != View.GONE;
- boolean panelShowing = mNotificationPanel.getVisibility() != View.GONE;
+ boolean panelShowing = mNotificationPanel.isShowing();
if (panelShowing) return false;
switch (event.getAction()) {