PhoneStatusBarView.java revision 1dacf2772d0099ae74f42f81d162a3d0e180ffb7
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.statusbar.phone; 18 19import android.content.Context; 20import android.content.res.Configuration; 21import android.graphics.Canvas; 22import android.graphics.Rect; 23import android.os.SystemClock; 24import android.util.AttributeSet; 25import android.view.MotionEvent; 26import android.view.View; 27import android.view.ViewGroup; 28import android.view.ViewParent; 29import android.view.accessibility.AccessibilityEvent; 30import android.widget.FrameLayout; 31 32import com.android.systemui.R; 33import com.android.systemui.statusbar.policy.FixedSizeDrawable; 34 35public class PhoneStatusBarView extends FrameLayout { 36 private static final String TAG = "PhoneStatusBarView"; 37 38 static final int DIM_ANIM_TIME = 400; 39 40 PhoneStatusBar mService; 41 boolean mTracking; 42 int mStartX, mStartY; 43 ViewGroup mNotificationIcons; 44 ViewGroup mStatusIcons; 45 View mDate; 46 FixedSizeDrawable mBackground; 47 48 boolean mNightMode = false; 49 int mStartAlpha = 0, mEndAlpha = 0; 50 long mEndTime = 0; 51 52 Rect mButtonBounds = new Rect(); 53 boolean mCapturingEvents = true; 54 55 public PhoneStatusBarView(Context context, AttributeSet attrs) { 56 super(context, attrs); 57 } 58 59 @Override 60 protected void onFinishInflate() { 61 super.onFinishInflate(); 62 mNotificationIcons = (ViewGroup)findViewById(R.id.notificationIcons); 63 mStatusIcons = (ViewGroup)findViewById(R.id.statusIcons); 64 mDate = findViewById(R.id.date); 65 66 mBackground = new FixedSizeDrawable(mDate.getBackground()); 67 mBackground.setFixedBounds(0, 0, 0, 0); 68 mDate.setBackgroundDrawable(mBackground); 69 } 70 71 @Override 72 protected void onAttachedToWindow() { 73 super.onAttachedToWindow(); 74 mService.onBarViewAttached(); 75 } 76 77 @Override 78 protected void onConfigurationChanged(Configuration newConfig) { 79 super.onConfigurationChanged(newConfig); 80 mService.updateDisplaySize(); 81 boolean nightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) 82 == Configuration.UI_MODE_NIGHT_YES; 83 if (mNightMode != nightMode) { 84 mNightMode = nightMode; 85 mStartAlpha = getCurAlpha(); 86 mEndAlpha = mNightMode ? 0x80 : 0x00; 87 mEndTime = SystemClock.uptimeMillis() + DIM_ANIM_TIME; 88 invalidate(); 89 } 90 } 91 92 int getCurAlpha() { 93 long time = SystemClock.uptimeMillis(); 94 if (time > mEndTime) { 95 return mEndAlpha; 96 } 97 return mEndAlpha 98 - (int)(((mEndAlpha-mStartAlpha) * (mEndTime-time) / DIM_ANIM_TIME)); 99 } 100 101 @Override 102 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 103 super.onSizeChanged(w, h, oldw, oldh); 104 mService.updateExpandedViewPos(PhoneStatusBar.EXPANDED_LEAVE_ALONE); 105 } 106 107 @Override 108 protected void onLayout(boolean changed, int l, int t, int r, int b) { 109 super.onLayout(changed, l, t, r, b); 110 111 // put the date date view quantized to the icons 112 int oldDateRight = mDate.getRight(); 113 int newDateRight; 114 115 newDateRight = getDateSize(mNotificationIcons, oldDateRight, 116 getViewOffset(mNotificationIcons)); 117 if (newDateRight < 0) { 118 int offset = getViewOffset(mStatusIcons); 119 if (oldDateRight < offset) { 120 newDateRight = oldDateRight; 121 } else { 122 newDateRight = getDateSize(mStatusIcons, oldDateRight, offset); 123 if (newDateRight < 0) { 124 newDateRight = r; 125 } 126 } 127 } 128 int max = r - getPaddingRight(); 129 if (newDateRight > max) { 130 newDateRight = max; 131 } 132 133 mDate.layout(mDate.getLeft(), mDate.getTop(), newDateRight, mDate.getBottom()); 134 mBackground.setFixedBounds(-mDate.getLeft(), -mDate.getTop(), (r-l), (b-t)); 135 } 136 137 @Override 138 protected void dispatchDraw(Canvas canvas) { 139 super.dispatchDraw(canvas); 140 int alpha = getCurAlpha(); 141 if (alpha != 0) { 142 canvas.drawARGB(alpha, 0, 0, 0); 143 } 144 if (alpha != mEndAlpha) { 145 invalidate(); 146 } 147 } 148 149 /** 150 * Gets the left position of v in this view. Throws if v is not 151 * a child of this. 152 */ 153 private int getViewOffset(View v) { 154 int offset = 0; 155 while (v != this) { 156 offset += v.getLeft(); 157 ViewParent p = v.getParent(); 158 if (v instanceof View) { 159 v = (View)p; 160 } else { 161 throw new RuntimeException(v + " is not a child of " + this); 162 } 163 } 164 return offset; 165 } 166 167 private int getDateSize(ViewGroup g, int w, int offset) { 168 final int N = g.getChildCount(); 169 for (int i=0; i<N; i++) { 170 View v = g.getChildAt(i); 171 int l = v.getLeft() + offset; 172 int r = v.getRight() + offset; 173 if (w >= l && w <= r) { 174 return r; 175 } 176 } 177 return -1; 178 } 179 180 /** 181 * Ensure that, if there is no target under us to receive the touch, 182 * that we process it ourself. This makes sure that onInterceptTouchEvent() 183 * is always called for the entire gesture. 184 */ 185 @Override 186 public boolean onTouchEvent(MotionEvent event) { 187 if (!mCapturingEvents) { 188 return false; 189 } 190 if (event.getAction() != MotionEvent.ACTION_DOWN) { 191 mService.interceptTouchEvent(event); 192 } 193 return true; 194 } 195 196 @Override 197 public boolean onInterceptTouchEvent(MotionEvent event) { 198 if (event.getAction() == MotionEvent.ACTION_DOWN) { 199 if (mButtonBounds.contains((int)event.getX(), (int)event.getY())) { 200 mCapturingEvents = false; 201 return false; 202 } 203 } 204 mCapturingEvents = true; 205 return mService.interceptTouchEvent(event) 206 ? true : super.onInterceptTouchEvent(event); 207 } 208 209 @Override 210 public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { 211 if (super.onRequestSendAccessibilityEvent(child, event)) { 212 // The status bar is very small so augment the view that the user is touching 213 // with the content of the status bar a whole. This way an accessibility service 214 // may announce the current item as well as the entire content if appropriate. 215 AccessibilityEvent record = AccessibilityEvent.obtain(); 216 onInitializeAccessibilityEvent(record); 217 dispatchPopulateAccessibilityEvent(record); 218 event.appendRecord(record); 219 return true; 220 } 221 return false; 222 } 223} 224