KeyguardSecurityViewFlipper.java revision 25a272a9f6323f6a3513bb522d45e839449878ce
1/* 2 * Copyright (C) 2012 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.internal.policy.impl.keyguard; 18 19import com.android.internal.R; 20import com.android.internal.widget.LockPatternUtils; 21 22import android.content.Context; 23import android.content.res.TypedArray; 24import android.graphics.Rect; 25import android.util.AttributeSet; 26import android.util.Log; 27import android.view.MotionEvent; 28import android.view.View; 29import android.view.ViewDebug; 30import android.view.ViewGroup; 31import android.view.WindowManager; 32import android.widget.FrameLayout; 33import android.widget.ViewFlipper; 34 35/** 36 * Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so 37 * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy. 38 * 39 */ 40public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView { 41 private static final String TAG = "KeyguardSecurityViewFlipper"; 42 private static final boolean DEBUG = false; 43 44 private Rect mTempRect = new Rect(); 45 46 public KeyguardSecurityViewFlipper(Context context) { 47 this(context, null); 48 } 49 50 public KeyguardSecurityViewFlipper(Context context, AttributeSet attr) { 51 super(context, attr); 52 } 53 54 @Override 55 public boolean onTouchEvent(MotionEvent ev) { 56 boolean result = super.onTouchEvent(ev); 57 mTempRect.set(0, 0, 0, 0); 58 for (int i = 0; i < getChildCount(); i++) { 59 View child = getChildAt(i); 60 if (child.getVisibility() == View.VISIBLE) { 61 offsetRectIntoDescendantCoords(child, mTempRect); 62 ev.offsetLocation(mTempRect.left, mTempRect.top); 63 result = child.dispatchTouchEvent(ev) || result; 64 ev.offsetLocation(-mTempRect.left, -mTempRect.top); 65 } 66 } 67 return result; 68 } 69 70 KeyguardSecurityView getSecurityView() { 71 View child = getChildAt(getDisplayedChild()); 72 if (child instanceof KeyguardSecurityView) { 73 return (KeyguardSecurityView) child; 74 } 75 return null; 76 } 77 78 @Override 79 public void setKeyguardCallback(KeyguardSecurityCallback callback) { 80 KeyguardSecurityView ksv = getSecurityView(); 81 if (ksv != null) { 82 ksv.setKeyguardCallback(callback); 83 } 84 } 85 86 @Override 87 public void setLockPatternUtils(LockPatternUtils utils) { 88 KeyguardSecurityView ksv = getSecurityView(); 89 if (ksv != null) { 90 ksv.setLockPatternUtils(utils); 91 } 92 } 93 94 @Override 95 public void reset() { 96 KeyguardSecurityView ksv = getSecurityView(); 97 if (ksv != null) { 98 ksv.reset(); 99 } 100 } 101 102 @Override 103 public void onPause() { 104 KeyguardSecurityView ksv = getSecurityView(); 105 if (ksv != null) { 106 ksv.onPause(); 107 } 108 } 109 110 @Override 111 public void onResume(int reason) { 112 KeyguardSecurityView ksv = getSecurityView(); 113 if (ksv != null) { 114 ksv.onResume(reason); 115 } 116 } 117 118 @Override 119 public boolean needsInput() { 120 KeyguardSecurityView ksv = getSecurityView(); 121 return (ksv != null) ? ksv.needsInput() : false; 122 } 123 124 @Override 125 public KeyguardSecurityCallback getCallback() { 126 KeyguardSecurityView ksv = getSecurityView(); 127 return (ksv != null) ? ksv.getCallback() : null; 128 } 129 130 @Override 131 public void showUsabilityHint() { 132 KeyguardSecurityView ksv = getSecurityView(); 133 if (ksv != null) { 134 ksv.showUsabilityHint(); 135 } 136 } 137 138 @Override 139 public void showBouncer(int duration) { 140 KeyguardSecurityView active = getSecurityView(); 141 for (int i = 0; i < getChildCount(); i++) { 142 View child = getChildAt(i); 143 if (child instanceof KeyguardSecurityView) { 144 KeyguardSecurityView ksv = (KeyguardSecurityView) child; 145 ksv.showBouncer(ksv == active ? duration : 0); 146 } 147 } 148 } 149 150 @Override 151 public void hideBouncer(int duration) { 152 KeyguardSecurityView active = getSecurityView(); 153 for (int i = 0; i < getChildCount(); i++) { 154 View child = getChildAt(i); 155 if (child instanceof KeyguardSecurityView) { 156 KeyguardSecurityView ksv = (KeyguardSecurityView) child; 157 ksv.hideBouncer(ksv == active ? duration : 0); 158 } 159 } 160 } 161 162 @Override 163 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 164 return p instanceof LayoutParams; 165 } 166 167 @Override 168 protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 169 return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) : new LayoutParams(p); 170 } 171 172 @Override 173 public LayoutParams generateLayoutParams(AttributeSet attrs) { 174 return new LayoutParams(getContext(), attrs); 175 } 176 177 @Override 178 protected void onMeasure(int widthSpec, int heightSpec) { 179 final int widthMode = MeasureSpec.getMode(widthSpec); 180 final int heightMode = MeasureSpec.getMode(heightSpec); 181 if (DEBUG && widthMode != MeasureSpec.AT_MOST) { 182 Log.w(TAG, "onMeasure: widthSpec " + MeasureSpec.toString(widthSpec) + 183 " should be AT_MOST"); 184 } 185 if (DEBUG && heightMode != MeasureSpec.AT_MOST) { 186 Log.w(TAG, "onMeasure: heightSpec " + MeasureSpec.toString(heightSpec) + 187 " should be AT_MOST"); 188 } 189 190 final int widthSize = MeasureSpec.getSize(widthSpec); 191 final int heightSize = MeasureSpec.getSize(heightSpec); 192 int maxWidth = widthSize; 193 int maxHeight = heightSize; 194 final int count = getChildCount(); 195 for (int i = 0; i < count; i++) { 196 final View child = getChildAt(i); 197 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 198 199 if (lp.maxWidth > 0 && lp.maxWidth < maxWidth) { 200 maxWidth = lp.maxWidth; 201 } 202 if (lp.maxHeight > 0 && lp.maxHeight < maxHeight) { 203 maxHeight = lp.maxHeight; 204 } 205 } 206 207 final int wPadding = getPaddingLeft() + getPaddingRight(); 208 final int hPadding = getPaddingTop() + getPaddingBottom(); 209 maxWidth -= wPadding; 210 maxHeight -= hPadding; 211 212 int width = widthMode == MeasureSpec.EXACTLY ? widthSize : 0; 213 int height = heightMode == MeasureSpec.EXACTLY ? heightSize : 0; 214 for (int i = 0; i < count; i++) { 215 final View child = getChildAt(i); 216 final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 217 218 final int childWidthSpec = makeChildMeasureSpec(maxWidth, lp.width); 219 final int childHeightSpec = makeChildMeasureSpec(maxHeight, lp.height); 220 221 child.measure(childWidthSpec, childHeightSpec); 222 223 width = Math.max(width, Math.min(child.getMeasuredWidth(), widthSize - wPadding)); 224 height = Math.max(height, Math.min(child.getMeasuredHeight(), heightSize - hPadding)); 225 } 226 setMeasuredDimension(width + wPadding, height + hPadding); 227 } 228 229 private int makeChildMeasureSpec(int maxSize, int childDimen) { 230 final int mode; 231 final int size; 232 switch (childDimen) { 233 case LayoutParams.WRAP_CONTENT: 234 mode = MeasureSpec.AT_MOST; 235 size = maxSize; 236 break; 237 case LayoutParams.MATCH_PARENT: 238 mode = MeasureSpec.EXACTLY; 239 size = maxSize; 240 break; 241 default: 242 mode = MeasureSpec.EXACTLY; 243 size = Math.min(maxSize, childDimen); 244 break; 245 } 246 return MeasureSpec.makeMeasureSpec(size, mode); 247 } 248 249 public static class LayoutParams extends FrameLayout.LayoutParams { 250 @ViewDebug.ExportedProperty(category = "layout") 251 public int maxWidth; 252 253 @ViewDebug.ExportedProperty(category = "layout") 254 public int maxHeight; 255 256 public LayoutParams(ViewGroup.LayoutParams other) { 257 super(other); 258 } 259 260 public LayoutParams(LayoutParams other) { 261 super(other); 262 263 maxWidth = other.maxWidth; 264 maxHeight = other.maxHeight; 265 } 266 267 public LayoutParams(Context c, AttributeSet attrs) { 268 super(c, attrs); 269 270 final TypedArray a = c.obtainStyledAttributes(attrs, 271 R.styleable.KeyguardSecurityViewFlipper_Layout, 0, 0); 272 maxWidth = a.getDimensionPixelSize( 273 R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxWidth, 0); 274 maxHeight = a.getDimensionPixelSize( 275 R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxHeight, 0); 276 a.recycle(); 277 } 278 } 279} 280