/*
|
* 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.
|
*/
|
|
package com.android.keyguard;
|
|
import android.annotation.NonNull;
|
import android.content.Context;
|
import android.content.res.ColorStateList;
|
import android.content.res.TypedArray;
|
import android.graphics.Rect;
|
import android.util.AttributeSet;
|
import android.util.Log;
|
import android.view.MotionEvent;
|
import android.view.View;
|
import android.view.ViewDebug;
|
import android.view.ViewGroup;
|
import android.view.ViewHierarchyEncoder;
|
import android.widget.FrameLayout;
|
import android.widget.ViewFlipper;
|
|
import com.android.internal.widget.LockPatternUtils;
|
|
/**
|
* Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
|
* we can emulate {@link android.view.WindowManager.LayoutParams#FLAG_SLIPPERY} within a view
|
* hierarchy.
|
*/
|
public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
|
private static final String TAG = "KeyguardSecurityViewFlipper";
|
private static final boolean DEBUG = KeyguardConstants.DEBUG;
|
|
private Rect mTempRect = new Rect();
|
|
public KeyguardSecurityViewFlipper(Context context) {
|
this(context, null);
|
}
|
|
public KeyguardSecurityViewFlipper(Context context, AttributeSet attr) {
|
super(context, attr);
|
}
|
|
@Override
|
public boolean onTouchEvent(MotionEvent ev) {
|
boolean result = super.onTouchEvent(ev);
|
mTempRect.set(0, 0, 0, 0);
|
for (int i = 0; i < getChildCount(); i++) {
|
View child = getChildAt(i);
|
if (child.getVisibility() == View.VISIBLE) {
|
offsetRectIntoDescendantCoords(child, mTempRect);
|
ev.offsetLocation(mTempRect.left, mTempRect.top);
|
result = child.dispatchTouchEvent(ev) || result;
|
ev.offsetLocation(-mTempRect.left, -mTempRect.top);
|
}
|
}
|
return result;
|
}
|
|
KeyguardSecurityView getSecurityView() {
|
View child = getChildAt(getDisplayedChild());
|
if (child instanceof KeyguardSecurityView) {
|
return (KeyguardSecurityView) child;
|
}
|
return null;
|
}
|
|
@Override
|
public void setKeyguardCallback(KeyguardSecurityCallback callback) {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.setKeyguardCallback(callback);
|
}
|
}
|
|
@Override
|
public void setLockPatternUtils(LockPatternUtils utils) {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.setLockPatternUtils(utils);
|
}
|
}
|
|
@Override
|
public void reset() {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.reset();
|
}
|
}
|
|
@Override
|
public void onPause() {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.onPause();
|
}
|
}
|
|
@Override
|
public void onResume(int reason) {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.onResume(reason);
|
}
|
}
|
|
@Override
|
public boolean needsInput() {
|
KeyguardSecurityView ksv = getSecurityView();
|
return (ksv != null) ? ksv.needsInput() : false;
|
}
|
|
@Override
|
public KeyguardSecurityCallback getCallback() {
|
KeyguardSecurityView ksv = getSecurityView();
|
return (ksv != null) ? ksv.getCallback() : null;
|
}
|
|
@Override
|
public void showPromptReason(int reason) {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.showPromptReason(reason);
|
}
|
}
|
|
@Override
|
public void showMessage(CharSequence message, ColorStateList colorState) {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.showMessage(message, colorState);
|
}
|
}
|
|
@Override
|
public void showUsabilityHint() {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.showUsabilityHint();
|
}
|
}
|
|
@Override
|
public void startAppearAnimation() {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
ksv.startAppearAnimation();
|
}
|
}
|
|
@Override
|
public boolean startDisappearAnimation(Runnable finishRunnable) {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
return ksv.startDisappearAnimation(finishRunnable);
|
} else {
|
return false;
|
}
|
}
|
|
@Override
|
public CharSequence getTitle() {
|
KeyguardSecurityView ksv = getSecurityView();
|
if (ksv != null) {
|
return ksv.getTitle();
|
}
|
return "";
|
}
|
|
@Override
|
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
|
return p instanceof LayoutParams;
|
}
|
|
@Override
|
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) : new LayoutParams(p);
|
}
|
|
@Override
|
public LayoutParams generateLayoutParams(AttributeSet attrs) {
|
return new LayoutParams(getContext(), attrs);
|
}
|
|
@Override
|
protected void onMeasure(int widthSpec, int heightSpec) {
|
final int widthMode = MeasureSpec.getMode(widthSpec);
|
final int heightMode = MeasureSpec.getMode(heightSpec);
|
if (DEBUG && widthMode != MeasureSpec.AT_MOST) {
|
Log.w(TAG, "onMeasure: widthSpec " + MeasureSpec.toString(widthSpec) +
|
" should be AT_MOST");
|
}
|
if (DEBUG && heightMode != MeasureSpec.AT_MOST) {
|
Log.w(TAG, "onMeasure: heightSpec " + MeasureSpec.toString(heightSpec) +
|
" should be AT_MOST");
|
}
|
|
final int widthSize = MeasureSpec.getSize(widthSpec);
|
final int heightSize = MeasureSpec.getSize(heightSpec);
|
int maxWidth = widthSize;
|
int maxHeight = heightSize;
|
final int count = getChildCount();
|
for (int i = 0; i < count; i++) {
|
final View child = getChildAt(i);
|
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
|
if (lp.maxWidth > 0 && lp.maxWidth < maxWidth) {
|
maxWidth = lp.maxWidth;
|
}
|
if (lp.maxHeight > 0 && lp.maxHeight < maxHeight) {
|
maxHeight = lp.maxHeight;
|
}
|
}
|
|
final int wPadding = getPaddingLeft() + getPaddingRight();
|
final int hPadding = getPaddingTop() + getPaddingBottom();
|
maxWidth = Math.max(0, maxWidth - wPadding);
|
maxHeight = Math.max(0, maxHeight - hPadding);
|
|
int width = widthMode == MeasureSpec.EXACTLY ? widthSize : 0;
|
int height = heightMode == MeasureSpec.EXACTLY ? heightSize : 0;
|
for (int i = 0; i < count; i++) {
|
final View child = getChildAt(i);
|
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
|
final int childWidthSpec = makeChildMeasureSpec(maxWidth, lp.width);
|
final int childHeightSpec = makeChildMeasureSpec(maxHeight, lp.height);
|
|
child.measure(childWidthSpec, childHeightSpec);
|
|
width = Math.max(width, Math.min(child.getMeasuredWidth(), widthSize - wPadding));
|
height = Math.max(height, Math.min(child.getMeasuredHeight(), heightSize - hPadding));
|
}
|
setMeasuredDimension(width + wPadding, height + hPadding);
|
}
|
|
private int makeChildMeasureSpec(int maxSize, int childDimen) {
|
final int mode;
|
final int size;
|
switch (childDimen) {
|
case LayoutParams.WRAP_CONTENT:
|
mode = MeasureSpec.AT_MOST;
|
size = maxSize;
|
break;
|
case LayoutParams.MATCH_PARENT:
|
mode = MeasureSpec.EXACTLY;
|
size = maxSize;
|
break;
|
default:
|
mode = MeasureSpec.EXACTLY;
|
size = Math.min(maxSize, childDimen);
|
break;
|
}
|
return MeasureSpec.makeMeasureSpec(size, mode);
|
}
|
|
public static class LayoutParams extends FrameLayout.LayoutParams {
|
@ViewDebug.ExportedProperty(category = "layout")
|
public int maxWidth;
|
|
@ViewDebug.ExportedProperty(category = "layout")
|
public int maxHeight;
|
|
public LayoutParams(ViewGroup.LayoutParams other) {
|
super(other);
|
}
|
|
public LayoutParams(LayoutParams other) {
|
super(other);
|
|
maxWidth = other.maxWidth;
|
maxHeight = other.maxHeight;
|
}
|
|
public LayoutParams(Context c, AttributeSet attrs) {
|
super(c, attrs);
|
|
final TypedArray a = c.obtainStyledAttributes(attrs,
|
R.styleable.KeyguardSecurityViewFlipper_Layout, 0, 0);
|
maxWidth = a.getDimensionPixelSize(
|
R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxWidth, 0);
|
maxHeight = a.getDimensionPixelSize(
|
R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxHeight, 0);
|
a.recycle();
|
}
|
|
/** @hide */
|
@Override
|
protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
|
super.encodeProperties(encoder);
|
|
encoder.addProperty("layout:maxWidth", maxWidth);
|
encoder.addProperty("layout:maxHeight", maxHeight);
|
}
|
}
|
}
|