Merge "Fix 3253629: Tweaks to recent apps" into honeycomb

This commit is contained in:
Jim Miller
2011-01-12 20:07:36 -08:00
committed by Android (Google) Code Review
5 changed files with 227 additions and 110 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -20,23 +20,25 @@
<com.android.systemui.statusbar.tablet.RecentAppsPanel <com.android.systemui.statusbar.tablet.RecentAppsPanel
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recents_root"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="wrap_content" android:layout_width="wrap_content">
android:layout_marginBottom="48dip"
android:background="@drawable/recents_bg_protect_tile"
android:id="@+id/recents_bg_protect"
android:orientation="vertical">
<View <FrameLayout
android:layout_width="match_parent" android:id="@+id/recents_bg_protect"
android:layout_height="0dip" android:background="@drawable/recents_bg_protect_tile"
android:layout_weight="1" android:layout_width="wrap_content"
/> android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:paddingBottom="48dip"
android:clipToPadding="false">
<LinearLayout android:id="@+id/recents_glow" <LinearLayout android:id="@+id/recents_glow"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:layout_marginBottom="-28dip"
android:layout_gravity="bottom"
android:background="@drawable/recents_blue_glow"> android:background="@drawable/recents_blue_glow">
<LinearLayout android:id="@+id/recents_container" <LinearLayout android:id="@+id/recents_container"
@@ -48,4 +50,6 @@
</LinearLayout> </LinearLayout>
</FrameLayout>
</com.android.systemui.statusbar.tablet.RecentAppsPanel> </com.android.systemui.statusbar.tablet.RecentAppsPanel>

View File

@@ -194,10 +194,11 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
AnimatorSet mContentAnim; AnimatorSet mContentAnim;
// should group this into a multi-property animation // should group this into a multi-property animation
final int OPEN_DURATION = 250; final int OPEN_DURATION = 136;
final int CLOSE_DURATION = 250;
// the panel will start to appear this many px from the end // the panel will start to appear this many px from the end
final int HYPERSPACE_OFFRAMP = 120; final int HYPERSPACE_OFFRAMP = 30;
Choreographer() { Choreographer() {
} }
@@ -241,7 +242,7 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
.with(bgAnim) .with(bgAnim)
.with(posAnim) .with(posAnim)
; ;
mContentAnim.setDuration(OPEN_DURATION); mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
mContentAnim.addListener(this); mContentAnim.addListener(this);
} }

View File

@@ -43,32 +43,33 @@ import android.graphics.drawable.Drawable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.Slog;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.animation.DecelerateInterpolator; import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import com.android.systemui.R; import com.android.systemui.R;
public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnClickListener { public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, OnClickListener {
private static final int GLOW_PADDING = 15; private static final int GLOW_PADDING = 15;
private static final String TAG = "RecentAppsPanel"; private static final String TAG = "RecentAppsPanel";
private static final boolean DEBUG = TabletStatusBar.DEBUG; private static final boolean DEBUG = TabletStatusBar.DEBUG;
private static final int DISPLAY_TASKS_PORTRAIT = 7; // Limited by max binder transaction size private static final int DISPLAY_TASKS_PORTRAIT = 7; // Limited by max binder transaction size
private static final int DISPLAY_TASKS_LANDSCAPE = 5; // number of recent tasks to display private static final int DISPLAY_TASKS_LANDSCAPE = 5; // number of recent tasks to display
private static final int MAX_TASKS = DISPLAY_TASKS_PORTRAIT + 1; // allow extra for non-apps private static final int MAX_TASKS = DISPLAY_TASKS_PORTRAIT + 1; // allow extra for non-apps
private static final int STAGGER_ANIMATION_DELAY = 30;
private static final long ALPHA_ANIMATION_DURATION = 120;
private TabletStatusBar mBar; private TabletStatusBar mBar;
private LinearLayout mRecentsContainer;
private View mRecentsGlowView;
private ArrayList<ActivityDescription> mActivityDescriptions; private ArrayList<ActivityDescription> mActivityDescriptions;
private int mIconDpi; private int mIconDpi;
private AnimatorSet mAnimationSet; private View mRecentsScrim;
private View mBackgroundProtector; private View mRecentsGlowView;
private LinearLayout mRecentsContainer;
private Bitmap mGlowBitmap; private Bitmap mGlowBitmap;
private boolean mShowing;
private Choreographer mChoreo;
static class ActivityDescription { static class ActivityDescription {
int id; int id;
@@ -104,6 +105,145 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC
return x >= l && x < r && y >= t && y < b; return x >= l && x < r && y >= t && y < b;
} }
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);
}
}
/**
* We need to be aligned at the bottom. LinearLayout can't do this, so instead,
* let LinearLayout do all the hard work, and then shift everything down to the bottom.
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mChoreo.setPanelHeight(mRecentsContainer.getHeight());
}
/**
* Whether the panel is showing, or, if it's animating, whether it will be
* when the animation is done.
*/
public boolean isShowing() {
return mShowing;
}
private static class Choreographer implements Animator.AnimatorListener {
// should group this into a multi-property animation
private static final int OPEN_DURATION = 136;
private static final int CLOSE_DURATION = 250;
boolean mVisible;
int mPanelHeight;
View mRootView;
View mScrimView;
View mContentView;
AnimatorSet mContentAnim;
// the panel will start to appear this many px from the end
final int HYPERSPACE_OFFRAMP = 200;
public Choreographer(View root, View scrim, View content) {
mRootView = root;
mScrimView = scrim;
mContentView = content;
}
void createAnimation(boolean appearing) {
float start, end;
if (DEBUG) Log.e(TAG, "createAnimation()", new Exception());
// 0: on-screen
// height: off-screen
float y = mContentView.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 {
start = y;
end = y + HYPERSPACE_OFFRAMP;
}
Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
start, end);
posAnim.setInterpolator(appearing
? new android.view.animation.DecelerateInterpolator(2.5f)
: new android.view.animation.AccelerateInterpolator(2.5f));
Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
glowAnim.setInterpolator(appearing
? new android.view.animation.AccelerateInterpolator(1.0f)
: new android.view.animation.DecelerateInterpolator(1.0f));
Animator bgAnim = ObjectAnimator.ofInt(mScrimView.getBackground(),
"alpha", appearing ? 0 : 255, appearing ? 255 : 0);
mContentAnim = new AnimatorSet();
mContentAnim
.play(bgAnim)
.with(glowAnim)
.with(posAnim);
mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
mContentAnim.addListener(this);
}
void startAnimation(boolean appearing) {
if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
createAnimation(appearing);
mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mContentAnim.start();
mVisible = appearing;
}
void jumpTo(boolean appearing) {
mContentView.setTranslationY(appearing ? 0 : mPanelHeight);
}
public void setPanelHeight(int h) {
if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
mPanelHeight = h;
}
public void onAnimationCancel(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationCancel");
// force this to zero so we close the window
mVisible = false;
}
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationEnd");
if (!mVisible) {
mRootView.setVisibility(View.GONE);
}
mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
mContentAnim = null;
}
public void onAnimationRepeat(Animator animation) {
}
public void onAnimationStart(Animator animation) {
}
}
public void setBar(TabletStatusBar bar) { public void setBar(TabletStatusBar bar) {
mBar = bar; mBar = bar;
} }
@@ -128,12 +268,12 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC
super.onFinishInflate(); super.onFinishInflate();
mRecentsContainer = (LinearLayout) findViewById(R.id.recents_container); mRecentsContainer = (LinearLayout) findViewById(R.id.recents_container);
mRecentsGlowView = findViewById(R.id.recents_glow); mRecentsGlowView = findViewById(R.id.recents_glow);
mBackgroundProtector = (View) findViewById(R.id.recents_bg_protect); mRecentsScrim = (View) findViewById(R.id.recents_bg_protect);
mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView);
// In order to save space, we make the background texture repeat in the Y direction // In order to save space, we make the background texture repeat in the Y direction
View view = findViewById(R.id.recents_bg_protect); if (mRecentsScrim != null && mRecentsScrim.getBackground() instanceof BitmapDrawable) {
if (view != null && view.getBackground() instanceof BitmapDrawable) { ((BitmapDrawable) mRecentsScrim.getBackground()).setTileModeY(TileMode.REPEAT);
((BitmapDrawable) view.getBackground()).setTileModeY(TileMode.REPEAT);
} }
} }
@@ -255,7 +395,10 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC
if (mActivityDescriptions.size() > 0) { if (mActivityDescriptions.size() > 0) {
updateUiElements(getResources().getConfiguration(), true); updateUiElements(getResources().getConfiguration(), true);
} else { } else {
mBar.animateCollapse(); // Immediately hide this panel
mShowing = false;
setVisibility(View.GONE);
// mBar.animateCollapse();
} }
} }
@@ -284,13 +427,10 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC
private void updateUiElements(Configuration config, boolean animate) { private void updateUiElements(Configuration config, boolean animate) {
mRecentsContainer.removeAllViews(); mRecentsContainer.removeAllViews();
final float initialAlpha = 0.0f;
final int first = 0; final int first = 0;
final boolean isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT; final boolean isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT;
final int taskCount = isPortrait ? DISPLAY_TASKS_PORTRAIT : DISPLAY_TASKS_LANDSCAPE; final int taskCount = isPortrait ? DISPLAY_TASKS_PORTRAIT : DISPLAY_TASKS_LANDSCAPE;
final int last = Math.min(mActivityDescriptions.size(), taskCount) - 1; final int last = Math.min(mActivityDescriptions.size(), taskCount) - 1;
ArrayList<Animator> anims = new ArrayList<Animator>(last+1);
DecelerateInterpolator interp = new DecelerateInterpolator();
for (int i = last; i >= first; i--) { for (int i = last; i >= first; i--) {
ActivityDescription activityDescription = mActivityDescriptions.get(i); ActivityDescription activityDescription = mActivityDescriptions.get(i);
View view = View.inflate(mContext, R.layout.status_bar_recent_item, null); View view = View.inflate(mContext, R.layout.status_bar_recent_item, null);
@@ -306,40 +446,11 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC
view.setOnClickListener(this); view.setOnClickListener(this);
view.setTag(activityDescription); view.setTag(activityDescription);
mRecentsContainer.addView(view); mRecentsContainer.addView(view);
if (animate) {
view.setAlpha(initialAlpha);
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", initialAlpha, 1.0f);
anim.setDuration(ALPHA_ANIMATION_DURATION);
anim.setStartDelay((last-i) * STAGGER_ANIMATION_DELAY);
anim.setInterpolator(interp);
anims.add(anim);
}
} }
int views = mRecentsContainer.getChildCount(); int views = mRecentsContainer.getChildCount();
mRecentsContainer.setVisibility(views > 0 ? View.VISIBLE : View.GONE); mRecentsContainer.setVisibility(views > 0 ? View.VISIBLE : View.GONE);
mRecentsGlowView.setVisibility(views > 0 ? View.VISIBLE : View.GONE); mRecentsGlowView.setVisibility(views > 0 ? View.VISIBLE : View.GONE);
if (animate && views > 0) {
ObjectAnimator anim = ObjectAnimator.ofFloat(mRecentsGlowView, "alpha",
initialAlpha, 1.0f);
anim.setDuration((last-first) * STAGGER_ANIMATION_DELAY);
anim.setInterpolator(interp);
anims.add(anim);
anim = ObjectAnimator.ofFloat(mBackgroundProtector, "alpha",
initialAlpha, 1.0f);
anim.setDuration(last * STAGGER_ANIMATION_DELAY);
anim.setInterpolator(interp);
anims.add(anim);
}
if (anims.size() > 0) {
mAnimationSet = new AnimatorSet();
mAnimationSet.playTogether(anims);
mAnimationSet.start();
}
} }
public void onClick(View v) { public void onClick(View v) {
@@ -356,6 +467,7 @@ public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnC
if (DEBUG) Log.v(TAG, "Starting activity " + intent); if (DEBUG) Log.v(TAG, "Starting activity " + intent);
getContext().startActivity(intent); getContext().startActivity(intent);
} }
setVisibility(View.GONE);
mBar.animateCollapse(); mBar.animateCollapse();
} }
} }

View File

@@ -93,9 +93,6 @@ public class TabletStatusBar extends StatusBar implements
// Fitts' Law assistance for LatinIME; TODO: replace with a more general approach // Fitts' Law assistance for LatinIME; TODO: replace with a more general approach
private static final boolean FAKE_SPACE_BAR = true; private static final boolean FAKE_SPACE_BAR = true;
private static final int MAX_IMAGE_LEVEL = 10000;
private static final boolean USE_2D_RECENTS = true;
public static final int LIGHTS_ON_DELAY = 5000; public static final int LIGHTS_ON_DELAY = 5000;
// The height of the bar, as definied by the build. It may be taller if we're plugged // The height of the bar, as definied by the build. It may be taller if we're plugged
@@ -241,7 +238,6 @@ public class TabletStatusBar extends StatusBar implements
WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp); WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
// Recents Panel // Recents Panel
if (USE_2D_RECENTS) {
mRecentsPanel = (RecentAppsPanel) View.inflate(context, mRecentsPanel = (RecentAppsPanel) View.inflate(context,
R.layout.status_bar_recent_panel, null); R.layout.status_bar_recent_panel, null);
mRecentsPanel.setVisibility(View.GONE); mRecentsPanel.setVisibility(View.GONE);
@@ -265,7 +261,6 @@ public class TabletStatusBar extends StatusBar implements
WindowManagerImpl.getDefault().addView(mRecentsPanel, lp); WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
mRecentsPanel.setBar(this); mRecentsPanel.setBar(this);
} }
}
@Override @Override
public void start() { public void start() {
@@ -516,11 +511,16 @@ public class TabletStatusBar extends StatusBar implements
break; break;
case MSG_OPEN_RECENTS_PANEL: case MSG_OPEN_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "opening recents panel"); if (DEBUG) Slog.d(TAG, "opening recents panel");
if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.VISIBLE); if (mRecentsPanel != null) {
mRecentsPanel.setVisibility(View.VISIBLE);
mRecentsPanel.show(true, true);
}
break; break;
case MSG_CLOSE_RECENTS_PANEL: case MSG_CLOSE_RECENTS_PANEL:
if (DEBUG) Slog.d(TAG, "closing recents panel"); if (DEBUG) Slog.d(TAG, "closing recents panel");
if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.GONE); if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
mRecentsPanel.show(false, true);
}
break; break;
case MSG_SHOW_CHROME: case MSG_SHOW_CHROME:
if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)"); if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");