1c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler/* 2c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * Copyright (C) 2012 The Android Open Source Project 3c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * 4c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 5c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * you may not use this file except in compliance with the License. 6c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * You may obtain a copy of the License at 7c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * 8c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 9c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * 10c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * Unless required by applicable law or agreed to in writing, software 11c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 12c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * See the License for the specific language governing permissions and 14c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler * limitations under the License. 15c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler */ 16c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler 17c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandlerpackage com.android.systemui.statusbar.phone; 18c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler 19c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandlerimport android.content.Context; 20198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandlerimport android.graphics.Canvas; 21198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandlerimport android.graphics.Paint; 22c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandlerimport android.util.AttributeSet; 235de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wrenimport android.util.Log; 24c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandlerimport android.view.KeyEvent; 255de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wrenimport android.view.MotionEvent; 26b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandlerimport android.view.View; 27b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandlerimport android.view.ViewRootImpl; 28c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandlerimport android.widget.FrameLayout; 299b2cd15f0fed990f532f35590c2a2896b90dc7fcChris Wrenimport android.widget.ScrollView; 30c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandlerimport android.widget.TextSwitcher; 31c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler 325de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wrenimport com.android.systemui.ExpandHelper; 335de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wrenimport com.android.systemui.R; 34198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandlerimport com.android.systemui.statusbar.BaseStatusBar; 355de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wrenimport com.android.systemui.statusbar.policy.NotificationRowLayout; 365de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren 37c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler 38c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandlerpublic class StatusBarWindowView extends FrameLayout 39c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler{ 40198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public static final String TAG = "StatusBarWindowView"; 41198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public static final boolean DEBUG = BaseStatusBar.DEBUG; 425de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren 435de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren private ExpandHelper mExpandHelper; 445de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren private NotificationRowLayout latestItems; 45b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler private NotificationPanelView mNotificationPanel; 46101784e5605338f22e32f587ffcaa09b582d556cDaniel Sandler private ScrollView mScrollView; 475de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren 48c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler PhoneStatusBar mService; 49c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler 50c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler public StatusBarWindowView(Context context, AttributeSet attrs) { 51c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler super(context, attrs); 525de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren setMotionEventSplittingEnabled(false); 53198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler setWillNotDraw(!DEBUG); 545de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren } 555de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren 565de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren @Override 575de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren protected void onAttachedToWindow () { 585de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren super.onAttachedToWindow(); 595de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren latestItems = (NotificationRowLayout) findViewById(R.id.latestItems); 60101784e5605338f22e32f587ffcaa09b582d556cDaniel Sandler mScrollView = (ScrollView) findViewById(R.id.scroll); 61b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel); 625de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height); 635de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height); 645de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren mExpandHelper = new ExpandHelper(mContext, latestItems, minHeight, maxHeight); 655de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren mExpandHelper.setEventSource(this); 66101784e5605338f22e32f587ffcaa09b582d556cDaniel Sandler mExpandHelper.setScrollView(mScrollView); 67b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandler 68b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandler // We really need to be able to animate while window animations are going on 69b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandler // so that activities may be started asynchronously from panel animations 70b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandler final ViewRootImpl root = getViewRootImpl(); 71b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandler if (root != null) { 72b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandler root.setDrawDuringWindowsAnimating(true); 73b10d885c3bb9d634c1c21178319fdf1c04c16bc3Daniel Sandler } 74c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler } 75c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler 76c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler @Override 77c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler public boolean dispatchKeyEvent(KeyEvent event) { 78c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 79c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler switch (event.getKeyCode()) { 80c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler case KeyEvent.KEYCODE_BACK: 81c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler if (!down) { 8211cf178100e71d3f9f34ab5865e03a277c5eadaaDaniel Sandler mService.animateCollapsePanels(); 83c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler } 84c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler return true; 85c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler } 86c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler return super.dispatchKeyEvent(event); 87c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler } 885de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren 895de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren @Override 905de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren public boolean onInterceptTouchEvent(MotionEvent ev) { 91b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler boolean intercept = false; 92101784e5605338f22e32f587ffcaa09b582d556cDaniel Sandler if (mNotificationPanel.isFullyExpanded() && mScrollView.getVisibility() == View.VISIBLE) { 93b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler intercept = mExpandHelper.onInterceptTouchEvent(ev); 94b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler } 95b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler if (!intercept) { 96b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler super.onInterceptTouchEvent(ev); 97b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler } 985de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren if (intercept) { 99a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn MotionEvent cancellation = MotionEvent.obtain(ev); 100a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn cancellation.setAction(MotionEvent.ACTION_CANCEL); 1015de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren latestItems.onInterceptTouchEvent(cancellation); 102a4b7f2f75e7803193429ec1179fb5e2eb1c6fbdaDianne Hackborn cancellation.recycle(); 1035de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren } 1045de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren return intercept; 1055de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren } 1065de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren 1075de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren @Override 1085de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren public boolean onTouchEvent(MotionEvent ev) { 109b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler boolean handled = false; 110b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler if (mNotificationPanel.isFullyExpanded()) { 111b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler handled = mExpandHelper.onTouchEvent(ev); 112b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler } 113b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler if (!handled) { 114b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler handled = super.onTouchEvent(ev); 115b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler } 1165de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren return handled; 1175de6e94e36e2adbdd4ebfb5c1903c23c9ea3c388Chris Wren } 118198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler 119198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler @Override 120198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public void onDraw(Canvas canvas) { 121198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler super.onDraw(canvas); 122198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler if (DEBUG) { 123198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler Paint pt = new Paint(); 124198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler pt.setColor(0x80FFFF00); 125198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler pt.setStrokeWidth(12.0f); 126198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler pt.setStyle(Paint.Style.STROKE); 127198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt); 128198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler } 129198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler } 130ac47ff70c322614ff2ca9ad82fe41338daf55877Daniel Sandler 131ac47ff70c322614ff2ca9ad82fe41338daf55877Daniel Sandler public void cancelExpandHelper() { 1321a3bdd5097e83659590895991904bbc6250cd5f2Daniel Sandler if (mExpandHelper != null) { 1331a3bdd5097e83659590895991904bbc6250cd5f2Daniel Sandler mExpandHelper.cancel(); 1341a3bdd5097e83659590895991904bbc6250cd5f2Daniel Sandler } 135ac47ff70c322614ff2ca9ad82fe41338daf55877Daniel Sandler } 136c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler} 137c4f2a5652dd42fdb43a94e341b7a2034b0211a21Daniel Sandler 138