KeyButtonView.java revision 5298582717494098fcdf115d832c8e871340d0b5
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.policy; 18 19import android.animation.Animator; 20import android.animation.AnimatorSet; 21import android.animation.ObjectAnimator; 22import android.content.Context; 23import android.content.res.TypedArray; 24import android.graphics.drawable.AnimationDrawable; 25import android.graphics.drawable.Drawable; 26import android.graphics.Canvas; 27import android.graphics.RectF; 28import android.os.RemoteException; 29import android.os.SystemClock; 30import android.os.ServiceManager; 31import android.util.AttributeSet; 32import android.util.Slog; 33import android.view.accessibility.AccessibilityEvent; 34import android.view.HapticFeedbackConstants; 35import android.view.IWindowManager; 36import android.view.InputDevice; 37import android.view.KeyCharacterMap; 38import android.view.KeyEvent; 39import android.view.MotionEvent; 40import android.view.SoundEffectConstants; 41import android.view.View; 42import android.view.ViewConfiguration; 43import android.view.ViewGroup; 44import android.widget.ImageView; 45import android.widget.RemoteViews.RemoteView; 46 47import com.android.systemui.R; 48 49public class KeyButtonView extends ImageView { 50 private static final String TAG = "StatusBar.KeyButtonView"; 51 52 IWindowManager mWindowManager; 53 long mDownTime; 54 boolean mSending; 55 int mCode; 56 int mRepeat; 57 int mTouchSlop; 58 Drawable mGlowBG; 59 float mGlowAlpha = 0f, mGlowScale = 1f, mDrawingAlpha = 1f; 60 61 Runnable mCheckLongPress = new Runnable() { 62 public void run() { 63 if (isPressed()) { 64 65 if (mCode != 0) { 66 mRepeat++; 67 sendEvent(KeyEvent.ACTION_DOWN, 68 KeyEvent.FLAG_FROM_SYSTEM 69 | KeyEvent.FLAG_VIRTUAL_HARD_KEY 70 | KeyEvent.FLAG_LONG_PRESS); 71 72 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 73 } else { 74 // Just an old-fashioned ImageView 75 performLongClick(); 76 } 77 } 78 } 79 }; 80 81 public KeyButtonView(Context context, AttributeSet attrs) { 82 this(context, attrs, 0); 83 } 84 85 public KeyButtonView(Context context, AttributeSet attrs, int defStyle) { 86 super(context, attrs); 87 88 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyButtonView, 89 defStyle, 0); 90 91 mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0); 92 93 mGlowBG = a.getDrawable(R.styleable.KeyButtonView_glowBackground); 94 if (mGlowBG != null) { 95 mDrawingAlpha = 0.5f; 96 } 97 98 a.recycle(); 99 100 mWindowManager = IWindowManager.Stub.asInterface( 101 ServiceManager.getService(Context.WINDOW_SERVICE)); 102 103 setClickable(true); 104 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 105 } 106 107 @Override 108 protected void onDraw(Canvas canvas) { 109 if (mGlowBG != null) { 110 canvas.save(); 111 final int w = getWidth(); 112 final int h = getHeight(); 113 canvas.scale(mGlowScale, mGlowScale, w*0.5f, h*0.5f); 114 mGlowBG.setBounds(0, 0, w, h); 115 mGlowBG.setAlpha((int)(mGlowAlpha * 255)); 116 mGlowBG.draw(canvas); 117 canvas.restore(); 118 119 canvas.saveLayerAlpha(null, (int)(mDrawingAlpha * 255), Canvas.ALL_SAVE_FLAG); 120 } 121 super.onDraw(canvas); 122 if (mGlowBG != null) { 123 canvas.restore(); 124 } 125 } 126 127 public float getDrawingAlpha() { 128 if (mGlowBG == null) return 0; 129 return mDrawingAlpha; 130 } 131 132 public void setDrawingAlpha(float x) { 133 if (mGlowBG == null) return; 134 mDrawingAlpha = x; 135 invalidate(); 136 } 137 138 public float getGlowAlpha() { 139 if (mGlowBG == null) return 0; 140 return mGlowAlpha; 141 } 142 143 public void setGlowAlpha(float x) { 144 if (mGlowBG == null) return; 145 mGlowAlpha = x; 146 invalidate(); 147 } 148 149 public float getGlowScale() { 150 if (mGlowBG == null) return 0; 151 return mGlowScale; 152 } 153 154 public void setGlowScale(float x) { 155 if (mGlowBG == null) return; 156 mGlowScale = x; 157 final float w = getWidth(); 158 final float h = getHeight(); 159 if (x < 1.0f) { 160 invalidate(); 161 } else { 162 final float rx = (w * (x - 1.0f)) / 2.0f; 163 final float ry = (h * (x - 1.0f)) / 2.0f; 164 com.android.systemui.SwipeHelper.invalidateGlobalRegion( 165 this, 166 new RectF(getLeft() - rx, 167 getTop() - ry, 168 getRight() + rx, 169 getBottom() + ry)); 170 } 171 } 172 173 public void setPressed(boolean pressed) { 174 if (mGlowBG != null) { 175 if (pressed != isPressed()) { 176 AnimatorSet as = new AnimatorSet(); 177 if (pressed) { 178 if (mGlowScale < 1.7f) mGlowScale = 1.7f; 179 if (mGlowAlpha < 0.5f) mGlowAlpha = 0.5f; 180 setDrawingAlpha(1f); 181 as.playTogether( 182 ObjectAnimator.ofFloat(this, "glowAlpha", 1f), 183 ObjectAnimator.ofFloat(this, "glowScale", 1.8f) 184 ); 185 as.setDuration(50); 186 } else { 187 as.playTogether( 188 ObjectAnimator.ofFloat(this, "glowAlpha", 0f), 189 ObjectAnimator.ofFloat(this, "glowScale", 1f), 190 ObjectAnimator.ofFloat(this, "drawingAlpha", 0.5f) 191 ); 192 as.setDuration(500); 193 } 194 as.start(); 195 } 196 } 197 super.setPressed(pressed); 198 } 199 200 public boolean onTouchEvent(MotionEvent ev) { 201 final int action = ev.getAction(); 202 int x, y; 203 204 switch (action) { 205 case MotionEvent.ACTION_DOWN: 206 //Slog.d("KeyButtonView", "press"); 207 mDownTime = SystemClock.uptimeMillis(); 208 mRepeat = 0; 209 mSending = true; 210 sendEvent(KeyEvent.ACTION_DOWN, 211 KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, mDownTime); 212 setPressed(true); 213 removeCallbacks(mCheckLongPress); 214 postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout()); 215 break; 216 case MotionEvent.ACTION_MOVE: 217 if (mSending) { 218 x = (int)ev.getX(); 219 y = (int)ev.getY(); 220 setPressed(x >= -mTouchSlop 221 && x < getWidth() + mTouchSlop 222 && y >= -mTouchSlop 223 && y < getHeight() + mTouchSlop); 224 } 225 break; 226 case MotionEvent.ACTION_CANCEL: 227 setPressed(false); 228 if (mSending) { 229 mSending = false; 230 sendEvent(KeyEvent.ACTION_UP, 231 KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY 232 | KeyEvent.FLAG_CANCELED); 233 removeCallbacks(mCheckLongPress); 234 } 235 break; 236 case MotionEvent.ACTION_UP: 237 final boolean doIt = isPressed(); 238 setPressed(false); 239 if (mSending) { 240 mSending = false; 241 final int flags = KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY; 242 removeCallbacks(mCheckLongPress); 243 244 if (mCode != 0) { 245 if (doIt) { 246 sendEvent(KeyEvent.ACTION_UP, flags); 247 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 248 playSoundEffect(SoundEffectConstants.CLICK); 249 } else { 250 sendEvent(KeyEvent.ACTION_UP, flags | KeyEvent.FLAG_CANCELED); 251 } 252 } else { 253 // no key code, just a regular ImageView 254 if (doIt) performClick(); 255 } 256 } 257 break; 258 } 259 260 return true; 261 } 262 263 void sendEvent(int action, int flags) { 264 sendEvent(action, flags, SystemClock.uptimeMillis()); 265 } 266 267 void sendEvent(int action, int flags, long when) { 268 final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, mRepeat, 269 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags, InputDevice.SOURCE_KEYBOARD); 270 try { 271 //Slog.d(TAG, "injecting event " + ev); 272 mWindowManager.injectInputEventNoWait(ev); 273 } catch (RemoteException ex) { 274 // System process is dead 275 } 276 } 277} 278 279 280