Merge "New status bar capable of multiple sliding panels." into jb-mr1-dev

This commit is contained in:
Daniel Sandler
2012-08-14 07:56:44 -07:00
committed by Android (Google) Code Review
12 changed files with 646 additions and 653 deletions

View File

@@ -12,6 +12,12 @@ public class TimeAnimator extends ValueAnimator {
private TimeListener mListener; private TimeListener mListener;
private long mPreviousTime = -1; private long mPreviousTime = -1;
@Override
public void start() {
mPreviousTime = -1;
super.start();
}
@Override @Override
boolean animationFrame(long currentTime) { boolean animationFrame(long currentTime) {
if (mListener != null) { if (mListener != null) {

View File

@@ -31,10 +31,16 @@
android:layout_height="@*android:dimen/status_bar_height" android:layout_height="@*android:dimen/status_bar_height"
/> />
<include layout="@layout/status_bar_expanded"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="0dp"
android:layout_gravity="center_horizontal|top"
/>
<com.android.systemui.statusbar.phone.PanelHolder
android:id="@+id/panel_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<include layout="@layout/status_bar_expanded"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
/>
</com.android.systemui.statusbar.phone.PanelHolder>
</com.android.systemui.statusbar.phone.StatusBarWindowView> </com.android.systemui.statusbar.phone.StatusBarWindowView>

View File

@@ -18,12 +18,12 @@
*/ */
--> -->
<FrameLayout <com.android.systemui.statusbar.phone.NotificationPanelView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/notification_panel" android:id="@+id/notification_panel"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="0dp"
android:background="@drawable/notification_panel_bg" android:background="@drawable/notification_panel_bg"
android:paddingTop="@dimen/notification_panel_padding_top" android:paddingTop="@dimen/notification_panel_padding_top"
android:layout_marginLeft="@dimen/notification_panel_margin_left" android:layout_marginLeft="@dimen/notification_panel_margin_left"
@@ -42,7 +42,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/close_handle_underlap" android:layout_marginBottom="@dimen/close_handle_underlap"
android:orientation="vertical" android:orientation="vertical"
> >
@@ -65,7 +65,7 @@
<ScrollView <ScrollView
android:id="@+id/scroll" android:id="@+id/scroll"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:fadingEdge="none" android:fadingEdge="none"
android:overScrollMode="always" android:overScrollMode="always"
> >
@@ -78,7 +78,7 @@
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>
<com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close" <LinearLayout android:id="@+id/handle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/close_handle_height" android:layout_height="@dimen/close_handle_height"
android:layout_gravity="bottom" android:layout_gravity="bottom"
@@ -91,6 +91,5 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/status_bar_close" android:src="@drawable/status_bar_close"
/> />
</LinearLayout>
</com.android.systemui.statusbar.phone.CloseDragHandle> </com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
</FrameLayout><!-- end of sliding panel -->

View File

@@ -32,9 +32,15 @@
android:layout_height="@*android:dimen/status_bar_height" android:layout_height="@*android:dimen/status_bar_height"
/> />
<include layout="@layout/status_bar_expanded" <com.android.systemui.statusbar.phone.PanelHolder
android:id="@+id/panel_holder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
/> >
<include layout="@layout/status_bar_expanded"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</com.android.systemui.statusbar.phone.PanelHolder>
</com.android.systemui.statusbar.phone.StatusBarWindowView> </com.android.systemui.statusbar.phone.StatusBarWindowView>

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2012 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.phone;
import android.content.Context;
import android.util.AttributeSet;
public class NotificationPanelView extends PanelView {
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
android.util.Slog.v("NotificationPanelView", "ctor");
}
@Override
public void fling(float vel, boolean always) {
((PhoneStatusBarView) mBar).mBar.getGestureRecorder().tag(
"fling " + ((vel > 0) ? "open" : "closed"),
"v=" + vel);
super.fling(vel, always);
}
}

View File

@@ -0,0 +1,115 @@
package com.android.systemui.statusbar.phone;
import java.util.ArrayList;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class PanelBar extends FrameLayout {
public static final boolean DEBUG = true;
public static final String TAG = PanelView.class.getSimpleName();
public static final void LOG(String fmt, Object... args) {
if (!DEBUG) return;
Slog.v(TAG, String.format(fmt, args));
}
private PanelHolder mPanelHolder;
private ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
private PanelView mTouchingPanel;
public PanelBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
public void addPanel(PanelView pv) {
mPanels.add(pv);
pv.setBar(this);
}
public void setPanelHolder(PanelHolder ph) {
if (ph == null) {
Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
return;
}
ph.setBar(this);
mPanelHolder = ph;
final int N = ph.getChildCount();
for (int i=0; i<N; i++) {
final PanelView v = (PanelView) ph.getChildAt(i);
if (v != null) {
addPanel(v);
}
}
}
public float getBarHeight() {
return getMeasuredHeight();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// figure out which panel needs to be talked to here
if (event.getAction() == MotionEvent.ACTION_DOWN) {
final int N = mPanels.size();
final int i = (int)(N * event.getX() / getMeasuredWidth());
mTouchingPanel = mPanels.get(i);
mPanelHolder.setSelectedPanel(mTouchingPanel);
LOG("PanelBar.onTouch: ACTION_DOWN: panel %d", i);
onPanelPeeked();
}
final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event);
return result;
}
public void panelExpansionChanged(PanelView panel, float frac) {
boolean fullyClosed = true;
boolean fullyOpened = false;
for (PanelView pv : mPanels) {
if (pv.getExpandedHeight() > 0f) {
fullyClosed = false;
final float thisFrac = pv.getExpandedFraction();
LOG("panel %s: f=%.1f", pv, thisFrac);
if (panel == pv) {
if (thisFrac == 1f) fullyOpened = true;
} else {
pv.setExpandedFraction(1f-frac);
}
}
}
if (fullyOpened) onPanelFullyOpened();
if (fullyClosed) onAllPanelsCollapsed();
else onPanelPeeked();
LOG("panelExpansionChanged: [%s%s ]", fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
}
public void collapseAllPanels(boolean animate) {
for (PanelView pv : mPanels) {
if (animate && pv == mTouchingPanel) {
mTouchingPanel.collapse();
} else {
pv.setExpandedFraction(0); // just in case
}
}
}
public void onPanelPeeked() {
LOG("onPanelPeeked");
}
public void onAllPanelsCollapsed() {
LOG("onAllPanelsCollapsed");
}
public void onPanelFullyOpened() {
LOG("onPanelFullyOpened");
}
}

View File

@@ -0,0 +1,65 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class PanelHolder extends FrameLayout {
private int mSelectedPanelIndex;
private PanelBar mBar;
public PanelHolder(Context context, AttributeSet attrs) {
super(context, attrs);
setChildrenDrawingOrderEnabled(true);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
setChildrenDrawingOrderEnabled(true);
}
public int getPanelIndex(PanelView pv) {
final int N = getChildCount();
for (int i=0; i<N; i++) {
final PanelView v = (PanelView) getChildAt(i);
if (pv == v) return i;
}
return -1;
}
public void setSelectedPanel(PanelView pv) {
mSelectedPanelIndex = getPanelIndex(pv);
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {
if (mSelectedPanelIndex == -1) {
return i;
} else {
if (i == childCount - 1) {
return mSelectedPanelIndex;
} else if (i >= mSelectedPanelIndex) {
return i + 1;
} else {
return i;
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mBar.collapseAllPanels(true);
break;
}
return false;
}
public void setBar(PanelBar panelBar) {
mBar = panelBar;
}
}

View File

@@ -0,0 +1,327 @@
package com.android.systemui.statusbar.phone;
import android.animation.TimeAnimator;
import android.animation.TimeAnimator.TimeListener;
import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.FrameLayout;
import com.android.systemui.R;
public class PanelView extends FrameLayout {
public static final boolean DEBUG = true;
public static final String TAG = PanelView.class.getSimpleName();
public static final void LOG(String fmt, Object... args) {
if (!DEBUG) return;
Log.v(TAG, String.format(fmt, args));
}
public static final boolean BRAKES = false;
private float mSelfExpandVelocityPx; // classic value: 2000px/s
private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
private float mFlingExpandMinVelocityPx; // classic value: 200px/s
private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
private float mExpandAccelPx; // classic value: 2000px/s/s
private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
private float mFlingGestureMaxOutputVelocityPx; // how fast can it really go? (should be a little
// faster than mSelfCollapseVelocityPx)
private float mCollapseBrakingDistancePx = 200; // XXX Resource
private float mExpandBrakingDistancePx = 150; // XXX Resource
private float mBrakingSpeedPx = 150; // XXX Resource
private View mHandleView;
private float mTouchOffset;
private float mExpandedFraction = 0;
private float mExpandedHeight = 0;
private TimeAnimator mTimeAnimator;
private VelocityTracker mVelocityTracker;
private int[] mAbsPos = new int[2];
PanelBar mBar;
private final TimeListener mAnimationCallback = new TimeListener() {
@Override
public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
animationTick(deltaTime);
}
};
private float mVel, mAccel;
private int mFullHeight = 0;
private void animationTick(long dtms) {
if (!mTimeAnimator.isStarted()) {
// XXX HAX to work around bug in TimeAnimator.end() not resetting its last time
mTimeAnimator = new TimeAnimator();
mTimeAnimator.setTimeListener(mAnimationCallback);
mTimeAnimator.start();
} else {
final float dt = dtms * 0.001f; // ms -> s
LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
LOG("tick: before: h=%d", (int) mExpandedHeight);
final float fh = getFullHeight();
final boolean closing = mExpandedHeight > 0 && mVel < 0;
boolean braking = false;
if (BRAKES) {
if (closing) {
braking = mExpandedHeight <= mCollapseBrakingDistancePx;
mAccel = braking ? 10*mCollapseAccelPx : -mCollapseAccelPx;
} else {
braking = mExpandedHeight >= (fh-mExpandBrakingDistancePx);
mAccel = braking ? 10*-mExpandAccelPx : mExpandAccelPx;
}
} else {
mAccel = closing ? -mCollapseAccelPx : mExpandAccelPx;
}
mVel += mAccel * dt;
if (braking) {
if (closing && mVel > -mBrakingSpeedPx) {
mVel = -mBrakingSpeedPx;
} else if (!closing && mVel < mBrakingSpeedPx) {
mVel = mBrakingSpeedPx;
}
} else {
if (closing && mVel > -mFlingCollapseMinVelocityPx) {
mVel = -mFlingCollapseMinVelocityPx;
} else if (!closing && mVel > mFlingGestureMaxOutputVelocityPx) {
mVel = mFlingGestureMaxOutputVelocityPx;
}
}
float h = mExpandedHeight + mVel * dt;
LOG("tick: new h=%d closing=%s", (int) h, closing?"true":"false");
setExpandedHeightInternal(h);
mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
if (mVel == 0
|| (closing && mExpandedHeight == 0)
|| (!closing && mExpandedHeight == getFullHeight())) {
mTimeAnimator.end();
}
}
}
public PanelView(Context context, AttributeSet attrs) {
super(context, attrs);
mTimeAnimator = new TimeAnimator();
mTimeAnimator.setTimeListener(mAnimationCallback);
}
private void loadDimens() {
final Resources res = getContext().getResources();
mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
}
private void trackMovement(MotionEvent event) {
// Add movement to velocity tracker using raw screen X and Y coordinates instead
// of window coordinates because the window frame may be moving at the same time.
float deltaX = event.getRawX() - event.getX();
float deltaY = event.getRawY() - event.getY();
event.offsetLocation(deltaX, deltaY);
mVelocityTracker.addMovement(event);
event.offsetLocation(-deltaX, -deltaY);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
loadDimens();
mHandleView = findViewById(R.id.handle);
LOG("handle view: " + mHandleView);
if (mHandleView != null) {
mHandleView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final float y = event.getY();
final float rawY = event.getRawY();
LOG("handle.onTouch: y=%.1f rawY=%.1f off=%.1f", y, rawY, mTouchOffset);
PanelView.this.getLocationOnScreen(mAbsPos);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mVelocityTracker = VelocityTracker.obtain();
trackMovement(event);
mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight();
break;
case MotionEvent.ACTION_MOVE:
PanelView.this.setExpandedHeight(rawY - mAbsPos[1] - mTouchOffset);
mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
trackMovement(event);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
trackMovement(event);
mVelocityTracker.computeCurrentVelocity(1000);
float yVel = mVelocityTracker.getYVelocity();
boolean negative = yVel < 0;
float xVel = mVelocityTracker.getXVelocity();
if (xVel < 0) {
xVel = -xVel;
}
if (xVel > mFlingGestureMaxXVelocityPx) {
xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
}
float vel = (float)Math.hypot(yVel, xVel);
if (vel > mFlingGestureMaxOutputVelocityPx) {
vel = mFlingGestureMaxOutputVelocityPx;
}
if (negative) {
vel = -vel;
}
LOG("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
mVelocityTracker.getXVelocity(),
mVelocityTracker.getYVelocity(),
xVel, yVel,
vel);
fling(vel, false);
mVelocityTracker.recycle();
mVelocityTracker = null;
break;
}
return true;
}});
}
}
public void fling(float vel, boolean always) {
mVel = vel;
if (mVel != 0) {
animationTick(0); // begin the animation
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onViewAdded(View child) {
LOG("onViewAdded: " + child);
}
public View getHandle() {
return mHandleView;
}
// Rubberbands the panel to hold its contents.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
LOG("onMeasure(%d, %d) -> (%d, %d)",
widthMeasureSpec, heightMeasureSpec, getMeasuredWidth(), getMeasuredHeight());
mFullHeight = getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
(int) mExpandedHeight, MeasureSpec.AT_MOST); // MeasureSpec.getMode(heightMeasureSpec));
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
public void setExpandedHeight(float height) {
mTimeAnimator.end();
setExpandedHeightInternal(height);
}
public void setExpandedHeightInternal(float h) {
float fh = getFullHeight();
if (fh == 0) {
// Hmm, full height hasn't been computed yet
}
LOG("setExpansion: height=%.1f fh=%.1f", h, fh);
if (h < 0) h = 0;
else if (h > fh) h = fh;
mExpandedHeight = h;
requestLayout();
// FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
// lp.height = (int) mExpandedHeight;
// setLayoutParams(lp);
mExpandedFraction = Math.min(1f, h / fh);
}
private float getFullHeight() {
return mFullHeight;
}
public void setExpandedFraction(float frac) {
setExpandedHeight(getFullHeight() * frac);
}
public float getExpandedHeight() {
return mExpandedHeight;
}
public float getExpandedFraction() {
return mExpandedFraction;
}
public void setBar(PanelBar panelBar) {
mBar = panelBar;
}
public void collapse() {
// TODO: abort animation or ongoing touch
if (mExpandedHeight > 0) {
fling(-mSelfCollapseVelocityPx, /*always=*/ true);
}
}
public void expand() {
if (mExpandedHeight < getFullHeight()) {
fling (mSelfExpandVelocityPx, /*always=*/ true);
}
}
}

View File

@@ -52,7 +52,6 @@ import android.service.dreams.IDreamManager;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.Slog; import android.util.Slog;
import android.view.Choreographer;
import android.view.Display; import android.view.Display;
import android.view.Gravity; import android.view.Gravity;
import android.view.IWindowManager; import android.view.IWindowManager;
@@ -77,7 +76,6 @@ import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarNotification; import com.android.internal.statusbar.StatusBarNotification;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.UniverseBackground;
import com.android.systemui.recent.RecentTasksLoader; import com.android.systemui.recent.RecentTasksLoader;
import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
@@ -101,7 +99,7 @@ import java.util.ArrayList;
public class PhoneStatusBar extends BaseStatusBar { public class PhoneStatusBar extends BaseStatusBar {
static final String TAG = "PhoneStatusBar"; static final String TAG = "PhoneStatusBar";
public static final boolean DEBUG = false; public static final boolean DEBUG = true;
public static final boolean SPEW = DEBUG; public static final boolean SPEW = DEBUG;
public static final boolean DUMPTRUCK = true; // extra dumpsys info public static final boolean DUMPTRUCK = true; // extra dumpsys info
@@ -111,7 +109,7 @@ public class PhoneStatusBar extends BaseStatusBar {
public static final String ACTION_STATUSBAR_START public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START"; = "com.android.internal.policy.statusbar.START";
private static final boolean DIM_BEHIND_EXPANDED_PANEL = true; public static final boolean DIM_BEHIND_EXPANDED_PANEL = true;
private static final boolean SHOW_CARRIER_LABEL = true; private static final boolean SHOW_CARRIER_LABEL = true;
private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000; private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
@@ -159,8 +157,6 @@ public class PhoneStatusBar extends BaseStatusBar {
StatusBarWindowView mStatusBarWindow; StatusBarWindowView mStatusBarWindow;
PhoneStatusBarView mStatusBarView; PhoneStatusBarView mStatusBarView;
UniverseBackground mUniverseBackground;
int mPixelFormat; int mPixelFormat;
Object mQueueLock = new Object(); Object mQueueLock = new Object();
@@ -171,7 +167,7 @@ public class PhoneStatusBar extends BaseStatusBar {
LinearLayout mStatusIcons; LinearLayout mStatusIcons;
// expanded notifications // expanded notifications
View mNotificationPanel; // the sliding/resizing panel within the notification window PanelView mNotificationPanel; // the sliding/resizing panel within the notification window
ScrollView mScrollView; ScrollView mScrollView;
View mExpandedContents; View mExpandedContents;
int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx; int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx;
@@ -191,10 +187,6 @@ public class PhoneStatusBar extends BaseStatusBar {
private int mCarrierLabelHeight; private int mCarrierLabelHeight;
private TextView mEmergencyCallLabel; private TextView mEmergencyCallLabel;
// drag bar
CloseDragHandle mCloseView;
private int mCloseViewHeight;
// position // position
int[] mPositionTmp = new int[2]; int[] mPositionTmp = new int[2];
boolean mExpanded; boolean mExpanded;
@@ -222,7 +214,6 @@ public class PhoneStatusBar extends BaseStatusBar {
boolean mTracking; boolean mTracking;
VelocityTracker mVelocityTracker; VelocityTracker mVelocityTracker;
Choreographer mChoreographer;
boolean mAnimating; boolean mAnimating;
boolean mClosing; // only valid when mAnimating; indicates the initial acceleration boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
float mAnimY; float mAnimY;
@@ -262,40 +253,6 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
}; };
private final Runnable mStartRevealAnimation = new Runnable() {
@Override
public void run() {
mAnimAccel = mExpandAccelPx;
mAnimVel = mFlingExpandMinVelocityPx;
mAnimY = getStatusBarHeight();
updateExpandedViewPos((int)mAnimY);
mAnimating = true;
mAnimatingReveal = true;
resetLastAnimTime();
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
mAnimationCallback, null);
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
mRevealAnimationCallback, null);
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
mRevealAnimationCallback, null);
}
};
private final Runnable mPerformSelfExpandFling = new Runnable() {
@Override
public void run() {
performFling(0, mSelfExpandVelocityPx, true);
}
};
private final Runnable mPerformFling = new Runnable() {
@Override
public void run() {
performFling(mFlingY + mViewDelta, mFlingVelocity, false);
}
};
@Override @Override
public void start() { public void start() {
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
@@ -313,11 +270,6 @@ public class PhoneStatusBar extends BaseStatusBar {
if (ENABLE_INTRUDERS) addIntruderView(); if (ENABLE_INTRUDERS) addIntruderView();
mUniverseBackground = new UniverseBackground(mContext);
mUniverseBackground.setVisibility(View.GONE);
WindowManagerImpl.getDefault().addView(mUniverseBackground,
mUniverseBackground.getLayoutParams(mDisplay));
// Lastly, call to the icon policy to install/update all the icons. // Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext); mIconPolicy = new PhoneStatusBarPolicy(mContext);
} }
@@ -353,7 +305,12 @@ public class PhoneStatusBar extends BaseStatusBar {
}}); }});
mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar); mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel); mStatusBarView.setBar(this);
PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
mStatusBarView.setPanelHolder(holder);
mNotificationPanel = (PanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
// don't allow clicks on the panel to pass through to the background where they will cause the panel to close // don't allow clicks on the panel to pass through to the background where they will cause the panel to close
mNotificationPanel.setOnTouchListener(new View.OnTouchListener() { mNotificationPanel.setOnTouchListener(new View.OnTouchListener() {
@Override @Override
@@ -380,10 +337,6 @@ public class PhoneStatusBar extends BaseStatusBar {
updateShowSearchHoldoff(); updateShowSearchHoldoff();
mStatusBarView.mService = this;
mChoreographer = Choreographer.getInstance();
try { try {
boolean showNav = mWindowManager.hasNavigationBar(); boolean showNav = mWindowManager.hasNavigationBar();
if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav); if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
@@ -429,10 +382,6 @@ public class PhoneStatusBar extends BaseStatusBar {
TickerView tickerView = (TickerView)mStatusBarView.findViewById(R.id.tickerText); TickerView tickerView = (TickerView)mStatusBarView.findViewById(R.id.tickerText);
tickerView.mTicker = mTicker; tickerView.mTicker = mTicker;
mCloseView = (CloseDragHandle)mStatusBarWindow.findViewById(R.id.close);
mCloseView.mService = this;
mCloseViewHeight = res.getDimensionPixelSize(R.dimen.close_handle_height);
mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore); mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
// set the inital view visibility // set the inital view visibility
@@ -597,10 +546,6 @@ public class PhoneStatusBar extends BaseStatusBar {
return mNaturalBarHeight; return mNaturalBarHeight;
} }
private int getCloseViewHeight() {
return mCloseViewHeight;
}
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() { private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
toggleRecentApps(); toggleRecentApps();
@@ -1169,20 +1114,6 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
} }
final Runnable mAnimationCallback = new Runnable() {
@Override
public void run() {
doAnimation(mChoreographer.getFrameTimeNanos());
}
};
final Runnable mRevealAnimationCallback = new Runnable() {
@Override
public void run() {
doRevealAnimation(mChoreographer.getFrameTimeNanos());
}
};
View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() { View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) { public void onFocusChange(View v, boolean hasFocus) {
// Because 'v' is a ViewGroup, all its children will be (un)selected // Because 'v' is a ViewGroup, all its children will be (un)selected
@@ -1191,7 +1122,7 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
}; };
private void makeExpandedVisible(boolean revealAfterDraw) { void makeExpandedVisible(boolean revealAfterDraw) {
if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
if (mExpandedVisible) { if (mExpandedVisible) {
return; return;
@@ -1218,34 +1149,17 @@ public class PhoneStatusBar extends BaseStatusBar {
// Updating the window layout will force an expensive traversal/redraw. // Updating the window layout will force an expensive traversal/redraw.
// Kick off the reveal animation after this is complete to avoid animation latency. // Kick off the reveal animation after this is complete to avoid animation latency.
if (revealAfterDraw) { if (revealAfterDraw) {
mHandler.post(mStartRevealAnimation); // mHandler.post(mStartRevealAnimation);
} }
visibilityChanged(true); visibilityChanged(true);
} }
public void animateExpand() {
if (SPEW) Slog.d(TAG, "Animate expand: expanded=" + mExpanded);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return ;
}
if (mExpanded) {
return;
}
prepareTracking(0, true);
mHandler.post(mPerformSelfExpandFling);
}
public void animateCollapse() { public void animateCollapse() {
animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE); animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
} }
public void animateCollapse(int flags) { public void animateCollapse(int flags) {
animateCollapse(flags, 1.0f);
}
public void animateCollapse(int flags, float velocityMultiplier) {
if (SPEW) { if (SPEW) {
Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+ " mExpandedVisible=" + mExpandedVisible + " mExpandedVisible=" + mExpandedVisible
@@ -1267,41 +1181,23 @@ public class PhoneStatusBar extends BaseStatusBar {
mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL); mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
} }
if (!mExpandedVisible) { mStatusBarView.collapseAllPanels(true);
return;
}
int y;
if (mAnimating || mAnimatingReveal) {
y = (int)mAnimY;
} else {
y = getExpandedViewMaxHeight()-1;
}
// Let the fling think that we're open so it goes in the right direction
// and doesn't try to re-open the windowshade.
mExpanded = true;
prepareTracking(y, false);
performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
} }
void performExpand() { @Override
if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded); public void animateExpand() {
if (SPEW) Slog.d(TAG, "animateExpand: mExpanded=" + mExpanded);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) { if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return ; return ;
} }
if (mExpanded) {
return;
}
mExpanded = true; mNotificationPanel.expand();
makeExpandedVisible(false);
updateExpandedViewPos(EXPANDED_FULL_OPEN);
if (false) postStartTracing(); if (false) postStartTracing();
} }
void performCollapse() { void makeExpandedInvisible() {
if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpanded=" + mExpanded
+ " mExpandedVisible=" + mExpandedVisible); + " mExpandedVisible=" + mExpandedVisible);
if (!mExpandedVisible) { if (!mExpandedVisible) {
@@ -1309,7 +1205,7 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
// Ensure the panel is fully collapsed (just in case; bug 6765842) // Ensure the panel is fully collapsed (just in case; bug 6765842)
updateExpandedViewPos(0); mStatusBarView.collapseAllPanels(/*animate=*/ false);
mExpandedVisible = false; mExpandedVisible = false;
mPile.setLayoutTransitionsEnabled(false); mPile.setLayoutTransitionsEnabled(false);
@@ -1343,67 +1239,6 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
} }
void resetLastAnimTime() {
mAnimLastTimeNanos = System.nanoTime();
if (SPEW) {
Throwable t = new Throwable();
t.fillInStackTrace();
Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
}
}
void doAnimation(long frameTimeNanos) {
if (mAnimating) {
if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
incrementAnim(frameTimeNanos);
if (SPEW) {
Slog.d(TAG, "doAnimation after mAnimY=" + mAnimY);
Slog.d(TAG, "doAnimation expandedViewMax=" + getExpandedViewMaxHeight());
}
if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
mAnimating = false;
updateExpandedViewPos(EXPANDED_FULL_OPEN);
performExpand();
return;
}
if (mAnimY == 0 && mAnimAccel == 0 && mClosing) {
if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
mAnimating = false;
performCollapse();
return;
}
if (mAnimY < getStatusBarHeight() && mClosing) {
// Draw one more frame with the bar positioned at the top of the screen
// before ending the animation so that the user sees the bar in
// its final position. The call to performCollapse() causes a window
// relayout which takes time and might cause the animation to skip
// on the very last frame before the bar disappears if we did it now.
mAnimY = 0;
mAnimAccel = 0;
mAnimVel = 0;
}
updateExpandedViewPos((int)mAnimY);
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
mAnimationCallback, null);
}
}
void stopTracking() {
if (!mTracking)
return;
mTracking = false;
setPileLayers(View.LAYER_TYPE_NONE);
mVelocityTracker.recycle();
mVelocityTracker = null;
mCloseView.setPressed(false);
}
/** /**
* Enables or disables layers on the children of the notifications pile. * Enables or disables layers on the children of the notifications pile.
* *
@@ -1451,148 +1286,6 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
} }
void incrementAnim(long frameTimeNanos) {
final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
final float t = deltaNanos * 0.000000001f; // ns -> s
final float y = mAnimY;
final float v = mAnimVel; // px/s
final float a = mAnimAccel; // px/s/s
mAnimY = y + (v*t) + (0.5f*a*t*t); // px
mAnimVel = v + (a*t); // px/s
mAnimLastTimeNanos = frameTimeNanos; // ns
//Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
// + " mAnimAccel=" + mAnimAccel);
}
void doRevealAnimation(long frameTimeNanos) {
if (SPEW) {
Slog.d(TAG, "doRevealAnimation: dt=" + (frameTimeNanos - mAnimLastTimeNanos));
}
final int h = mNotificationPanelMinHeight;
if (mAnimatingReveal && mAnimating && mAnimY < h) {
incrementAnim(frameTimeNanos);
if (mAnimY >= h) {
mAnimY = h;
updateExpandedViewPos((int)mAnimY);
} else {
updateExpandedViewPos((int)mAnimY);
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
mRevealAnimationCallback, null);
}
}
}
void prepareTracking(int y, boolean opening) {
if (CHATTY) {
Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
}
mCloseView.setPressed(true);
mTracking = true;
setPileLayers(View.LAYER_TYPE_HARDWARE);
mVelocityTracker = VelocityTracker.obtain();
if (opening) {
makeExpandedVisible(true);
} else {
// it's open, close it?
if (mAnimating) {
mAnimating = false;
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
mAnimationCallback, null);
}
updateExpandedViewPos(y + mViewDelta);
}
}
void performFling(int y, float vel, boolean always) {
if (CHATTY) {
Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel + " mExpanded=" + mExpanded);
}
mAnimatingReveal = false;
mAnimY = y;
mAnimVel = vel;
//Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
if (mExpanded) {
if (!always && (
vel > mFlingCollapseMinVelocityPx
|| (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
vel > -mFlingExpandMinVelocityPx))) {
// We are expanded, but they didn't move sufficiently to cause
// us to retract. Animate back to the expanded position.
mAnimAccel = mExpandAccelPx;
if (vel < 0) {
mAnimVel = 0;
}
}
else {
// We are expanded and are now going to animate away.
mAnimAccel = -mCollapseAccelPx;
if (vel > 0) {
mAnimVel = 0;
}
}
} else {
if (always || (
vel > mFlingExpandMinVelocityPx
|| (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
vel > -mFlingCollapseMinVelocityPx))) {
// We are collapsed, and they moved enough to allow us to
// expand. Animate in the notifications.
mAnimAccel = mExpandAccelPx;
if (vel < 0) {
mAnimVel = 0;
}
}
else {
// We are collapsed, but they didn't move sufficiently to cause
// us to retract. Animate back to the collapsed position.
mAnimAccel = -mCollapseAccelPx;
if (vel > 0) {
mAnimVel = 0;
}
}
}
//Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
// + " mAnimAccel=" + mAnimAccel);
resetLastAnimTime();
mAnimating = true;
mClosing = mAnimAccel < 0;
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
mAnimationCallback, null);
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
mRevealAnimationCallback, null);
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
mAnimationCallback, null);
stopTracking();
}
boolean handleUniverseEvent(MotionEvent event) {
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return false;
}
if (mExpanded) {
return false;
}
if (mUniverseBackground.consumeEvent(event)) {
if (mTracking) {
// fling back to the top, starting from the last tracked position.
mFlingY = mTrackingPosition;
mViewDelta = 0;
mFlingVelocity = -1;
mHandler.post(mPerformFling);
}
return true;
}
return false;
}
boolean interceptTouchEvent(MotionEvent event) { boolean interceptTouchEvent(MotionEvent event) {
if (SPEW) { if (SPEW) {
Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled=" Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
@@ -1612,104 +1305,11 @@ public class PhoneStatusBar extends BaseStatusBar {
return false; return false;
} }
final int y = (int)event.getRawY();
final int action = event.getAction();
final int statusBarSize = getStatusBarHeight();
final int hitSize = statusBarSize*2;
if (action == MotionEvent.ACTION_DOWN) {
if (!areLightsOn()) {
setLightsOn(true);
}
if (!mExpanded) {
mViewDelta = statusBarSize - y;
} else {
mCloseView.getLocationOnScreen(mAbsPos);
mViewDelta = mAbsPos[1]
+ getCloseViewHeight() // XXX: not closeViewHeight, but paddingBottom from the 9patch
+ mNotificationPanelBackgroundPadding.top
+ mNotificationPanelBackgroundPadding.bottom
- y;
}
if ((!mExpanded && y < hitSize) ||
// @@ add taps outside the panel if it's not full-screen
(mExpanded && y > (getExpandedViewMaxHeight()-hitSize))) {
// We drop events at the edge of the screen to make the windowshade come
// down by accident less, especially when pushing open a device with a keyboard
// that rotates (like g1 and droid)
int x = (int)event.getRawX();
final int edgeBorder = mEdgeBorder;
if (x >= edgeBorder && x < mDisplayMetrics.widthPixels - edgeBorder) {
prepareTracking(y, !mExpanded);// opening if we're not already fully visible
trackMovement(event);
mGestureRec.tag("tracking", mExpanded ? "expanded" : "collapsed");
}
}
} else if (mTracking) {
trackMovement(event);
if (action == MotionEvent.ACTION_MOVE) {
if (mAnimatingReveal && (y + mViewDelta) < mNotificationPanelMinHeight) {
// nothing
} else {
mAnimatingReveal = false;
updateExpandedViewPos(y + mViewDelta);
}
} else if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL) {
mVelocityTracker.computeCurrentVelocity(1000);
float yVel = mVelocityTracker.getYVelocity();
boolean negative = yVel < 0;
float xVel = mVelocityTracker.getXVelocity();
if (xVel < 0) {
xVel = -xVel;
}
if (xVel > mFlingGestureMaxXVelocityPx) {
xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
}
float vel = (float)Math.hypot(yVel, xVel);
if (vel > mFlingGestureMaxOutputVelocityPx) {
vel = mFlingGestureMaxOutputVelocityPx;
}
if (negative) {
vel = -vel;
}
if (CHATTY) {
Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
mVelocityTracker.getXVelocity(),
mVelocityTracker.getYVelocity(),
xVel, yVel,
vel));
}
if (mTrackingPosition == mNotificationPanelMinHeight) {
// start the fling from the tracking position, ignore y and view delta
mFlingY = mTrackingPosition;
mViewDelta = 0;
} else {
mFlingY = y;
}
mFlingVelocity = vel;
mGestureRec.tag("fling " + ((mFlingVelocity > 0) ? "open" : "closed"),
"v=" + mFlingVelocity);
mHandler.post(mPerformFling);
}
}
return false; return false;
} }
private void trackMovement(MotionEvent event) { public GestureRecorder getGestureRecorder() {
// Add movement to velocity tracker using raw screen X and Y coordinates instead return mGestureRec;
// of window coordinates because the window frame may be moving at the same time.
float deltaX = event.getRawX() - event.getX();
float deltaY = event.getRawY() - event.getY();
event.offsetLocation(deltaX, deltaY);
mVelocityTracker.addMovement(event);
event.offsetLocation(-deltaX, -deltaY);
} }
@Override // CommandQueue @Override // CommandQueue
@@ -1930,7 +1530,6 @@ public class PhoneStatusBar extends BaseStatusBar {
+ " mViewDelta=" + mViewDelta); + " mViewDelta=" + mViewDelta);
pw.println(" mDisplayMetrics=" + mDisplayMetrics); pw.println(" mDisplayMetrics=" + mDisplayMetrics);
pw.println(" mPile: " + viewInfo(mPile)); pw.println(" mPile: " + viewInfo(mPile));
pw.println(" mCloseView: " + viewInfo(mCloseView));
pw.println(" mTickerView: " + viewInfo(mTickerView)); pw.println(" mTickerView: " + viewInfo(mTickerView));
pw.println(" mScrollView: " + viewInfo(mScrollView) pw.println(" mScrollView: " + viewInfo(mScrollView)
+ " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY()); + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
@@ -2039,83 +1638,13 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
@Override @Override
protected void updateExpandedViewPos(int expandedPosition) { public void updateExpandedViewPos(int thingy) {
if (SPEW) { // TODO
Slog.d(TAG, "updateExpandedViewPos: expandedPosition=" + expandedPosition if (DEBUG) Slog.v(TAG, "updateExpandedViewPos");
//+ " mTrackingParams.y=" + ((mTrackingParams == null) ? "?" : mTrackingParams.y)
+ " mTracking=" + mTracking
+ " mTrackingPosition=" + mTrackingPosition
+ " mExpandedVisible=" + mExpandedVisible
+ " mAnimating=" + mAnimating
+ " mAnimatingReveal=" + mAnimatingReveal
+ " mClosing=" + mClosing
+ " gravity=" + mNotificationPanelGravity);
}
int panelh = 0;
final int disph = getExpandedViewMaxHeight();
// If the expanded view is not visible, make sure they're still off screen.
// Maybe the view was resized.
if (!mExpandedVisible) {
if (SPEW) Slog.d(TAG, "updateExpandedViewPos: view not visible, bailing");
updateExpandedInvisiblePosition();
return;
}
// tracking view...
if (expandedPosition == EXPANDED_FULL_OPEN) {
panelh = disph;
}
else if (expandedPosition == EXPANDED_LEAVE_ALONE) {
panelh = mTrackingPosition;
}
else {
if (expandedPosition <= disph) {
panelh = expandedPosition;
} else {
panelh = disph;
}
}
// catch orientation changes and other peculiar cases
if (panelh > 0 &&
((panelh > disph) ||
(panelh < disph && !mTracking && !mAnimating))) {
if (SPEW) Slog.d(TAG, "updateExpandedViewPos: orientation change?");
panelh = disph;
} else if (panelh < 0) {
panelh = 0;
}
if (SPEW) Slog.d(TAG, "updateExpandedViewPos: adjusting size to panelh=" + panelh);
if (panelh == mTrackingPosition) {
if (SPEW) Slog.d(TAG, "updateExpandedViewPos: panelh == mTrackingPosition, bailing");
return;
}
mTrackingPosition = panelh;
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams(); FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams();
lp.height = panelh;
lp.gravity = mNotificationPanelGravity; lp.gravity = mNotificationPanelGravity;
lp.leftMargin = mNotificationPanelMarginLeftPx; lp.leftMargin = mNotificationPanelMarginLeftPx;
if (SPEW) {
Slog.v(TAG, "updated cropView height=" + panelh + " grav=" + lp.gravity);
}
mNotificationPanel.setLayoutParams(lp); mNotificationPanel.setLayoutParams(lp);
final int barh = getCloseViewHeight() + getStatusBarHeight();
final float frac = saturate((float)(panelh - barh) / (disph - barh));
if (DIM_BEHIND_EXPANDED_PANEL && ActivityManager.isHighEndGfx(mDisplay)) {
// woo, special effects
final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
final int color = ((int)(0xB0 * k)) << 24;
mStatusBarWindow.setBackgroundColor(color);
}
updateCarrierLabelVisibility(false);
} }
// called by makeStatusbar and also by PhoneStatusBarView // called by makeStatusbar and also by PhoneStatusBarView
@@ -2264,7 +1793,7 @@ public class PhoneStatusBar extends BaseStatusBar {
} }
else if (Intent.ACTION_SCREEN_OFF.equals(action)) { else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
// no waiting! // no waiting!
performCollapse(); makeExpandedInvisible();
} }
else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) { else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
updateResources(); updateResources();

View File

@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone; package com.android.systemui.statusbar.phone;
import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Canvas; import android.graphics.Canvas;
@@ -35,133 +36,16 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.policy.FixedSizeDrawable; import com.android.systemui.statusbar.policy.FixedSizeDrawable;
public class PhoneStatusBarView extends FrameLayout { public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView"; private static final String TAG = "PhoneStatusBarView";
PhoneStatusBar mBar;
static final int DIM_ANIM_TIME = 400;
PhoneStatusBar mService;
boolean mTracking;
int mStartX, mStartY;
ViewGroup mNotificationIcons;
ViewGroup mStatusIcons;
boolean mNightMode = false;
int mStartAlpha = 0, mEndAlpha = 0;
long mEndTime = 0;
Rect mButtonBounds = new Rect();
boolean mCapturingEvents = true;
public PhoneStatusBarView(Context context, AttributeSet attrs) { public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
@Override public void setBar(PhoneStatusBar bar) {
protected void onFinishInflate() { mBar = bar;
super.onFinishInflate();
mNotificationIcons = (ViewGroup)findViewById(R.id.notificationIcons);
mStatusIcons = (ViewGroup)findViewById(R.id.statusIcons);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//mService.onBarViewAttached();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mService.updateDisplaySize();
boolean nightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
== Configuration.UI_MODE_NIGHT_YES;
if (mNightMode != nightMode) {
mNightMode = nightMode;
mStartAlpha = getCurAlpha();
mEndAlpha = mNightMode ? 0x80 : 0x00;
mEndTime = SystemClock.uptimeMillis() + DIM_ANIM_TIME;
invalidate();
}
}
int getCurAlpha() {
long time = SystemClock.uptimeMillis();
if (time > mEndTime) {
return mEndAlpha;
}
return mEndAlpha
- (int)(((mEndAlpha-mStartAlpha) * (mEndTime-time) / DIM_ANIM_TIME));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mService.updateExpandedViewPos(BaseStatusBar.EXPANDED_LEAVE_ALONE);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
int alpha = getCurAlpha();
if (alpha != 0) {
canvas.drawARGB(alpha, 0, 0, 0);
}
if (alpha != mEndAlpha) {
invalidate();
}
}
/**
* Gets the left position of v in this view. Throws if v is not
* a child of this.
*/
private int getViewOffset(View v) {
int offset = 0;
while (v != this) {
offset += v.getLeft();
ViewParent p = v.getParent();
if (v instanceof View) {
v = (View)p;
} else {
throw new RuntimeException(v + " is not a child of " + this);
}
}
return offset;
}
/**
* Ensure that, if there is no target under us to receive the touch,
* that we process it ourself. This makes sure that onInterceptTouchEvent()
* is always called for the entire gesture.
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mCapturingEvents) {
return false;
}
if (event.getAction() != MotionEvent.ACTION_DOWN) {
mService.interceptTouchEvent(event);
}
return true;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mButtonBounds.contains((int)event.getX(), (int)event.getY())) {
mCapturingEvents = false;
return false;
}
}
mCapturingEvents = true;
return mService.interceptTouchEvent(event)
? true : super.onInterceptTouchEvent(event);
} }
@Override @Override
@@ -178,4 +62,42 @@ public class PhoneStatusBarView extends FrameLayout {
} }
return false; return false;
} }
@Override
public void onPanelPeeked() {
super.onPanelPeeked();
mBar.makeExpandedVisible(true);
}
@Override
public void onAllPanelsCollapsed() {
super.onAllPanelsCollapsed();
mBar.makeExpandedInvisible();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return mBar.interceptTouchEvent(event) || super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event);
}
@Override
public void panelExpansionChanged(PanelView pv, float frac) {
super.panelExpansionChanged(pv, frac);
if (PhoneStatusBar.DIM_BEHIND_EXPANDED_PANEL && ActivityManager.isHighEndGfx(mBar.mDisplay)) {
// woo, special effects
final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
final int color = ((int)(0xB0 * k)) << 24;
mBar.mStatusBarWindow.setBackgroundColor(color);
}
mBar.updateCarrierLabelVisibility(false);
}
} }

View File

@@ -37,8 +37,6 @@ public class StatusBarWindowView extends FrameLayout
private ExpandHelper mExpandHelper; private ExpandHelper mExpandHelper;
private NotificationRowLayout latestItems; private NotificationRowLayout latestItems;
private boolean mUniverseHandling = false;
PhoneStatusBar mService; PhoneStatusBar mService;
public StatusBarWindowView(Context context, AttributeSet attrs) { public StatusBarWindowView(Context context, AttributeSet attrs) {
@@ -73,16 +71,6 @@ public class StatusBarWindowView extends FrameLayout
@Override @Override
public boolean onInterceptTouchEvent(MotionEvent ev) { public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mService.handleUniverseEvent(ev)) {
mUniverseHandling = true;
MotionEvent cancellation = MotionEvent.obtain(ev);
cancellation.setAction(MotionEvent.ACTION_CANCEL);
mExpandHelper.onInterceptTouchEvent(cancellation);
latestItems.onInterceptTouchEvent(cancellation);
cancellation.recycle();
return true;
}
boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) || boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) ||
super.onInterceptTouchEvent(ev); super.onInterceptTouchEvent(ev);
if (intercept) { if (intercept) {
@@ -96,12 +84,6 @@ public class StatusBarWindowView extends FrameLayout
@Override @Override
public boolean onTouchEvent(MotionEvent ev) { public boolean onTouchEvent(MotionEvent ev) {
if (mUniverseHandling) {
if (!mService.handleUniverseEvent(ev)) {
mUniverseHandling = false;
}
return true;
}
boolean handled = mExpandHelper.onTouchEvent(ev) || boolean handled = mExpandHelper.onTouchEvent(ev) ||
super.onTouchEvent(ev); super.onTouchEvent(ev);
return handled; return handled;

View File

@@ -34,6 +34,7 @@ import android.text.style.RelativeSizeSpan;
import android.text.style.RelativeSizeSpan; import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Slog;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
@@ -173,7 +174,6 @@ public class Clock extends TextView {
+ "a" + MAGIC2 + format.substring(b + 1); + "a" + MAGIC2 + format.substring(b + 1);
} }
} }
mClockFormat = sdf = new SimpleDateFormat(format); mClockFormat = sdf = new SimpleDateFormat(format);
mClockFormatString = format; mClockFormatString = format;
} else { } else {