diff options
Diffstat (limited to 'packages')
23 files changed, 661 insertions, 581 deletions
diff --git a/packages/SystemUI/res/layout-sw600dp/heads_up.xml b/packages/SystemUI/res/layout-sw600dp/heads_up.xml index 71f7c21..f7035fe 100644 --- a/packages/SystemUI/res/layout-sw600dp/heads_up.xml +++ b/packages/SystemUI/res/layout-sw600dp/heads_up.xml @@ -25,7 +25,6 @@ android:id="@+id/content_holder" android:layout_height="wrap_content" android:layout_width="@dimen/notification_panel_width" - android:layout_marginStart="@dimen/notification_panel_margin_left" android:background="@drawable/heads_up_window_bg" /> </com.android.systemui.statusbar.policy.HeadsUpNotificationView> diff --git a/packages/SystemUI/res/layout/flip_settings.xml b/packages/SystemUI/res/layout/flip_settings.xml index f3c1b90..28d9625 100644 --- a/packages/SystemUI/res/layout/flip_settings.xml +++ b/packages/SystemUI/res/layout/flip_settings.xml @@ -22,5 +22,4 @@ android:layout_height="wrap_content" android:background="#5f000000" android:animateLayoutChanges="true" - android:visibility="gone" android:columnCount="@integer/quick_settings_num_columns" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/heads_up.xml b/packages/SystemUI/res/layout/heads_up.xml index 3a58b84..e4954e7 100644 --- a/packages/SystemUI/res/layout/heads_up.xml +++ b/packages/SystemUI/res/layout/heads_up.xml @@ -22,6 +22,5 @@ android:layout_height="wrap_content" android:layout_width="@dimen/notification_panel_width" android:id="@+id/content_holder" - android:layout_marginStart="@dimen/notification_panel_margin_left" android:background="@drawable/notification_panel_bg" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 761ad42..3267c36 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -23,9 +23,7 @@ xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" android:id="@+id/notification_panel" android:layout_width="0dp" - android:layout_height="wrap_content" - android:paddingTop="@dimen/notification_panel_padding_top" - android:layout_marginStart="@dimen/notification_panel_margin_left" + android:layout_height="match_parent" > <include @@ -36,15 +34,6 @@ android:layout_gravity="bottom" /> - <include - layout="@layout/status_bar_flip_button" - android:id="@+id/keyguard_flipper" - android:layout_width="50dp" - android:layout_height="50dp" - android:layout_gravity="right|top" - android:layout_marginTop="@dimen/status_bar_height" - android:visibility="gone" /> - <com.android.keyguard.CarrierText android:id="@+id/keyguard_carrier_text" android:layout_width="wrap_content" @@ -54,11 +43,6 @@ android:ellipsize="marquee" android:textAppearance="?android:attr/textAppearanceMedium" /> - <include layout="@layout/status_bar_expanded_header" - android:layout_width="match_parent" - android:layout_height="@dimen/notification_panel_header_height" - /> - <include layout="@layout/keyguard_status_view" android:layout_height="wrap_content" @@ -74,27 +58,54 @@ android:visibility="gone" /> - <FrameLayout + <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer android:id="@+id/notification_container_parent" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/close_handle_underlap" - > - <include - layout="@layout/flip_settings" - android:layout_marginTop="@dimen/notification_panel_header_height" + android:clipToPadding="false" + android:clipChildren="false"> + + <com.android.systemui.statusbar.phone.ObservableScrollView + android:id="@+id/scroll_view" android:layout_width="match_parent" - android:layout_height="wrap_content" - /> + android:layout_height="match_parent" + android:visibility="invisible" + android:scrollbars="none" + android:fillViewport="true"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + <include + layout="@layout/flip_settings" + android:layout_marginTop="@dimen/status_bar_header_height_expanded" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + <!-- A view to reserve space for the collapsed stack --> + <View + android:layout_height="@dimen/collapsed_stack_height" + android:layout_width="match_parent"/> + </LinearLayout> + </com.android.systemui.statusbar.phone.ObservableScrollView> + <com.android.systemui.statusbar.stack.NotificationStackScrollLayout android:id="@+id/notification_stack_scroller" android:layout_width="match_parent" - android:layout_height="wrap_content" - /> - </FrameLayout> + android:layout_height="match_parent" + android:layout_marginBottom="@dimen/close_handle_underlap"/> + + </com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer> + + + <include layout="@layout/status_bar_expanded_header" + android:layout_width="match_parent" + android:layout_height="@dimen/status_bar_header_height" + /> <include layout="@layout/keyguard_bottom_area" android:visibility="gone" /> + </com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel --> diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml index 8975728..460dd4b 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml @@ -15,21 +15,30 @@ ** limitations under the License. --> -<LinearLayout +<!-- Extends RelativeLayout --> +<com.android.systemui.statusbar.phone.StatusBarHeaderView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" android:id="@+id/header" android:layout_width="match_parent" - android:layout_height="@dimen/notification_panel_header_height" - android:background="@drawable/notification_header_bg" + android:layout_height="@dimen/status_bar_header_height" android:orientation="horizontal" android:gravity="center_vertical" android:baselineAligned="false" > + + <View + android:id="@+id/background" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/notification_header_bg" + android:clickable="true" + /> <RelativeLayout android:id="@+id/datetime" android:layout_width="wrap_content" android:layout_height="match_parent" + android:layout_gravity="start" android:paddingStart="8dp" android:paddingEnd="8dp" android:background="@drawable/ic_notify_button_bg" @@ -55,12 +64,6 @@ /> </RelativeLayout> - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1" - /> - <TextView android:id="@+id/header_debug_info" android:visibility="invisible" @@ -74,18 +77,22 @@ android:padding="2dp" /> + <include layout="@layout/status_bar_flip_button" + android:id="@+id/header_flipper" + android:layout_width="50dp" + android:layout_height="50dp" + android:layout_alignParentEnd="true"/> + <ImageView android:id="@+id/clear_all_button" android:layout_width="50dp" android:layout_height="50dp" + android:layout_toStartOf="@id/header_flipper" android:scaleType="center" android:src="@drawable/ic_notify_clear" android:background="@drawable/ic_notify_button_bg" android:contentDescription="@string/accessibility_clear_all" /> - <include layout="@layout/status_bar_flip_button" - android:id="@+id/header_flipper" - android:layout_width="50dp" - android:layout_height="50dp" - android:layout_marginStart="12dp" /> -</LinearLayout> + + +</com.android.systemui.statusbar.phone.StatusBarHeaderView> diff --git a/packages/SystemUI/res/layout/status_bar_flip_button.xml b/packages/SystemUI/res/layout/status_bar_flip_button.xml index b7dff8c..f4d7033 100644 --- a/packages/SystemUI/res/layout/status_bar_flip_button.xml +++ b/packages/SystemUI/res/layout/status_bar_flip_button.xml @@ -15,22 +15,11 @@ ~ limitations under the License --> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="50dp" - android:layout_height="50dp"> - <ImageView android:id="@+id/settings_button" - android:layout_width="50dp" - android:layout_height="50dp" - android:scaleType="center" - android:src="@drawable/ic_notify_settings" - android:background="@drawable/ic_notify_button_bg" - android:contentDescription="@string/accessibility_desc_quick_settings" /> - <ImageView android:id="@+id/notification_button" - android:layout_width="50dp" - android:layout_height="50dp" - android:scaleType="center" - android:src="@drawable/ic_notifications" - android:background="@drawable/ic_notify_button_bg" - android:visibility="gone" - android:contentDescription="@string/accessibility_notifications_button" /> -</FrameLayout>
\ No newline at end of file +<ImageView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/settings_button" + android:layout_width="50dp" + android:layout_height="50dp" + android:scaleType="center" + android:src="@drawable/ic_notify_quicksettings" + android:background="@drawable/ic_notify_button_bg" + android:contentDescription="@string/accessibility_desc_quick_settings"/>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 61d43d7..f9b022c 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -33,11 +33,10 @@ <com.android.systemui.statusbar.phone.PanelHolder android:id="@+id/panel_holder" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginTop="@dimen/panel_holder_padding_top"> + 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_height="match_parent" android:layout_gravity="start|top" /> </com.android.systemui.statusbar.phone.PanelHolder> diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml deleted file mode 100644 index c6c0719..0000000 --- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * 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. -*/ ---> -<resources> - <!-- Layout parameters for the notification panel --> - <dimen name="notification_panel_margin_bottom">0dp</dimen> - <dimen name="notification_panel_margin_left">32dp</dimen> -</resources> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index 92e3885..7372181 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -19,10 +19,6 @@ <!-- The width of the notification panel window: 446 + 16 + 16 (padding in the bg drawable) --> <dimen name="notification_panel_width">478dp</dimen> - <!-- Layout parameters for the notification panel --> - <dimen name="notification_panel_margin_bottom">192dp</dimen> - <dimen name="notification_panel_margin_left">16dp</dimen> - <!-- Gravity for the notification panel --> <!-- 0x31 = top|center_horizontal --> <integer name="notification_panel_layout_gravity">0x31</integer> @@ -43,9 +39,6 @@ <dimen name="status_bar_recents_thumbnail_width">200dp</dimen> <dimen name="status_bar_recents_thumbnail_height">177dp</dimen> - <!-- On tablets, panels drop from the statusbar instead of overlapping it. --> - <dimen name="panel_holder_padding_top">@*android:dimen/status_bar_height</dimen> - <!-- Minimum fraction of the screen that should be taken up by the notification panel. --> <item type="dimen" name="notification_panel_min_height_frac">40%</item> diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml index b1fc00a..a1c5b66 100644 --- a/packages/SystemUI/res/values-sw720dp/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp/dimens.xml @@ -24,8 +24,6 @@ <!-- The width of the ticker, including the icon --> <dimen name="notification_ticker_width">360dp</dimen> - <!-- Status bar panel bottom offset (height of status bar - overlap) --> - <dimen name="status_bar_panel_bottom_offset">36dp</dimen> <!-- gap on either side of status bar notification icons --> <dimen name="status_bar_icon_padding">1dp</dimen> <!-- The width of the notification panel window --> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index c3ccb59..93a75bc 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -99,9 +99,6 @@ <integer name="blinds_pop_duration_ms">10</integer> - <!-- The device supports quick settings. --> - <bool name="config_hasQuickSettings">true</bool> - <!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? --> <bool name="config_show4GForLTE">true</bool> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index d763bd6..8d3a565 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -152,21 +152,11 @@ <!-- Amount of close_handle that will NOT overlap the notification list --> <dimen name="close_handle_underlap">32dp</dimen> - <!-- Height of the notification panel header bar --> - <dimen name="notification_panel_header_height">48dp</dimen> + <!-- Height of the status bar header bar --> + <dimen name="status_bar_header_height">48dp</dimen> - <!-- Extra space above the panel --> - <dimen name="notification_panel_padding_top">0dp</dimen> - - <!-- Extra space above the clock in the panel --> - <dimen name="notification_panel_header_padding_top">0dp</dimen> - - <!-- Extra space above the panel holder --> - <dimen name="panel_holder_padding_top">0dp</dimen> - - <!-- Layout parameters for the notification panel --> - <dimen name="notification_panel_margin_bottom">0dp</dimen> - <dimen name="notification_panel_margin_left">0dp</dimen> + <!-- Height of the status bar header bar when expanded --> + <dimen name="status_bar_header_height_expanded">144dp</dimen> <!-- Gravity for the notification panel --> <!-- 0x37 = fill_horizontal|top --> @@ -261,6 +251,9 @@ <!-- The padding between the individual notification cards. --> <dimen name="notification_padding">3dp</dimen> + <!-- The total height of the stack in its collapsed size (i.e. when quick settings is open) --> + <dimen name="collapsed_stack_height">94dp</dimen> + <!-- Width of the zen mode interstitial dialog. --> <dimen name="zen_mode_dialog_width">320dp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index d224975..a325186 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1144,7 +1144,6 @@ public abstract class BaseStatusBar extends SystemUI implements protected abstract void updateNotificationIcons(); protected abstract void tick(IBinder key, StatusBarNotification n, boolean firstTime); protected abstract void updateExpandedViewPos(int expandedPosition); - protected abstract int getExpandedViewMaxHeight(); protected abstract boolean shouldDisableNavbarGestures(); protected boolean isTopNotification(ViewGroup parent, NotificationData.Entry entry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 627b80f..f63ba9c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -16,11 +16,17 @@ package com.android.systemui.statusbar.phone; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; +import android.view.VelocityTracker; import android.view.View; import android.view.accessibility.AccessibilityEvent; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableView; @@ -29,18 +35,40 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; public class NotificationPanelView extends PanelView implements - ExpandableView.OnHeightChangedListener { + ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener, + View.OnClickListener { public static final boolean DEBUG_GESTURES = true; + private static final int EXPANSION_ANIMATION_LENGTH = 375; PhoneStatusBar mStatusBar; - private View mHeader; + private StatusBarHeaderView mHeader; + private QuickSettingsContainerView mQsContainer; private View mKeyguardStatusView; + private ObservableScrollView mScrollView; + private View mStackScrollerContainer; private NotificationStackScrollLayout mNotificationStackScroller; - private boolean mTrackingSettings; private int mNotificationTopPadding; private boolean mAnimateNextTopPaddingChange; + private Interpolator mExpansionInterpolator; + + private int mTrackingPointer; + private VelocityTracker mVelocityTracker; + private boolean mTracking; + private boolean mQsExpanded; + private float mInitialHeightOnTouch; + private float mInitialTouchX; + private float mInitialTouchY; + private float mQsExpansionHeight; + private int mQsMinExpansionHeight; + private int mQsMaxExpansionHeight; + private int mMinStackHeight; + private float mNotificationTranslation; + private int mStackScrollerIntrinsicPadding; + private boolean mQsExpansionEnabled = true; + private ValueAnimator mQsExpansionAnimator; + public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -63,14 +91,21 @@ public class NotificationPanelView extends PanelView implements @Override protected void onFinishInflate() { super.onFinishInflate(); - - mHeader = findViewById(R.id.header); + mHeader = (StatusBarHeaderView) findViewById(R.id.header); + mHeader.getBackgroundView().setOnClickListener(this); mKeyguardStatusView = findViewById(R.id.keyguard_status_view); + mStackScrollerContainer = findViewById(R.id.notification_container_parent); + mQsContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container); + mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); + mScrollView.setListener(this); mNotificationStackScroller = (NotificationStackScrollLayout) findViewById(R.id.notification_stack_scroller); mNotificationStackScroller.setOnHeightChangedListener(this); mNotificationTopPadding = getResources().getDimensionPixelSize( R.dimen.notifications_top_padding); + mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height); + mExpansionInterpolator = AnimationUtils.loadInterpolator( + getContext(), android.R.interpolator.fast_out_slow_in); } @Override @@ -78,11 +113,21 @@ public class NotificationPanelView extends PanelView implements super.onLayout(changed, left, top, right, bottom); int keyguardBottomMargin = ((MarginLayoutParams) mKeyguardStatusView.getLayoutParams()).bottomMargin; - mNotificationStackScroller.setTopPadding(mStatusBar.getBarState() == StatusBarState.KEYGUARD - ? mKeyguardStatusView.getBottom() + keyguardBottomMargin - : mHeader.getBottom() + mNotificationTopPadding, - mAnimateNextTopPaddingChange); - mAnimateNextTopPaddingChange = false; + if (!mQsExpanded) { + mStackScrollerIntrinsicPadding = mStatusBar.getBarState() == StatusBarState.KEYGUARD + ? mKeyguardStatusView.getBottom() + keyguardBottomMargin + : mHeader.getBottom() + mNotificationTopPadding; + mNotificationStackScroller.setTopPadding(mStackScrollerIntrinsicPadding, + mAnimateNextTopPaddingChange); + mAnimateNextTopPaddingChange = false; + } + + // Calculate quick setting heights. + mQsMinExpansionHeight = mHeader.getCollapsedHeight(); + mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight(); + if (mQsExpansionHeight == 0) { + mQsExpansionHeight = mQsMinExpansionHeight; + } } public void animateNextTopPaddingChange() { @@ -90,6 +135,30 @@ public class NotificationPanelView extends PanelView implements requestLayout(); } + /** + * @return Whether Quick Settings are currently expanded. + */ + public boolean isQsExpanded() { + return mQsExpanded; + } + + public void setQsExpansionEnabled(boolean qsExpansionEnabled) { + mQsExpansionEnabled = qsExpansionEnabled; + mHeader.setExpansionEnabled(qsExpansionEnabled); + } + + public void closeQs() { + cancelAnimation(); + setQsExpansion(mQsMinExpansionHeight); + } + + public void openQs() { + cancelAnimation(); + if (mQsExpansionEnabled) { + setQsExpansion(mQsMaxExpansionHeight); + } + } + @Override public void fling(float vel, boolean always) { GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder(); @@ -114,42 +183,245 @@ public class NotificationPanelView extends PanelView implements @Override public boolean onInterceptTouchEvent(MotionEvent event) { - // intercept for quick settings - if (event.getAction() == MotionEvent.ACTION_DOWN) { - final View target = mStatusBar.getBarState() == StatusBarState.KEYGUARD - ? mKeyguardStatusView - : mHeader; - final boolean inTarget = PhoneStatusBar.inBounds(target, event, true); - if (inTarget && !isInSettings()) { - mTrackingSettings = true; - requestDisallowInterceptTouchEvent(true); - return true; - } - if (!inTarget && isInSettings()) { - mTrackingSettings = true; - requestDisallowInterceptTouchEvent(true); - return true; - } + int pointerIndex = event.findPointerIndex(mTrackingPointer); + if (pointerIndex < 0) { + pointerIndex = 0; + mTrackingPointer = event.getPointerId(pointerIndex); } - return super.onInterceptTouchEvent(event); + final float x = event.getX(pointerIndex); + final float y = event.getY(pointerIndex); + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mInitialTouchY = y; + mInitialTouchX = x; + initVelocityTracker(); + trackMovement(event); + if (shouldIntercept(mInitialTouchX, mInitialTouchY, 0)) { + getParent().requestDisallowInterceptTouchEvent(true); + } + break; + case MotionEvent.ACTION_POINTER_UP: + final int upPointer = event.getPointerId(event.getActionIndex()); + if (mTrackingPointer == upPointer) { + // gesture is ongoing, find a new pointer to track + final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; + mTrackingPointer = event.getPointerId(newIndex); + mInitialTouchX = event.getX(newIndex); + mInitialTouchY = event.getY(newIndex); + } + break; + + case MotionEvent.ACTION_MOVE: + final float h = y - mInitialTouchY; + trackMovement(event); + if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX) + && shouldIntercept(mInitialTouchX, mInitialTouchY, h)) { + onQsExpansionStarted(); + mInitialHeightOnTouch = mQsExpansionHeight; + mInitialTouchY = y; + mInitialTouchX = x; + mTracking = true; + return true; + } + break; + } + return !mQsExpanded && super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference // implementation. - if (mTrackingSettings) { - mStatusBar.onSettingsEvent(event); - if (event.getAction() == MotionEvent.ACTION_UP - || event.getAction() == MotionEvent.ACTION_CANCEL) { - mTrackingSettings = false; + if (mTracking) { + int pointerIndex = event.findPointerIndex(mTrackingPointer); + if (pointerIndex < 0) { + pointerIndex = 0; + mTrackingPointer = event.getPointerId(pointerIndex); + } + final float y = event.getY(pointerIndex); + final float x = event.getX(pointerIndex); + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + mTracking = true; + mInitialTouchY = y; + mInitialTouchX = x; + onQsExpansionStarted(); + mInitialHeightOnTouch = mQsExpansionHeight; + initVelocityTracker(); + trackMovement(event); + break; + + case MotionEvent.ACTION_POINTER_UP: + final int upPointer = event.getPointerId(event.getActionIndex()); + if (mTrackingPointer == upPointer) { + // gesture is ongoing, find a new pointer to track + final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; + final float newY = event.getY(newIndex); + final float newX = event.getX(newIndex); + mTrackingPointer = event.getPointerId(newIndex); + mInitialHeightOnTouch = mQsExpansionHeight; + mInitialTouchY = newY; + mInitialTouchX = newX; + } + break; + + case MotionEvent.ACTION_MOVE: + final float h = y - mInitialTouchY; + setQsExpansion(h + mInitialHeightOnTouch); + trackMovement(event); + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mTracking = false; + mTrackingPointer = -1; + trackMovement(event); + + float vel = getCurrentVelocity(); + + // TODO: Better logic whether we should expand or not. + flingSettings(vel, vel > 0); + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + break; } return true; } - if (isInSettings()) { - return true; + + // Consume touch events when QS are expanded. + return mQsExpanded || super.onTouchEvent(event); + } + + private void onQsExpansionStarted() { + cancelAnimation(); + + // Reset scroll position and apply that position to the expanded height. + float height = mQsExpansionHeight - mScrollView.getScrollY(); + mScrollView.scrollTo(0, 0); + setQsExpansion(height); + } + + private void expandQs() { + mHeader.setExpanded(true); + mNotificationStackScroller.setEnabled(false); + mScrollView.setVisibility(View.VISIBLE); + mQsExpanded = true; + } + + private void collapseQs() { + mHeader.setExpanded(false); + mNotificationStackScroller.setEnabled(true); + mScrollView.setVisibility(View.INVISIBLE); + mQsExpanded = false; + } + + private void setQsExpansion(float height) { + height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight); + if (height > mQsMinExpansionHeight && !mQsExpanded) { + expandQs(); + } else if (height <= mQsMinExpansionHeight && mQsExpanded) { + collapseQs(); + } + mQsExpansionHeight = height; + mHeader.setExpansion(height); + setQsTranslation(height); + setQsStackScrollerPadding(height); + } + + private void setQsTranslation(float height) { + mQsContainer.setY(height - mQsContainer.getHeight()); + } + + private void setQsStackScrollerPadding(float height) { + float start = height - mScrollView.getScrollY() + mNotificationTopPadding; + float stackHeight = mNotificationStackScroller.getHeight() - start; + if (stackHeight <= mMinStackHeight) { + float overflow = mMinStackHeight - stackHeight; + stackHeight = mMinStackHeight; + start = mNotificationStackScroller.getHeight() - stackHeight; + mNotificationStackScroller.setTranslationY(overflow); + mNotificationTranslation = overflow + mScrollView.getScrollY(); + } else { + mNotificationStackScroller.setTranslationY(0); + mNotificationTranslation = mScrollView.getScrollY(); + } + mNotificationStackScroller.setTopPadding(clampQsStackScrollerPadding((int) start), false); + } + + private int clampQsStackScrollerPadding(int desiredPadding) { + return Math.max(desiredPadding, mStackScrollerIntrinsicPadding); + } + + private void trackMovement(MotionEvent event) { + if (mVelocityTracker != null) mVelocityTracker.addMovement(event); + } + + private void initVelocityTracker() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + } + mVelocityTracker = VelocityTracker.obtain(); + } + + private float getCurrentVelocity() { + if (mVelocityTracker == null) { + return 0; + } + mVelocityTracker.computeCurrentVelocity(1000); + return mVelocityTracker.getYVelocity(); + } + + private void cancelAnimation() { + if (mQsExpansionAnimator != null) { + mQsExpansionAnimator.cancel(); + } + } + private void flingSettings(float vel, boolean expand) { + + // TODO: Actually use velocity. + + float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight; + ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target); + animator.setDuration(EXPANSION_ANIMATION_LENGTH); + animator.setInterpolator(mExpansionInterpolator); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + setQsExpansion((Float) animation.getAnimatedValue()); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mQsExpansionAnimator = null; + } + }); + animator.start(); + mQsExpansionAnimator = animator; + } + + /** + * @return Whether we should intercept a gesture to open Quick Settings. + */ + private boolean shouldIntercept(float x, float y, float yDiff) { + if (!mQsExpansionEnabled) { + return false; + } + View headerView = mStatusBar.getBarState() == StatusBarState.KEYGUARD && !mQsExpanded + ? mKeyguardStatusView + : mHeader; + boolean onHeader = x >= headerView.getLeft() && x <= headerView.getRight() + && y >= headerView.getTop() && y <= headerView.getBottom(); + if (mQsExpanded) { + return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0); + } else { + return onHeader; } - return super.onTouchEvent(event); } @Override @@ -164,14 +436,16 @@ public class NotificationPanelView extends PanelView implements protected int getMaxPanelHeight() { if (!isInSettings()) { int maxPanelHeight = super.getMaxPanelHeight(); - int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin(); + int notificationMarginBottom = mStackScrollerContainer.getPaddingBottom(); + int emptyBottomMargin = notificationMarginBottom + + mNotificationStackScroller.getEmptyBottomMargin(); return maxPanelHeight - emptyBottomMargin; } return super.getMaxPanelHeight(); } private boolean isInSettings() { - return mStatusBar != null && mStatusBar.isFlippedToSettings(); + return mQsExpanded; } @Override @@ -200,4 +474,24 @@ public class NotificationPanelView extends PanelView implements public void onHeightChanged(ExpandableView view) { requestPanelHeightUpdate(); } + + @Override + public void onScrollChanged() { + if (mQsExpanded) { + mNotificationStackScroller.setTranslationY( + mNotificationTranslation - mScrollView.getScrollY()); + } + } + + @Override + public void onClick(View v) { + if (v == mHeader.getBackgroundView()) { + onQsExpansionStarted(); + if (mQsExpanded) { + flingSettings(0 /* vel */, false /* expand */); + } else if (mQsExpansionEnabled) { + flingSettings(0 /* vel */, true /* expand */); + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java new file mode 100644 index 0000000..f41e78d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 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.graphics.Rect; +import android.util.AttributeSet; +import android.widget.FrameLayout; + +/** + * The container with notification stack scroller and quick settings inside. + */ +public class NotificationsQuickSettingsContainer extends FrameLayout { + + public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected boolean fitSystemWindows(Rect insets) { + setPadding(0, 0, 0, insets.bottom); + insets.bottom = 0; + return true; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java new file mode 100644 index 0000000..46484f3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014 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; +import android.view.View; +import android.widget.ScrollView; + +/** + * A scroll view which can be observed for scroll change events. + */ +public class ObservableScrollView extends ScrollView { + + private Listener mListener; + + public ObservableScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setListener(Listener listener) { + mListener = listener; + } + + public boolean isScrolledToBottom() { + return getScrollY() == getMaxScrollY(); + } + + private int getMaxScrollY() { + int scrollRange = 0; + if (getChildCount() > 0) { + View child = getChildAt(0); + scrollRange = Math.max(0, + child.getHeight() - (getHeight() - mPaddingBottom - mPaddingTop)); + } + return scrollRange; + } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (mListener != null) { + mListener.onScrollChanged(); + } + } + + public interface Listener { + void onScrollChanged(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 0cdca66..c854ac9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -75,7 +75,7 @@ public class PanelView extends FrameLayout { private boolean mClosing; private boolean mTracking; private int mTrackingPointer; - private int mTouchSlop; + protected int mTouchSlop; private TimeAnimator mTimeAnimator; private ObjectAnimator mPeekAnimator; @@ -220,9 +220,9 @@ public class PanelView extends FrameLayout { private float mVel, mAccel; protected int mMaxPanelHeight = 0; private String mViewName; - protected float mInitialTouchY; - protected float mInitialTouchX; - protected float mFinalTouchY; + private float mInitialTouchY; + private float mInitialTouchX; + private float mFinalTouchY; protected void onExpandingFinished() { } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 3856ba1..c4ee6ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -73,7 +73,6 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewPropertyAnimator; @@ -192,8 +191,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, int mIconHPadding = -1; Display mDisplay; Point mCurrentDisplaySize = new Point(); - private float mHeadsUpVerticalOffset; - private int[] mStackScrollerPosition = new int[2]; StatusBarWindowView mStatusBarWindow; PhoneStatusBarView mStatusBarView; @@ -222,14 +219,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window View mExpandedContents; int mNotificationPanelGravity; - int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx; + int mNotificationPanelMarginBottomPx; float mNotificationPanelMinHeightFrac; boolean mNotificationPanelIsFullScreenWidth; TextView mNotificationPanelDebugText; // settings QuickSettings mQS; - boolean mHasQuickSettings; View mFlipSettingsView; QuickSettingsContainerView mSettingsContainer; @@ -245,14 +241,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, int mKeyguardMaxNotificationCount; View mDateTimeView; View mClearButton; - FlipperButton mHeaderFlipper, mKeyguardFlipper; + ImageView mHeaderFlipper; // carrier/wifi label private TextView mCarrierLabel; private boolean mCarrierLabelVisible = false; private int mCarrierLabelHeight; private TextView mEmergencyCallLabel; - private int mNotificationHeaderHeight; + private int mStatusBarHeaderHeight; private View mKeyguardCarrierLabel; private boolean mShowCarrierInPanel = false; @@ -326,11 +322,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " + "selfChange=%s userSetup=%s mUserSetup=%s", selfChange, userSetup, mUserSetup)); - mHeaderFlipper.userSetup(userSetup); - mKeyguardFlipper.userSetup(userSetup); if (userSetup != mUserSetup) { mUserSetup = userSetup; + if (mNotificationPanel != null) { + mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() && userSetup); + } if (!mUserSetup && mStatusBarView != null) animateCollapseQuickSettings(); } @@ -651,16 +648,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mClearButton.setEnabled(false); mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date); - mHasQuickSettings = res.getBoolean(R.bool.config_hasQuickSettings); - mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime); if (mDateTimeView != null) { mDateTimeView.setOnClickListener(mClockClickListener); mDateTimeView.setEnabled(true); } - mHeaderFlipper = new FlipperButton(mStatusBarWindow.findViewById(R.id.header_flipper)); - mKeyguardFlipper =new FlipperButton(mStatusBarWindow.findViewById(R.id.keyguard_flipper)); + mHeaderFlipper = (ImageView) mStatusBarWindow.findViewById(R.id.header_flipper); if (!mNotificationPanelIsFullScreenWidth) { mNotificationPanel.setSystemUiVisibility( @@ -735,26 +729,23 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // updateCarrierLabelVisibility(false); } - // Quick Settings (where available, some restrictions apply) - if (mHasQuickSettings) { - // Quick Settings needs a container to survive - mSettingsContainer = (QuickSettingsContainerView) - mStatusBarWindow.findViewById(R.id.quick_settings_container); - mFlipSettingsView = mSettingsContainer; - if (mSettingsContainer != null) { - mQS = new QuickSettings(mContext, mSettingsContainer); - if (!mNotificationPanelIsFullScreenWidth) { - mSettingsContainer.setSystemUiVisibility( - View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS - | View.STATUS_BAR_DISABLE_SYSTEM_INFO); - } - mQS.setService(this); - mQS.setBar(mStatusBarView); - mQS.setup(mNetworkController, mBluetoothController, mBatteryController, - mLocationController, mRotationLockController); - } else { - mQS = null; // fly away, be free - } + // Quick Settings needs a container to survive + mSettingsContainer = (QuickSettingsContainerView) + mStatusBarWindow.findViewById(R.id.quick_settings_container); + mFlipSettingsView = mSettingsContainer; + if (mSettingsContainer != null) { + mQS = new QuickSettings(mContext, mSettingsContainer); + if (!mNotificationPanelIsFullScreenWidth) { + mSettingsContainer.setSystemUiVisibility( + View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS + | View.STATUS_BAR_DISABLE_SYSTEM_INFO); + } + mQS.setService(this); + mQS.setBar(mStatusBarView); + mQS.setup(mNetworkController, mBluetoothController, mBatteryController, + mLocationController, mRotationLockController); + } else { + mQS = null; // fly away, be free } PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); @@ -775,101 +766,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return mStatusBarView; } - public boolean onSettingsEvent(MotionEvent event) { - userActivity(); - if (mSettingsClosing - && mFlipSettingsViewAnim != null && mFlipSettingsViewAnim.isRunning()) { - return true; - } - if (mSettingsTracker != null) { - mSettingsTracker.addMovement(event); - } - final int slop = ViewConfiguration.get(mContext).getScaledTouchSlop(); - if (event.getAction() == MotionEvent.ACTION_DOWN) { - mSettingsTracker = VelocityTracker.obtain(); - mSettingsDownY = event.getY(); - mSettingsCancelled = false; - mSettingsStarted = false; - mSettingsClosing = mFlipSettingsView.getVisibility() == View.VISIBLE; - if (mSettingsClosing) { - mStackScroller.setVisibility(View.VISIBLE); - } else { - mFlipSettingsView.setTranslationY(-mNotificationPanel.getMeasuredHeight()); - } - dispatchSettingsEvent(event); - } else if (mSettingsTracker != null && (event.getAction() == MotionEvent.ACTION_UP - || event.getAction() == MotionEvent.ACTION_CANCEL)) { - final float dy = event.getY() - mSettingsDownY; - final FlipperButton flipper = mState == StatusBarState.KEYGUARD - ? mKeyguardFlipper - : mHeaderFlipper; - final boolean inButton = flipper.inHolderBounds(event); - final boolean qsTap = mSettingsClosing && Math.abs(dy) < slop; - if (!qsTap && !inButton) { - mSettingsTracker.computeCurrentVelocity(1000); - final float vy = mSettingsTracker.getYVelocity(); - final boolean animate = true; - if (dy <= slop || vy <= 0) { - flipToNotifications(animate); - } else { - flipToSettings(animate); - } - } - mSettingsTracker.recycle(); - mSettingsTracker = null; - dispatchSettingsEvent(event); - } else if (mSettingsTracker != null && event.getAction() == MotionEvent.ACTION_MOVE) { - final float dy = event.getY() - mSettingsDownY; - if (mSettingsClosing) { - positionSettings(dy); - final boolean qsTap = Math.abs(dy) < slop; - if (!mSettingsCancelled && !qsTap) { - MotionEvent cancelEvent = MotionEvent.obtainNoHistory(event); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL); - dispatchSettingsEvent(cancelEvent); - mSettingsCancelled = true; - } - } else { - if (!mSettingsStarted && dy > slop) { - mSettingsStarted = true; - mFlipSettingsView.setVisibility(View.VISIBLE); - mStackScroller.setVisibility(View.VISIBLE); - } - if (mSettingsStarted) { - positionSettings(dy); - } - dispatchSettingsEvent(event); - } - } - return true; - } - - private void dispatchSettingsEvent(MotionEvent event) { - final View target = mSettingsClosing ? mFlipSettingsView : mNotificationPanelHeader; - final int[] targetLoc = new int[2]; - target.getLocationInWindow(targetLoc); - final int[] panelLoc = new int[2]; - mNotificationPanel.getLocationInWindow(panelLoc); - final int dx = targetLoc[0] - panelLoc[0]; - final int dy = targetLoc[1] - panelLoc[1]; - event.offsetLocation(-dx, -dy); - target.dispatchTouchEvent(event); - } - - private void positionSettings(float dy) { - if (mSettingsClosing) { - final int ph = mNotificationPanel.getMeasuredHeight(); - dy = Math.min(Math.max(-ph, dy), 0); - mFlipSettingsView.setTranslationY(dy); - mStackScroller.setTranslationY(ph + dy); - } else { - final int h = mFlipSettingsView.getBottom(); - dy = Math.min(Math.max(0, dy), h); - mFlipSettingsView.setTranslationY(-h + dy); - mStackScroller.setTranslationY(dy); - } - } - private void startKeyguard() { KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class); mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, @@ -1230,8 +1126,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, ((ImageView)mClearButton).setImageResource(R.drawable.ic_notify_clear); } - mHeaderFlipper.refreshLayout(); - mKeyguardFlipper.refreshLayout(); + if (mHeaderFlipper != null) { + // Force asset reloading + mHeaderFlipper.setImageDrawable(null); + mHeaderFlipper.setImageResource(R.drawable.ic_notify_quicksettings); + } refreshAllStatusBarIcons(); } @@ -1286,8 +1185,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - mHeaderFlipper.provisionCheck(provisioned); - mKeyguardFlipper.provisionCheck(provisioned); + mNotificationPanel.setQsExpansionEnabled(provisioned && mUserSetup); } @Override @@ -1362,7 +1260,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, final boolean makeVisible = !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly()) && mStackScroller.getHeight() < (mNotificationPanel.getHeight() - - mCarrierLabelHeight - mNotificationHeaderHeight) + - mCarrierLabelHeight - mStatusBarHeaderHeight) && mStackScroller.getVisibility() == View.VISIBLE && mState != StatusBarState.KEYGUARD; @@ -1775,47 +1673,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void flipToNotifications(boolean animate) { - cancelAnim(mFlipSettingsViewAnim); - cancelAnim(mScrollViewAnim); - cancelAnim(mClearButtonAnim); - mHeaderFlipper.cancel(); - mKeyguardFlipper.cancel(); - mStackScroller.setVisibility(View.VISIBLE); - final int h = mNotificationPanel.getMeasuredHeight(); - if (animate) { - final float settingsY = - mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : 0; - final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : h; - mScrollViewAnim = start( - interpolator(mDecelerateInterpolator, - ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, 0) - .setDuration(FLIP_DURATION) - )); - mFlipSettingsViewAnim = start( - setVisibilityWhenDone( - interpolator(mDecelerateInterpolator, - ObjectAnimator.ofFloat( - mFlipSettingsView, View.TRANSLATION_Y, settingsY, -h)) - .setDuration(FLIP_DURATION), - mFlipSettingsView, View.INVISIBLE)); - } else { - mStackScroller.setTranslationY(0); - mFlipSettingsView.setTranslationY(-h); - mFlipSettingsView.setVisibility(View.INVISIBLE); - } - mHeaderFlipper.flipToNotifications(animate); - mKeyguardFlipper.flipToNotifications(animate); - mClearButton.setVisibility(View.VISIBLE); - mClearButton.setAlpha(0f); - setAreThereNotifications(); // this will show/hide the button as necessary - mNotificationPanel.postDelayed(new Runnable() { - public void run() { - updateCarrierLabelVisibility(false); - } - }, animate ? FLIP_DURATION - 150 : 0); - if (mOnFlipRunnable != null) { - mOnFlipRunnable.run(); - } + // TODO: Animation + mNotificationPanel.closeQs(); } @Override @@ -1829,78 +1688,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (!mUserSetup) return; mNotificationPanel.expand(); - if (mFlipSettingsView.getVisibility() != View.VISIBLE - || mFlipSettingsView.getTranslationY() < 0) { - flipToSettings(true /*animate*/); - } + mNotificationPanel.openQs(); if (false) postStartTracing(); } public boolean isFlippedToSettings() { - if (mFlipSettingsView != null) { - return mFlipSettingsView.getVisibility() == View.VISIBLE; + if (mNotificationPanel != null) { + return mNotificationPanel.isQsExpanded(); } return false; } - public void flipToSettings(boolean animate) { - // Settings are not available in setup - if (!mUserSetup) return; - - cancelAnim(mFlipSettingsViewAnim); - cancelAnim(mScrollViewAnim); - mHeaderFlipper.cancel(); - mKeyguardFlipper.cancel(); - cancelAnim(mClearButtonAnim); - - mFlipSettingsView.setVisibility(View.VISIBLE); - final int h = mNotificationPanel.getMeasuredHeight(); - if (animate) { - final float settingsY - = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : -h; - final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : 0; - mFlipSettingsViewAnim = start( - startDelay(0, - interpolator(mDecelerateInterpolator, - ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, - settingsY, 0f) - .setDuration(FLIP_DURATION) - ))); - mScrollViewAnim = start( - setVisibilityWhenDone( - interpolator(mDecelerateInterpolator, - ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, h) - ) - .setDuration(FLIP_DURATION), - mStackScroller, View.INVISIBLE)); - } else { - mFlipSettingsView.setTranslationY(0); - mStackScroller.setTranslationY(h); - mStackScroller.setVisibility(View.INVISIBLE); - } - mHeaderFlipper.flipToSettings(animate); - mKeyguardFlipper.flipToSettings(animate); - if (animate) { - mClearButtonAnim = start( - setVisibilityWhenDone( - ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f) - .setDuration(FLIP_DURATION), - mClearButton, View.INVISIBLE)); - } else { - mClearButton.setAlpha(0); - mClearButton.setVisibility(View.INVISIBLE); - } - mNotificationPanel.postDelayed(new Runnable() { - public void run() { - updateCarrierLabelVisibility(false); - } - }, animate ? FLIP_DURATION - 150 : 0); - if (mOnFlipRunnable != null) { - mOnFlipRunnable.run(); - } - } - public void animateCollapseQuickSettings() { mStatusBarView.collapseAllPanels(true); } @@ -1927,12 +1726,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStackScroller.setVisibility(View.VISIBLE); mNotificationPanel.setVisibility(View.GONE); - mFlipSettingsView.setVisibility(View.GONE); setAreThereNotifications(); // show the clear button - mHeaderFlipper.reset(); - mKeyguardFlipper.reset(); + mNotificationPanel.closeQs(); mExpandedVisible = false; if (mNavigationBarView != null) @@ -2463,20 +2260,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - void updateExpandedInvisiblePosition() { - mTrackingPosition = -mDisplayMetrics.heightPixels; - } - static final float saturate(float a) { return a < 0f ? 0f : (a > 1f ? 1f : a); } @Override - protected int getExpandedViewMaxHeight() { - return mDisplayMetrics.heightPixels - mNotificationPanelMarginBottomPx; - } - - @Override public void updateExpandedViewPos(int thingy) { if (SPEW) Log.v(TAG, "updateExpandedViewPos"); @@ -2486,15 +2274,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams(); lp.gravity = mNotificationPanelGravity; - lp.setMarginStart(mNotificationPanelMarginPx); mNotificationPanel.setLayoutParams(lp); - if (ENABLE_HEADS_UP && mHeadsUpNotificationView != null) { - mHeadsUpNotificationView.setMargin(mNotificationPanelMarginPx); - mStackScroller.getLocationOnScreen(mStackScrollerPosition); - mHeadsUpVerticalOffset = mStackScrollerPosition[1] - mNaturalBarHeight; - } - updateCarrierLabelVisibility(false); } @@ -2542,17 +2323,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, animateCollapsePanels(); } - private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() { - public void onClick(View v) { - if (mHasQuickSettings) { - animateExpandSettingsPanel(); - } else { - startActivityDismissingKeyguard( - new Intent(android.provider.Settings.ACTION_SETTINGS), true); - } - } - }; - private View.OnClickListener mClockClickListener = new View.OnClickListener() { public void onClick(View v) { startActivityDismissingKeyguard( @@ -2653,17 +2423,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - public void animateHeadsUp(boolean animateInto, float frac) { - if (!ENABLE_HEADS_UP || mHeadsUpNotificationView == null) return; - frac = frac / 0.4f; - frac = frac < 1.0f ? frac : 1.0f; - float alpha = 1.0f - frac; - float offset = mHeadsUpVerticalOffset * frac; - offset = animateInto ? offset : 0f; - mHeadsUpNotificationView.setAlpha(alpha); - mHeadsUpNotificationView.setY(offset); - } - public void onHeadsUpDismissed() { if (mInterruptingNotificationEntry == null) return; mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP); @@ -2736,17 +2495,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity); - mNotificationPanelMarginBottomPx - = (int) res.getDimension(R.dimen.notification_panel_margin_bottom); - mNotificationPanelMarginPx - = (int) res.getDimension(R.dimen.notification_panel_margin_left); mNotificationPanelGravity = res.getInteger(R.integer.notification_panel_layout_gravity); if (mNotificationPanelGravity <= 0) { mNotificationPanelGravity = Gravity.START | Gravity.TOP; } mCarrierLabelHeight = res.getDimensionPixelSize(R.dimen.carrier_label_height); - mNotificationHeaderHeight = res.getDimensionPixelSize(R.dimen.notification_panel_header_height); + mStatusBarHeaderHeight = res.getDimensionPixelSize(R.dimen.status_bar_header_height); mNotificationPanelMinHeightFrac = res.getFraction(R.dimen.notification_panel_min_height_frac, 1, 1); if (mNotificationPanelMinHeightFrac < 0f || mNotificationPanelMinHeightFrac > 1f) { @@ -3016,9 +2771,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private void updateKeyguardState() { if (mState == StatusBarState.KEYGUARD) { - if (isFlippedToSettings()) { - flipToNotifications(false /*animate*/); - } mKeyguardStatusView.setVisibility(View.VISIBLE); mKeyguardBottomArea.setVisibility(View.VISIBLE); mKeyguardIndicationTextView.setVisibility(View.VISIBLE); @@ -3026,7 +2778,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mKeyguardCarrierLabel.setVisibility(View.VISIBLE); mNotificationPanelHeader.setVisibility(View.GONE); - mKeyguardFlipper.setVisibility(View.VISIBLE); + mNotificationPanel.closeQs(); mSettingsContainer.setKeyguardShowing(true); } else { mKeyguardStatusView.setVisibility(View.GONE); @@ -3035,7 +2787,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mKeyguardCarrierLabel.setVisibility(View.GONE); mNotificationPanelHeader.setVisibility(View.VISIBLE); - mKeyguardFlipper.setVisibility(View.GONE); mSettingsContainer.setKeyguardShowing(false); } @@ -3202,131 +2953,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, * @return a ViewGroup that spans the entire panel which contains the quick settings */ public ViewGroup getQuickSettingsOverlayParent() { - if (mHasQuickSettings) { - return mNotificationPanel; - } else { - return null; - } - } - - public static boolean inBounds(View view, MotionEvent event, boolean orAbove) { - final int[] location = new int[2]; - view.getLocationInWindow(location); - final int rx = (int) event.getRawX(); - final int ry = (int) event.getRawY(); - return rx >= location[0] && rx <= location[0] + view.getMeasuredWidth() - && (orAbove || ry >= location[1]) && ry <= location[1] + view.getMeasuredHeight(); - } - - private final class FlipperButton { - private final View mHolder; - - private ImageView mSettingsButton, mNotificationButton; - private Animator mSettingsButtonAnim, mNotificationButtonAnim; - - public FlipperButton(View holder) { - mHolder = holder; - mSettingsButton = (ImageView) holder.findViewById(R.id.settings_button); - if (mSettingsButton != null) { - mSettingsButton.setOnClickListener(mSettingsButtonListener); - if (mHasQuickSettings) { - // the settings panel is hiding behind this button - mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); - mSettingsButton.setVisibility(View.VISIBLE); - } else { - // no settings panel, go straight to settings - mSettingsButton.setVisibility(View.VISIBLE); - mSettingsButton.setImageResource(R.drawable.ic_notify_settings); - } - } - mNotificationButton = (ImageView) holder.findViewById(R.id.notification_button); - if (mNotificationButton != null) { - mNotificationButton.setOnClickListener(mNotificationButtonListener); - } - } - - public boolean inHolderBounds(MotionEvent event) { - return inBounds(mHolder, event, false); - } - - public void provisionCheck(boolean provisioned) { - if (mSettingsButton != null) { - mSettingsButton.setEnabled(provisioned); - } - } - - public void userSetup(boolean userSetup) { - if (mSettingsButton != null) { - mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE); - } - } - - public void reset() { - cancel(); - mSettingsButton.setVisibility(View.VISIBLE); - mNotificationButton.setVisibility(View.GONE); - } - - public void refreshLayout() { - if (mSettingsButton != null) { - // Force asset reloading - mSettingsButton.setImageDrawable(null); - mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings); - } - - if (mNotificationButton != null) { - // Force asset reloading - mNotificationButton.setImageDrawable(null); - mNotificationButton.setImageResource(R.drawable.ic_notifications); - } - } - - public void flipToSettings(boolean animate) { - mNotificationButton.setVisibility(View.VISIBLE); - if (animate) { - mSettingsButtonAnim = start( - setVisibilityWhenDone( - ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f) - .setDuration(FLIP_DURATION_OUT), - mStackScroller, View.INVISIBLE)); - mNotificationButtonAnim = start( - startDelay(FLIP_DURATION_OUT, - ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f) - .setDuration(FLIP_DURATION_IN))); - } else { - mSettingsButton.setAlpha(0f); - mSettingsButton.setVisibility(View.INVISIBLE); - mNotificationButton.setAlpha(1f); - } - } - - public void flipToNotifications(boolean animate) { - mSettingsButton.setVisibility(View.VISIBLE); - if (animate) { - mNotificationButtonAnim = start( - setVisibilityWhenDone( - ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f) - .setDuration(FLIP_DURATION_OUT), - mNotificationButton, View.INVISIBLE)); - - mSettingsButtonAnim = start( - startDelay(FLIP_DURATION_OUT, - ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f) - .setDuration(FLIP_DURATION_IN))); - } else { - mNotificationButton.setVisibility(View.INVISIBLE); - mNotificationButton.setAlpha(0f); - mSettingsButton.setAlpha(1f); - } - } - - public void cancel() { - cancelAnim(mSettingsButtonAnim); - cancelAnim(mNotificationButtonAnim); - } - - public void setVisibility(int vis) { - mHolder.setVisibility(vis); - } + return mNotificationPanel; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 10c1625..e6de057 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -220,8 +220,6 @@ public class PhoneStatusBarView extends PanelBar { panel.setAlpha(alpha); } - mBar.animateHeadsUp(mNotificationPanel == panel, mPanelExpandedFractionSum); - mBar.updateCarrierLabelVisibility(false); mBar.userActivity(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java new file mode 100644 index 0000000..9d33930 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2014 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; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; + +import com.android.systemui.R; + +/** + * The view to manage the header area in the expanded status bar. + */ +public class StatusBarHeaderView extends RelativeLayout { + + private boolean mExpanded; + private View mBackground; + private View mFlipper; + + private int mCollapsedHeight; + private int mExpandedHeight; + + public StatusBarHeaderView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mBackground = findViewById(R.id.background); + mFlipper = findViewById(R.id.header_flipper); + loadDimens(); + } + + private void loadDimens() { + mCollapsedHeight = getResources().getDimensionPixelSize( + R.dimen.status_bar_header_height); + mExpandedHeight = getResources().getDimensionPixelSize( + R.dimen.status_bar_header_height_expanded); + } + + public int getCollapsedHeight() { + return mCollapsedHeight; + } + + public int getExpandedHeight() { + return mExpandedHeight; + } + + public void setExpanded(boolean expanded) { + if (expanded != mExpanded) { + ViewGroup.LayoutParams lp = getLayoutParams(); + lp.height = expanded ? mExpandedHeight : mCollapsedHeight; + setLayoutParams(lp); + mExpanded = expanded; + } + } + + public void setExpansionEnabled(boolean enabled) { + mFlipper.setVisibility(enabled ? View.VISIBLE : View.GONE); + } + + public void setExpansion(float height) { + if (height < mCollapsedHeight) { + height = mCollapsedHeight; + } + if (height > mExpandedHeight) { + height = mExpandedHeight; + } + if (mExpanded) { + mBackground.setTranslationY(-(mExpandedHeight - height)); + } else { + mBackground.setTranslationY(0); + } + } + + public View getBackgroundView() { + return mBackground; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 4c9264d..e802d18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -56,11 +56,14 @@ public class StatusBarWindowView extends FrameLayout { @Override protected boolean fitSystemWindows(Rect insets) { if (getFitsSystemWindows()) { - setPadding(insets.left, insets.top, insets.right, insets.bottom); + setPadding(insets.left, insets.top, insets.right, 0); + insets.left = 0; + insets.top = 0; + insets.right = 0; } else { setPadding(0, 0, 0, 0); } - return true; + return false; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index f8aab80..59d717c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -492,6 +492,9 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public boolean onTouchEvent(MotionEvent ev) { + if (!isEnabled()) { + return false; + } boolean scrollerWantsIt = false; if (!mSwipingInProgress) { scrollerWantsIt = onScrollTouch(ev); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java index 4b3d3b0..d6a8885 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java @@ -121,11 +121,6 @@ public class TvStatusBar extends BaseStatusBar { } @Override - protected int getExpandedViewMaxHeight() { - return 0; - } - - @Override protected boolean shouldDisableNavbarGestures() { return true; } |