FileDocCategorySizeDatePackage
KeyguardWidgetFrame.javaAPI DocAndroid 5.1 API18024Thu Mar 12 22:22:42 GMT 2015com.android.keyguard

KeyguardWidgetFrame

public class KeyguardWidgetFrame extends android.widget.FrameLayout

Fields Summary
private static final android.graphics.PorterDuffXfermode
sAddBlendMode
static final float
OUTLINE_ALPHA_MULTIPLIER
static final int
HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR
static final boolean
ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY
private int
mGradientColor
private android.graphics.LinearGradient
mForegroundGradient
private android.graphics.LinearGradient
mLeftToRightGradient
private android.graphics.LinearGradient
mRightToLeftGradient
private android.graphics.Paint
mGradientPaint
boolean
mLeftToRight
private float
mOverScrollAmount
private final android.graphics.Rect
mForegroundRect
private int
mForegroundAlpha
private CheckLongPressHelper
mLongPressHelper
private android.animation.Animator
mFrameFade
private boolean
mIsSmall
private android.os.Handler
mWorkerHandler
private float
mBackgroundAlpha
private float
mContentAlpha
private float
mBackgroundAlphaMultiplier
private android.graphics.drawable.Drawable
mBackgroundDrawable
private android.graphics.Rect
mBackgroundRect
private int
mSmallWidgetHeight
private int
mSmallFrameHeight
private boolean
mWidgetLockedSmall
private int
mMaxChallengeTop
private int
mFrameStrokeAdjustment
private boolean
mPerformAppWidgetSizeUpdateOnBootComplete
private int
mFrameHeight
private boolean
mIsHoveringOverDeleteDropTarget
private Object
mBgAlphaController
private KeyguardUpdateMonitorCallback
mUpdateMonitorCallbacks
Constructors Summary
public KeyguardWidgetFrame(android.content.Context context)


       
        this(context, null, 0);
    
public KeyguardWidgetFrame(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, 0);
    
public KeyguardWidgetFrame(android.content.Context context, android.util.AttributeSet attrs, int defStyle)

        super(context, attrs, defStyle);

        mLongPressHelper = new CheckLongPressHelper(this);

        Resources res = context.getResources();
        // TODO: this padding should really correspond to the padding embedded in the background
        // drawable (ie. outlines).
        float density = res.getDisplayMetrics().density;
        int padding = (int) (res.getDisplayMetrics().density * 8);
        setPadding(padding, padding, padding, padding);

        mFrameStrokeAdjustment = 2 + (int) (2 * density);

        // This will be overriden on phones based on the current security mode, however on tablets
        // we need to specify a height.
        mSmallWidgetHeight =
                res.getDimensionPixelSize(R.dimen.kg_small_widget_height);
        mBackgroundDrawable = res.getDrawable(R.drawable.kg_widget_bg_padded);
        mGradientColor = res.getColor(R.color.kg_widget_pager_gradient);
        mGradientPaint.setXfermode(sAddBlendMode);
    
Methods Summary
public voidadjustFrame(int challengeTop)

        int frameHeight = challengeTop + getPaddingBottom();
        setFrameHeight(frameHeight);
    
public voidcancelLongPress()

        super.cancelLongPress();
        mLongPressHelper.cancelLongPress();
    
public voiddisableHardwareLayersForContent()
Because this view has fading outlines, it is essential that we enable hardware layers on the content (child) so that updating the alpha of the outlines doesn't result in the content layer being recreated.

        View widget = getContent();
        if (widget != null) {
            widget.setLayerType(LAYER_TYPE_NONE, null);
        }
    
protected voiddispatchDraw(android.graphics.Canvas canvas)

        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
            canvas.save();
        }
        drawBg(canvas);
        super.dispatchDraw(canvas);
        drawGradientOverlay(canvas);
        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
            drawHoveringOverDeleteOverlay(canvas);
            canvas.restore();
        }
    
protected voiddrawBg(android.graphics.Canvas canvas)

        if (mBackgroundAlpha > 0.0f) {
            Drawable bg = mBackgroundDrawable;

            bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
            bg.setBounds(mBackgroundRect);
            bg.draw(canvas);
        }
    
private voiddrawGradientOverlay(android.graphics.Canvas c)

        mGradientPaint.setShader(mForegroundGradient);
        mGradientPaint.setAlpha(mForegroundAlpha);
        c.drawRect(mForegroundRect, mGradientPaint);
    
private voiddrawHoveringOverDeleteOverlay(android.graphics.Canvas c)

        if (mIsHoveringOverDeleteDropTarget) {
            c.drawColor(HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR);
        }
    
public voidenableHardwareLayersForContent()
Because this view has fading outlines, it is essential that we enable hardware layers on the content (child) so that updating the alpha of the outlines doesn't result in the content layer being recreated.

        View widget = getContent();
        if (widget != null && widget.isHardwareAccelerated()) {
            widget.setLayerType(LAYER_TYPE_HARDWARE, null);
        }
    
public voidfadeFrame(java.lang.Object caller, boolean takeControl, float alpha, int duration)

        if (takeControl) {
            mBgAlphaController = caller;
        }

        if (mBgAlphaController != caller && mBgAlphaController != null) {
            return;
        }

        if (mFrameFade != null) {
            mFrameFade.cancel();
            mFrameFade = null;
        }
        PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", alpha);
        mFrameFade = ObjectAnimator.ofPropertyValuesHolder(this, bgAlpha);
        mFrameFade.setDuration(duration);
        mFrameFade.start();
    
public floatgetBackgroundAlpha()

        return mBackgroundAlpha;
    
public floatgetBackgroundAlphaMultiplier()

        return mBackgroundAlphaMultiplier;
    
public android.view.ViewgetContent()

        return getChildAt(0);
    
public floatgetContentAlpha()

        return mContentAlpha;
    
public intgetContentAppWidgetId()

        View content = getContent();
        if (content instanceof AppWidgetHostView) {
            return ((AppWidgetHostView) content).getAppWidgetId();
        } else if (content instanceof KeyguardStatusView) {
            return ((KeyguardStatusView) content).getAppWidgetId();
        } else {
            return AppWidgetManager.INVALID_APPWIDGET_ID;
        }
    
public intgetSmallFrameHeight()

        return mSmallFrameHeight;
    
public android.os.HandlergetWorkerHandler()

        return mWorkerHandler;
    
public voidhideFrame(java.lang.Object caller)

        fadeFrame(caller, false, 0f, KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_OUT_DURATION);
    
public booleanisSmall()

        return mIsSmall;
    
public voidonActive(boolean isActive)

        // hook for subclasses
    
protected voidonAttachedToWindow()

        super.onAttachedToWindow();
        KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
    
public voidonBouncerShowing(boolean showing)

        // hook for subclasses
    
protected voidonDetachedFromWindow()

        super.onDetachedFromWindow();
        cancelLongPress();
        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);

    
public booleanonInterceptTouchEvent(android.view.MotionEvent ev)

        // Watch for longpress events at this level to make sure
        // users can always pick up this widget
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLongPressHelper.postCheckForLongPress(ev);
                break;
            case MotionEvent.ACTION_MOVE:
                mLongPressHelper.onMove(ev);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mLongPressHelper.cancelLongPress();
                break;
        }

        // Otherwise continue letting touch events fall through to children
        return false;
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        performAppWidgetSizeCallbacksIfNecessary();
    
protected voidonSizeChanged(int w, int h, int oldw, int oldh)

        super.onSizeChanged(w, h, oldw, oldh);

        if (!mIsSmall) {
            mFrameHeight = h;
        }

        // mFrameStrokeAdjustment is a cludge to prevent the overlay from drawing outside the
        // rounded rect background.
        mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,
                w - mFrameStrokeAdjustment, Math.min(h, mFrameHeight) - mFrameStrokeAdjustment);

        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(h, mFrameHeight));
        updateGradient();
        invalidate();
    
public booleanonTouchEvent(android.view.MotionEvent ev)

        // Watch for longpress events at this level to make sure
        // users can always pick up this widget
        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                mLongPressHelper.onMove(ev);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mLongPressHelper.cancelLongPress();
                break;
        }

        // We return true here to ensure that we will get cancel / up signal
        // even if none of our children have requested touch.
        return true;
    
public booleanonUserInteraction(android.view.MotionEvent event)

        // hook for subclasses
        return false;
    
private voidperformAppWidgetSizeCallbacksIfNecessary()

        View content = getContent();
        if (!(content instanceof AppWidgetHostView)) return;

        if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
            mPerformAppWidgetSizeUpdateOnBootComplete = true;
            return;
        }

        // TODO: there's no reason to force the AppWidgetHostView to catch duplicate size calls.
        // We can do that even more cheaply here. It's not an issue right now since we're in the
        // system process and hence no binder calls.
        AppWidgetHostView awhv = (AppWidgetHostView) content;
        float density = getResources().getDisplayMetrics().density;

        int width = (int) (content.getMeasuredWidth() / density);
        int height = (int) (content.getMeasuredHeight() / density);
        awhv.updateAppWidgetSize(null, width, height, width, height, true);
    
public voidrequestDisallowInterceptTouchEvent(boolean disallowIntercept)

        super.requestDisallowInterceptTouchEvent(disallowIntercept);
        cancelLongPress();
    
public voidresetSize()

        mIsSmall = false;
        if (!mWidgetLockedSmall) {
            setWidgetHeight(LayoutParams.MATCH_PARENT);
        }
        setFrameHeight(getMeasuredHeight());
    
public voidsetBackgroundAlpha(float alpha)

        if (Float.compare(mBackgroundAlpha, alpha) != 0) {
            mBackgroundAlpha = alpha;
            invalidate();
        }
    
public voidsetBackgroundAlphaMultiplier(float multiplier)

        if (Float.compare(mBackgroundAlphaMultiplier, multiplier) != 0) {
            mBackgroundAlphaMultiplier = multiplier;
            invalidate();
        }
    
public voidsetContentAlpha(float alpha)

        mContentAlpha = alpha;
        View content = getContent();
        if (content != null) {
            content.setAlpha(alpha);
        }
    
public voidsetFrameHeight(int height)

        mFrameHeight = height;
        mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(mFrameHeight, getMeasuredHeight()));
        mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,getMeasuredWidth() -
                mFrameStrokeAdjustment, Math.min(getMeasuredHeight(), mFrameHeight) -
                mFrameStrokeAdjustment);
        updateGradient();
        invalidate();
    
voidsetIsHoveringOverDeleteDropTarget(boolean isHovering)


       
        if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
            if (mIsHoveringOverDeleteDropTarget != isHovering) {
                mIsHoveringOverDeleteDropTarget = isHovering;
                int resId = isHovering ? R.string.keyguard_accessibility_delete_widget_start
                        : R.string.keyguard_accessibility_delete_widget_end;
                String text = getContext().getResources().getString(resId, getContentDescription());
                announceForAccessibility(text);
                invalidate();
            }
        }
    
public voidsetMaxChallengeTop(int top)

        boolean dirty = mMaxChallengeTop != top;
        mMaxChallengeTop = top;
        mSmallWidgetHeight = top - getPaddingTop();
        mSmallFrameHeight = top + getPaddingBottom();
        if (dirty && mIsSmall) {
            setWidgetHeight(mSmallWidgetHeight);
            setFrameHeight(mSmallFrameHeight);
        } else if (dirty && mWidgetLockedSmall) {
            setWidgetHeight(mSmallWidgetHeight);
        }
    
voidsetOverScrollAmount(float r, boolean left)

        if (Float.compare(mOverScrollAmount, r) != 0) {
            mOverScrollAmount = r;
            mForegroundGradient = left ? mLeftToRightGradient : mRightToLeftGradient;
            mForegroundAlpha = (int) Math.round((0.5f * r * 255));

            // We bump up the alpha of the outline to hide the fact that the overlay is drawing
            // over the rounded part of the frame.
            float bgAlpha = Math.min(OUTLINE_ALPHA_MULTIPLIER + r * (1 - OUTLINE_ALPHA_MULTIPLIER),
                    1f);
            setBackgroundAlpha(bgAlpha);
            invalidate();
        }
    
private voidsetWidgetHeight(int height)
Depending on whether the security is up, the widget size needs to change

param
height The height of the widget, -1 for full height

        boolean needLayout = false;
        View widget = getContent();
        if (widget != null) {
            LayoutParams lp = (LayoutParams) widget.getLayoutParams();
            if (lp.height != height) {
                needLayout = true;
                lp.height = height;
            }
        }
        if (needLayout) {
            requestLayout();
        }
    
public voidsetWidgetLockedSmall(boolean locked)

        if (locked) {
            setWidgetHeight(mSmallWidgetHeight);
        }
        mWidgetLockedSmall = locked;
    
public voidsetWorkerHandler(android.os.Handler workerHandler)

        mWorkerHandler = workerHandler;
    
public voidshowFrame(java.lang.Object caller)

        fadeFrame(caller, true, OUTLINE_ALPHA_MULTIPLIER,
                KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_IN_DURATION);
    
public voidshrinkWidget(boolean alsoShrinkFrame)

        mIsSmall = true;
        setWidgetHeight(mSmallWidgetHeight);

        if (alsoShrinkFrame) {
            setFrameHeight(mSmallFrameHeight);
        }
    
private voidupdateGradient()

        float x0 = mLeftToRight ? 0 : mForegroundRect.width();
        float x1 = mLeftToRight ? mForegroundRect.width(): 0;
        mLeftToRightGradient = new LinearGradient(x0, 0f, x1, 0f,
                mGradientColor, 0, Shader.TileMode.CLAMP);
        mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
                mGradientColor, 0, Shader.TileMode.CLAMP);