FileDocCategorySizeDatePackage
PasswordTextView.javaAPI DocAndroid 5.1 API26408Thu Mar 12 22:22:42 GMT 2015com.android.keyguard

PasswordTextView

public class PasswordTextView extends android.view.View
A View similar to a textView which contains password text and can animate when the text is changed

Fields Summary
private static final float
DOT_OVERSHOOT_FACTOR
private static final long
DOT_APPEAR_DURATION_OVERSHOOT
private static final long
APPEAR_DURATION
private static final long
DISAPPEAR_DURATION
private static final long
RESET_DELAY_PER_ELEMENT
private static final long
RESET_MAX_DELAY
private static final long
DOT_APPEAR_TEXT_DISAPPEAR_OVERLAP_DURATION
The overlap between the text disappearing and the dot appearing animation
private static final long
TEXT_REST_DURATION_AFTER_APPEAR
The duration the text needs to stay there at least before it can morph into a dot
private static final long
TEXT_VISIBILITY_DURATION
The duration the text should be visible, starting with the appear animation
private static final float
OVERSHOOT_TIME_POSITION
The position in time from [0,1] where the overshoot should be finished and the settle back animation of the dot should start
private final int
mTextHeightRaw
The raw text size, will be multiplied by the scaled density when drawn
private ArrayList
mTextChars
private String
mText
private Stack
mCharPool
private int
mDotSize
private android.os.PowerManager
mPM
private int
mCharPadding
private final android.graphics.Paint
mDrawPaint
private android.view.animation.Interpolator
mAppearInterpolator
private android.view.animation.Interpolator
mDisappearInterpolator
private android.view.animation.Interpolator
mFastOutSlowInInterpolator
private boolean
mShowPassword
Constructors Summary
public PasswordTextView(android.content.Context context)


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

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

        this(context, attrs, defStyleAttr, 0);
    
public PasswordTextView(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes)

        super(context, attrs, defStyleAttr, defStyleRes);
        setFocusableInTouchMode(true);
        setFocusable(true);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PasswordTextView);
        try {
            mTextHeightRaw = a.getInt(R.styleable.PasswordTextView_scaledTextSize, 0);
        } finally {
            a.recycle();
        }
        mDrawPaint.setFlags(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
        mDrawPaint.setTextAlign(Paint.Align.CENTER);
        mDrawPaint.setColor(0xffffffff);
        mDrawPaint.setTypeface(Typeface.create("sans-serif-light", 0));
        mDotSize = getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size);
        mCharPadding = getContext().getResources().getDimensionPixelSize(R.dimen
                .password_char_padding);
        mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
        mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
                android.R.interpolator.linear_out_slow_in);
        mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
                android.R.interpolator.fast_out_linear_in);
        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext,
                android.R.interpolator.fast_out_slow_in);
        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    
Methods Summary
public voidappend(char c)

        int visibleChars = mTextChars.size();
        String textbefore = mText;
        mText = mText + c;
        int newLength = mText.length();
        CharState charState;
        if (newLength > visibleChars) {
            charState = obtainCharState(c);
            mTextChars.add(charState);
        } else {
            charState = mTextChars.get(newLength - 1);
            charState.whichChar = c;
        }
        charState.startAppearAnimation();

        // ensure that the previous element is being swapped
        if (newLength > 1) {
            CharState previousState = mTextChars.get(newLength - 2);
            if (previousState.isDotSwapPending) {
                previousState.swapToDotWhenAppearFinished();
            }
        }
        userActivity();
        sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length(), 0, 1);
    
public voiddeleteLastChar()

        int length = mText.length();
        String textbefore = mText;
        if (length > 0) {
            mText = mText.substring(0, length - 1);
            CharState charState = mTextChars.get(length - 1);
            charState.startRemoveAnimation(0, 0);
        }
        userActivity();
        sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
    
private android.graphics.RectgetCharBounds()

        float textHeight = mTextHeightRaw * getResources().getDisplayMetrics().scaledDensity;
        mDrawPaint.setTextSize(textHeight);
        Rect bounds = new Rect();
        mDrawPaint.getTextBounds("0", 0, 1, bounds);
        return bounds;
    
private floatgetDrawingWidth()

        int width = 0;
        int length = mTextChars.size();
        Rect bounds = getCharBounds();
        int charLength = bounds.right - bounds.left;
        for (int i = 0; i < length; i++) {
            CharState charState = mTextChars.get(i);
            if (i != 0) {
                width += mCharPadding * charState.currentWidthFactor;
            }
            width += charLength * charState.currentWidthFactor;
        }
        return width;
    
public java.lang.StringgetText()

        return mText;
    
public booleanhasOverlappingRendering()

        return false;
    
private com.android.keyguard.PasswordTextView$CharStateobtainCharState(char c)

        CharState charState;
        if(mCharPool.isEmpty()) {
            charState = new CharState();
        } else {
            charState = mCharPool.pop();
            charState.reset();
        }
        charState.whichChar = c;
        return charState;
    
protected voidonDraw(android.graphics.Canvas canvas)

        float totalDrawingWidth = getDrawingWidth();
        float currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2;
        int length = mTextChars.size();
        Rect bounds = getCharBounds();
        int charHeight = (bounds.bottom - bounds.top);
        float yPosition = getHeight() / 2;
        float charLength = bounds.right - bounds.left;
        for (int i = 0; i < length; i++) {
            CharState charState = mTextChars.get(i);
            float charWidth = charState.draw(canvas, currentDrawPosition, charHeight, yPosition,
                    charLength);
            currentDrawPosition += charWidth;
        }
    
public voidonInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)

        super.onInitializeAccessibilityEvent(event);

        event.setClassName(PasswordTextView.class.getName());
        event.setPassword(true);
    
public voidonInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)

        super.onInitializeAccessibilityNodeInfo(info);

        info.setClassName(PasswordTextView.class.getName());
        info.setPassword(true);

        if (shouldSpeakPasswordsForAccessibility()) {
            info.setText(mText);
        }

        info.setEditable(true);

        info.setInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD);
    
public voidonPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)

        super.onPopulateAccessibilityEvent(event);

        if (shouldSpeakPasswordsForAccessibility()) {
            final CharSequence text = mText;
            if (!TextUtils.isEmpty(text)) {
                event.getText().add(text);
            }
        }
    
public voidreset(boolean animated)

        String textbefore = mText;
        mText = "";
        int length = mTextChars.size();
        int middleIndex = (length - 1) / 2;
        long delayPerElement = RESET_DELAY_PER_ELEMENT;
        for (int i = 0; i < length; i++) {
            CharState charState = mTextChars.get(i);
            if (animated) {
                int delayIndex;
                if (i <= middleIndex) {
                    delayIndex = i * 2;
                } else {
                    int distToMiddle = i - middleIndex;
                    delayIndex = (length - 1) - (distToMiddle - 1) * 2;
                }
                long startDelay = delayIndex * delayPerElement;
                startDelay = Math.min(startDelay, RESET_MAX_DELAY);
                long maxDelay = delayPerElement * (length - 1);
                maxDelay = Math.min(maxDelay, RESET_MAX_DELAY) + DISAPPEAR_DURATION;
                charState.startRemoveAnimation(startDelay, maxDelay);
                charState.removeDotSwapCallbacks();
            } else {
                mCharPool.push(charState);
            }
        }
        if (!animated) {
            mTextChars.clear();
        }
        sendAccessibilityEventTypeViewTextChanged(textbefore, 0, textbefore.length(), 0);
    
voidsendAccessibilityEventTypeViewTextChanged(java.lang.String beforeText, int fromIndex, int removedCount, int addedCount)

        if (AccessibilityManager.getInstance(mContext).isEnabled() &&
                (isFocused() || isSelected() && isShown())) {
            if (!shouldSpeakPasswordsForAccessibility()) {
                beforeText = null;
            }
            AccessibilityEvent event =
                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
            event.setFromIndex(fromIndex);
            event.setRemovedCount(removedCount);
            event.setAddedCount(addedCount);
            event.setBeforeText(beforeText);
            event.setPassword(true);
            sendAccessibilityEventUnchecked(event);
        }
    
private booleanshouldSpeakPasswordsForAccessibility()

return
true if the user has explicitly allowed accessibility services to speak passwords.

        return (Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0,
                UserHandle.USER_CURRENT_OR_SELF) == 1);
    
private voiduserActivity()

        mPM.userActivity(SystemClock.uptimeMillis(), false);