Merge "New status bar capable of multiple sliding panels." into jb-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a6aef1bbb4
@@ -12,6 +12,12 @@ public class TimeAnimator extends ValueAnimator {
|
||||
private TimeListener mListener;
|
||||
private long mPreviousTime = -1;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
mPreviousTime = -1;
|
||||
super.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean animationFrame(long currentTime) {
|
||||
if (mListener != null) {
|
||||
|
||||
@@ -31,10 +31,16 @@
|
||||
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>
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
*/
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
<com.android.systemui.statusbar.phone.NotificationPanelView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
|
||||
android:id="@+id/notification_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/notification_panel_bg"
|
||||
android:paddingTop="@dimen/notification_panel_padding_top"
|
||||
android:layout_marginLeft="@dimen/notification_panel_margin_left"
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/close_handle_underlap"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
@@ -65,7 +65,7 @@
|
||||
<ScrollView
|
||||
android:id="@+id/scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fadingEdge="none"
|
||||
android:overScrollMode="always"
|
||||
>
|
||||
@@ -78,7 +78,7 @@
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
<com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close"
|
||||
<LinearLayout android:id="@+id/handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/close_handle_height"
|
||||
android:layout_gravity="bottom"
|
||||
@@ -91,6 +91,5 @@
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/status_bar_close"
|
||||
/>
|
||||
|
||||
</com.android.systemui.statusbar.phone.CloseDragHandle>
|
||||
</FrameLayout><!-- end of sliding panel -->
|
||||
</LinearLayout>
|
||||
</com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
|
||||
|
||||
@@ -32,9 +32,15 @@
|
||||
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_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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,6 @@ import android.service.dreams.IDreamManager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
import android.view.IWindowManager;
|
||||
@@ -77,7 +76,6 @@ import android.widget.TextView;
|
||||
import com.android.internal.statusbar.StatusBarIcon;
|
||||
import com.android.internal.statusbar.StatusBarNotification;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.UniverseBackground;
|
||||
import com.android.systemui.recent.RecentTasksLoader;
|
||||
import com.android.systemui.statusbar.BaseStatusBar;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
@@ -101,7 +99,7 @@ import java.util.ArrayList;
|
||||
|
||||
public class PhoneStatusBar extends BaseStatusBar {
|
||||
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 DUMPTRUCK = true; // extra dumpsys info
|
||||
|
||||
@@ -111,7 +109,7 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
public static final String ACTION_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 int MSG_OPEN_NOTIFICATION_PANEL = 1000;
|
||||
@@ -159,8 +157,6 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
StatusBarWindowView mStatusBarWindow;
|
||||
PhoneStatusBarView mStatusBarView;
|
||||
|
||||
UniverseBackground mUniverseBackground;
|
||||
|
||||
int mPixelFormat;
|
||||
Object mQueueLock = new Object();
|
||||
|
||||
@@ -171,7 +167,7 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
LinearLayout mStatusIcons;
|
||||
|
||||
// expanded notifications
|
||||
View mNotificationPanel; // the sliding/resizing panel within the notification window
|
||||
PanelView mNotificationPanel; // the sliding/resizing panel within the notification window
|
||||
ScrollView mScrollView;
|
||||
View mExpandedContents;
|
||||
int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx;
|
||||
@@ -191,10 +187,6 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
private int mCarrierLabelHeight;
|
||||
private TextView mEmergencyCallLabel;
|
||||
|
||||
// drag bar
|
||||
CloseDragHandle mCloseView;
|
||||
private int mCloseViewHeight;
|
||||
|
||||
// position
|
||||
int[] mPositionTmp = new int[2];
|
||||
boolean mExpanded;
|
||||
@@ -222,7 +214,6 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
boolean mTracking;
|
||||
VelocityTracker mVelocityTracker;
|
||||
|
||||
Choreographer mChoreographer;
|
||||
boolean mAnimating;
|
||||
boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
|
||||
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
|
||||
public void start() {
|
||||
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
|
||||
@@ -313,11 +270,6 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
|
||||
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.
|
||||
mIconPolicy = new PhoneStatusBarPolicy(mContext);
|
||||
}
|
||||
@@ -353,7 +305,12 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
}});
|
||||
|
||||
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
|
||||
mNotificationPanel.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
@@ -380,10 +337,6 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
|
||||
updateShowSearchHoldoff();
|
||||
|
||||
mStatusBarView.mService = this;
|
||||
|
||||
mChoreographer = Choreographer.getInstance();
|
||||
|
||||
try {
|
||||
boolean showNav = mWindowManager.hasNavigationBar();
|
||||
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.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);
|
||||
|
||||
// set the inital view visibility
|
||||
@@ -597,10 +546,6 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
return mNaturalBarHeight;
|
||||
}
|
||||
|
||||
private int getCloseViewHeight() {
|
||||
return mCloseViewHeight;
|
||||
}
|
||||
|
||||
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
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() {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
// 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 (mExpandedVisible) {
|
||||
return;
|
||||
@@ -1218,34 +1149,17 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
// Updating the window layout will force an expensive traversal/redraw.
|
||||
// Kick off the reveal animation after this is complete to avoid animation latency.
|
||||
if (revealAfterDraw) {
|
||||
mHandler.post(mStartRevealAnimation);
|
||||
// mHandler.post(mStartRevealAnimation);
|
||||
}
|
||||
|
||||
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() {
|
||||
animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
|
||||
}
|
||||
|
||||
public void animateCollapse(int flags) {
|
||||
animateCollapse(flags, 1.0f);
|
||||
}
|
||||
|
||||
public void animateCollapse(int flags, float velocityMultiplier) {
|
||||
if (SPEW) {
|
||||
Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
|
||||
+ " mExpandedVisible=" + mExpandedVisible
|
||||
@@ -1267,41 +1181,23 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
|
||||
}
|
||||
|
||||
if (!mExpandedVisible) {
|
||||
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);
|
||||
mStatusBarView.collapseAllPanels(true);
|
||||
}
|
||||
|
||||
void performExpand() {
|
||||
if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
|
||||
@Override
|
||||
public void animateExpand() {
|
||||
if (SPEW) Slog.d(TAG, "animateExpand: mExpanded=" + mExpanded);
|
||||
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
|
||||
return ;
|
||||
}
|
||||
if (mExpanded) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExpanded = true;
|
||||
makeExpandedVisible(false);
|
||||
updateExpandedViewPos(EXPANDED_FULL_OPEN);
|
||||
mNotificationPanel.expand();
|
||||
|
||||
if (false) postStartTracing();
|
||||
}
|
||||
|
||||
void performCollapse() {
|
||||
if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
|
||||
void makeExpandedInvisible() {
|
||||
if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpanded=" + mExpanded
|
||||
+ " mExpandedVisible=" + mExpandedVisible);
|
||||
|
||||
if (!mExpandedVisible) {
|
||||
@@ -1309,7 +1205,7 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
}
|
||||
|
||||
// Ensure the panel is fully collapsed (just in case; bug 6765842)
|
||||
updateExpandedViewPos(0);
|
||||
mStatusBarView.collapseAllPanels(/*animate=*/ false);
|
||||
|
||||
mExpandedVisible = 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.
|
||||
*
|
||||
@@ -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) {
|
||||
if (SPEW) {
|
||||
Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
|
||||
@@ -1612,104 +1305,11 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
public GestureRecorder getGestureRecorder() {
|
||||
return mGestureRec;
|
||||
}
|
||||
|
||||
@Override // CommandQueue
|
||||
@@ -1930,7 +1530,6 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
+ " mViewDelta=" + mViewDelta);
|
||||
pw.println(" mDisplayMetrics=" + mDisplayMetrics);
|
||||
pw.println(" mPile: " + viewInfo(mPile));
|
||||
pw.println(" mCloseView: " + viewInfo(mCloseView));
|
||||
pw.println(" mTickerView: " + viewInfo(mTickerView));
|
||||
pw.println(" mScrollView: " + viewInfo(mScrollView)
|
||||
+ " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
|
||||
@@ -2039,83 +1638,13 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateExpandedViewPos(int expandedPosition) {
|
||||
if (SPEW) {
|
||||
Slog.d(TAG, "updateExpandedViewPos: expandedPosition=" + expandedPosition
|
||||
//+ " 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;
|
||||
|
||||
public void updateExpandedViewPos(int thingy) {
|
||||
// TODO
|
||||
if (DEBUG) Slog.v(TAG, "updateExpandedViewPos");
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams();
|
||||
lp.height = panelh;
|
||||
lp.gravity = mNotificationPanelGravity;
|
||||
lp.leftMargin = mNotificationPanelMarginLeftPx;
|
||||
if (SPEW) {
|
||||
Slog.v(TAG, "updated cropView height=" + panelh + " grav=" + lp.gravity);
|
||||
}
|
||||
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
|
||||
@@ -2264,7 +1793,7 @@ public class PhoneStatusBar extends BaseStatusBar {
|
||||
}
|
||||
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
|
||||
// no waiting!
|
||||
performCollapse();
|
||||
makeExpandedInvisible();
|
||||
}
|
||||
else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
|
||||
updateResources();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
@@ -35,133 +36,16 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.BaseStatusBar;
|
||||
import com.android.systemui.statusbar.policy.FixedSizeDrawable;
|
||||
|
||||
public class PhoneStatusBarView extends FrameLayout {
|
||||
public class PhoneStatusBarView extends PanelBar {
|
||||
private static final String TAG = "PhoneStatusBarView";
|
||||
|
||||
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;
|
||||
PhoneStatusBar mBar;
|
||||
|
||||
public PhoneStatusBarView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
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);
|
||||
public void setBar(PhoneStatusBar bar) {
|
||||
mBar = bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,4 +62,42 @@ public class PhoneStatusBarView extends FrameLayout {
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ public class StatusBarWindowView extends FrameLayout
|
||||
private ExpandHelper mExpandHelper;
|
||||
private NotificationRowLayout latestItems;
|
||||
|
||||
private boolean mUniverseHandling = false;
|
||||
|
||||
PhoneStatusBar mService;
|
||||
|
||||
public StatusBarWindowView(Context context, AttributeSet attrs) {
|
||||
@@ -73,16 +71,6 @@ public class StatusBarWindowView extends FrameLayout
|
||||
|
||||
@Override
|
||||
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) ||
|
||||
super.onInterceptTouchEvent(ev);
|
||||
if (intercept) {
|
||||
@@ -96,12 +84,6 @@ public class StatusBarWindowView extends FrameLayout
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (mUniverseHandling) {
|
||||
if (!mService.handleUniverseEvent(ev)) {
|
||||
mUniverseHandling = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
boolean handled = mExpandHelper.onTouchEvent(ev) ||
|
||||
super.onTouchEvent(ev);
|
||||
return handled;
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.text.style.RelativeSizeSpan;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Slog;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -173,7 +174,6 @@ public class Clock extends TextView {
|
||||
+ "a" + MAGIC2 + format.substring(b + 1);
|
||||
}
|
||||
}
|
||||
|
||||
mClockFormat = sdf = new SimpleDateFormat(format);
|
||||
mClockFormatString = format;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user