Merge "Simplify panel animations with an eye to performance." into honeycomb
This commit is contained in:
committed by
Android (Google) Code Review
commit
033376f6f0
@@ -12,6 +12,7 @@
|
||||
<application
|
||||
android:persistent="true"
|
||||
android:allowClearUserData="false"
|
||||
android:hardwareAccelerated="true"
|
||||
android:label="@string/app_label"
|
||||
android:icon="@drawable/ic_launcher_settings">
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 152 B After Width: | Height: | Size: 243 B |
22
packages/SystemUI/res/drawable/panel_notification_tiled.xml
Normal file
22
packages/SystemUI/res/drawable/panel_notification_tiled.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2011 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.
|
||||
-->
|
||||
|
||||
<bitmap
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/panel_notification"
|
||||
android:tileMode="repeat"
|
||||
/>
|
||||
|
||||
@@ -20,27 +20,35 @@
|
||||
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="right"
|
||||
android:paddingTop="32dp"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
<View
|
||||
android:id="@+id/scrim"
|
||||
android:background="@drawable/notify_panel_bg_protect"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/content_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
>
|
||||
|
||||
<com.android.systemui.statusbar.tablet.NotificationTitleArea
|
||||
<RelativeLayout
|
||||
android:id="@+id/title_area"
|
||||
android:layout_height="160dp"
|
||||
android:layout_width="384dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:paddingTop="20dp"
|
||||
android:orientation="vertical"
|
||||
android:animateLayoutChanges="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="@drawable/panel_notification_tiled"
|
||||
>
|
||||
|
||||
<com.android.systemui.statusbar.tablet.HoloClock
|
||||
@@ -154,13 +162,15 @@
|
||||
android:src="@drawable/status_bar_veto"
|
||||
android:baseline="21dp"
|
||||
/>
|
||||
</com.android.systemui.statusbar.tablet.NotificationTitleArea>
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/content_frame"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="408dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_below="@id/title_area"
|
||||
android:layout_alignParentRight="true"
|
||||
>
|
||||
<ScrollView
|
||||
android:id="@+id/notification_scroller"
|
||||
@@ -191,5 +201,17 @@
|
||||
android:src="@drawable/notify_item_glow_bottom"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/glow"
|
||||
android:background="@drawable/notify_glow_back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/content_parent"
|
||||
android:layout_alignLeft="@id/content_parent"
|
||||
android:layout_marginLeft="100dip"
|
||||
android:layout_marginTop="-100dip"
|
||||
/>
|
||||
|
||||
</com.android.systemui.statusbar.tablet.NotificationPanel>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.statusbar.tablet;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
@@ -33,11 +34,13 @@ import android.view.animation.AccelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
|
||||
View.OnClickListener {
|
||||
static final String TAG = "Tablet/NotificationPanel";
|
||||
static final boolean DEBUG = false;
|
||||
@@ -51,12 +54,11 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
ViewGroup mContentFrame;
|
||||
Rect mContentArea;
|
||||
View mSettingsView;
|
||||
View mScrim, mGlow;
|
||||
ViewGroup mContentParent;
|
||||
|
||||
Choreographer mChoreo = new Choreographer();
|
||||
int mStatusBarHeight;
|
||||
Drawable mBgDrawable;
|
||||
Drawable mGlowDrawable;
|
||||
|
||||
public NotificationPanel(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
@@ -69,8 +71,6 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
|
||||
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
|
||||
@@ -80,9 +80,13 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
setWillNotDraw(false);
|
||||
|
||||
mContentParent = (ViewGroup)findViewById(R.id.content_parent);
|
||||
mContentParent.bringToFront();
|
||||
mTitleArea = findViewById(R.id.title_area);
|
||||
mTitleArea.setOnClickListener(this);
|
||||
|
||||
mScrim = findViewById(R.id.scrim);
|
||||
mGlow = findViewById(R.id.glow);
|
||||
|
||||
mSettingsButton = (ImageView)findViewById(R.id.settings_button);
|
||||
mNotificationButton = (ImageView)findViewById(R.id.notification_button);
|
||||
|
||||
@@ -132,21 +136,6 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
// We know that none of our children are GONE, so don't worry about skipping GONE views.
|
||||
final int N = getChildCount();
|
||||
if (N == 0) {
|
||||
return;
|
||||
}
|
||||
final int allocatedBottom = getChildAt(N-1).getBottom();
|
||||
final int shift = b - allocatedBottom - getPaddingBottom();
|
||||
if (shift <= 0) {
|
||||
return;
|
||||
}
|
||||
for (int i=0; i<N; i++) {
|
||||
final View c = getChildAt(i);
|
||||
c.layout(c.getLeft(), c.getTop() + shift, c.getRight(), c.getBottom() + shift);
|
||||
}
|
||||
|
||||
mChoreo.setPanelHeight(mContentParent.getHeight());
|
||||
}
|
||||
|
||||
@@ -154,26 +143,6 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
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) {
|
||||
@@ -227,82 +196,82 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
|
||||
private class Choreographer implements Animator.AnimatorListener {
|
||||
boolean mVisible;
|
||||
int mBgAlpha;
|
||||
ValueAnimator mBgAnim;
|
||||
int mPanelHeight;
|
||||
int mPanelBottom;
|
||||
ValueAnimator mPositionAnim;
|
||||
AnimatorSet mContentAnim;
|
||||
|
||||
// should group this into a multi-property animation
|
||||
final int OPEN_DURATION = 200;
|
||||
final int OPEN_DURATION = 250;
|
||||
|
||||
// the panel will start to appear this many px from the end
|
||||
final int HYPERSPACE_OFFRAMP = 120;
|
||||
|
||||
Choreographer() {
|
||||
}
|
||||
|
||||
void createAnimation(boolean visible) {
|
||||
mBgAnim = ObjectAnimator.ofInt(this, "bgAlpha", mBgAlpha, visible ? 255 : 0)
|
||||
.setDuration(OPEN_DURATION);
|
||||
mBgAnim.addListener(this);
|
||||
void createAnimation(boolean appearing) {
|
||||
Animator bgAnim = ObjectAnimator.ofFloat(mScrim,
|
||||
"alpha", mScrim.getAlpha(), appearing ? 1 : 0);
|
||||
|
||||
mPositionAnim = ObjectAnimator.ofInt(this, "panelBottom", mPanelBottom,
|
||||
visible ? mPanelHeight : 0)
|
||||
.setDuration(OPEN_DURATION);
|
||||
}
|
||||
float start, end;
|
||||
|
||||
void startAnimation(boolean visible) {
|
||||
if (DEBUG) Slog.d(TAG, "startAnimation(visible=" + visible + ")");
|
||||
|
||||
createAnimation(visible);
|
||||
mBgAnim.start();
|
||||
mPositionAnim.start();
|
||||
|
||||
mVisible = visible;
|
||||
}
|
||||
|
||||
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;
|
||||
// 0: on-screen
|
||||
// height: off-screen
|
||||
float y = mContentParent.getTranslationY();
|
||||
if (appearing) {
|
||||
// we want to go from near-the-top to the top, unless we're half-open in the right
|
||||
// general vicinity
|
||||
start = (y < HYPERSPACE_OFFRAMP)
|
||||
? y
|
||||
: HYPERSPACE_OFFRAMP;
|
||||
end = 0;
|
||||
} else {
|
||||
alpha = ((float)mPanelBottom) / glowYOffset;
|
||||
start = y;
|
||||
end = y + HYPERSPACE_OFFRAMP;
|
||||
}
|
||||
mContentParent.setAlpha(alpha);
|
||||
mGlowDrawable.setAlpha((int)(255 * alpha));
|
||||
Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY", start, end);
|
||||
posAnim.setInterpolator(appearing
|
||||
? new android.view.animation.DecelerateInterpolator(2.0f)
|
||||
: new android.view.animation.AccelerateInterpolator(2.0f));
|
||||
|
||||
if (false) {
|
||||
Slog.d(TAG, "mPanelBottom=" + mPanelBottom + " translationY=" + translationY
|
||||
+ " alpha=" + alpha + " glowY=" + glowY);
|
||||
}
|
||||
Animator glowAnim = ObjectAnimator.ofFloat(mGlow, "alpha",
|
||||
mGlow.getAlpha(), appearing ? 1.0f : 0.0f);
|
||||
glowAnim.setInterpolator(appearing
|
||||
? new android.view.animation.AccelerateInterpolator(1.0f)
|
||||
: new android.view.animation.DecelerateInterpolator(1.0f));
|
||||
|
||||
mContentAnim = new AnimatorSet();
|
||||
mContentAnim
|
||||
.play(ObjectAnimator.ofFloat(mContentParent, "alpha", mContentParent.getAlpha(),
|
||||
appearing ? 1.0f : 0.0f))
|
||||
.with(glowAnim)
|
||||
.with(bgAnim)
|
||||
.with(posAnim)
|
||||
;
|
||||
mContentAnim.setDuration(OPEN_DURATION);
|
||||
mContentAnim.addListener(this);
|
||||
}
|
||||
|
||||
void startAnimation(boolean appearing) {
|
||||
if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
|
||||
|
||||
createAnimation(appearing);
|
||||
|
||||
mContentParent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
mContentAnim.start();
|
||||
|
||||
mVisible = appearing;
|
||||
}
|
||||
|
||||
void jumpTo(boolean appearing) {
|
||||
// setBgAlpha(appearing ? 255 : 0);
|
||||
mContentParent.setTranslationY(appearing ? 0 : mPanelHeight);
|
||||
}
|
||||
|
||||
public void setPanelHeight(int h) {
|
||||
if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
|
||||
mPanelHeight = h;
|
||||
if (mPanelBottom == 0) {
|
||||
if (mPanelHeight == 0) {
|
||||
// fully closed, no animation necessary
|
||||
setPanelBottom(0);
|
||||
} else if (mVisible) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim to open fully");
|
||||
@@ -312,17 +281,18 @@ public class NotificationPanel extends LinearLayout implements StatusBarPanel,
|
||||
}
|
||||
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
if (DEBUG) Slog.d(TAG, "onAnimationCancel mBgAlpha=" + mBgAlpha);
|
||||
if (DEBUG) Slog.d(TAG, "onAnimationCancel");
|
||||
// force this to zero so we close the window
|
||||
mBgAlpha = 0;
|
||||
mVisible = false;
|
||||
}
|
||||
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (DEBUG) Slog.d(TAG, "onAnimationEnd mBgAlpha=" + mBgAlpha);
|
||||
if (mBgAlpha == 0) {
|
||||
if (DEBUG) Slog.d(TAG, "onAnimationEnd");
|
||||
if (! mVisible) {
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
mBgAnim = null;
|
||||
mContentParent.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
mContentAnim = null;
|
||||
}
|
||||
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Slog;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
public class NotificationTitleArea extends RelativeLayout {
|
||||
static final String TAG = "NotificationTitleArea";
|
||||
|
||||
View mSettingsButton;
|
||||
View mNotificationButton;
|
||||
View mNotificationScroller;
|
||||
FrameLayout mSettingsFrame;
|
||||
View mSettingsPanel;
|
||||
|
||||
// for drawing the background
|
||||
Bitmap mTexture;
|
||||
Paint mPaint;
|
||||
int mTextureWidth;
|
||||
int mTextureHeight;
|
||||
|
||||
|
||||
public NotificationTitleArea(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public NotificationTitleArea(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
// for drawing the background
|
||||
mTexture = BitmapFactory.decodeResource(getResources(), R.drawable.panel_notification);
|
||||
mTextureWidth = mTexture.getWidth();
|
||||
mTextureHeight = mTexture.getHeight();
|
||||
|
||||
mPaint = new Paint();
|
||||
mPaint.setDither(false);
|
||||
}
|
||||
|
||||
public void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
final Bitmap texture = mTexture;
|
||||
final Paint paint = mPaint;
|
||||
|
||||
final int width = getWidth();
|
||||
final int height = getHeight();
|
||||
|
||||
final int textureWidth = mTextureWidth;
|
||||
final int textureHeight = mTextureHeight;
|
||||
|
||||
int x = 0;
|
||||
int y;
|
||||
|
||||
while (x < width) {
|
||||
y = 0;
|
||||
while (y < height) {
|
||||
canvas.drawBitmap(texture, x, y, paint);
|
||||
y += textureHeight;
|
||||
}
|
||||
x += textureWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ public class TabletStatusBar extends StatusBar {
|
||||
mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
|
||||
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
720, // ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
@@ -196,6 +196,7 @@ public class TabletStatusBar extends StatusBar {
|
||||
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
|
||||
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||
lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
|
||||
// lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
|
||||
|
||||
WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user