重写EditText让密码显示****

在做一个项目的时候客户要求密码框显示*号,这个纠结了一下啊,之前想做监听,但是发现bug好多,仔细的看了源代码终于找出解决方案,setTransformationMethod(new PasswordTransformationMethod());就可以达到想要的效果,源代码中的...其实是写死到代码中了,我们没法改,所以只能重写PasswordTransformationMethod,关于这个类里面包含内容比较多,值得注意的是每输入一个字符要延时一下才变成*,这里其实用handler做的处理。今天刚做出来,和大家分享一下,欢迎前辈批评指正。(用的时候在xml中加载该类(AsteriskPasswordEditText))

 

 

public class AsteriskPasswordEditText extends EditText
{
   
    public AsteriskPasswordEditText(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        this.setTransformationMethod(new PasswordTransformationMethod());
    }
   
    static class PasswordTransformationMethod implements TransformationMethod,
            TextWatcher
    {
       
        static final Object ACTIVE = new NoCopySpan.Concrete();
       
        private WeakReference<ContentResolver> mResolver;
       
        private boolean mPrefsInited;
       
        /* package */static final int SHOW_PASSWORD = 8;
       
        /* package */static final int AUTO_TEXT = 2;
       
        /* package */static final int AUTO_PERIOD = 4;
       
        /* package */static final int AUTO_CAP = 1;
       
        private int mPrefs;
       
        private SettingsObserver mObserver;
       
        public CharSequence getTransformation(CharSequence source, View view)
        {
            if (source instanceof Spannable)
            {
                Spannable sp = (Spannable) source;
               
                /*
                 * Remove any references to other views that may still be
                 * attached.  This will happen when you flip the screen
                 * while a password field is showing; there will still
                 * be references to the old EditText in the text.
                 */
                ViewReference[] vr = sp.getSpans(0,
                        sp.length(),
                        ViewReference.class);
                for (int i = 0; i < vr.length; i++)
                {
                    sp.removeSpan(vr[i]);
                }
               
                removeVisibleSpans(sp);
               
                sp.setSpan(new ViewReference(view),
                        0,
                        0,
                        Spannable.SPAN_POINT_POINT);
            }
           
            return new PasswordCharSequence(source);
        }
       
        public static PasswordTransformationMethod getInstance()
        {
            if (sInstance != null)
                return sInstance;
           
            sInstance = new PasswordTransformationMethod();
            return sInstance;
        }
       
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after)
        {
            // This callback isn't used.
        }
       
        public void onTextChanged(CharSequence s, int start, int before,
                int count)
        {
            if (s instanceof Spannable)
            {
                Spannable sp = (Spannable) s;
                ViewReference[] vr = sp.getSpans(0,
                        s.length(),
                        ViewReference.class);
                if (vr.length == 0)
                {
                    return;
                }
               
                /*
                 * There should generally only be one ViewReference in the text,
                 * but make sure to look through all of them if necessary in case
                 * something strange is going on.  (We might still end up with
                 * multiple ViewReferences if someone moves text from one password
                 * field to another.)
                 */
                View v = null;
                for (int i = 0; v == null && i < vr.length; i++)
                {
                    v = vr[i].get();
                }
               
                if (v == null)
                {
                    return;
                }
               
                int pref = getPrefs(v.getContext());
                if ((pref & SHOW_PASSWORD) != 0)
                {
                    if (count > 0)
                    {
                        removeVisibleSpans(sp);
                       
                        if (count == 1)
                        {
                            sp.setSpan(new Visible(sp, this), start, start
                                    + count, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                        }
                    }
                }
            }
        }
       
        //TextKeyListener������ start==================================================================
        /* package */int getPrefs(Context context)
        {
            synchronized (this)
            {
                if (!mPrefsInited || mResolver.get() == null)
                {
                    initPrefs(context);
                }
            }
            return mPrefs;
        }
       
        private void initPrefs(Context context)
        {
            final ContentResolver contentResolver = context.getContentResolver();
            mResolver = new WeakReference<ContentResolver>(contentResolver);
            if (mObserver == null)
            {
                mObserver = new SettingsObserver();
                contentResolver.registerContentObserver(Settings.System.CONTENT_URI,
                        true,
                        mObserver);
            }
           
            updatePrefs(contentResolver);
            mPrefsInited = true;
        }
       
        private class SettingsObserver extends ContentObserver
        {
            public SettingsObserver()
            {
                super(new Handler());
            }
           
            @Override
            public void onChange(boolean selfChange)
            {
                if (mResolver != null)
                {
                    final ContentResolver contentResolver = mResolver.get();
                    if (contentResolver == null)
                    {
                        mPrefsInited = false;
                    }
                    else
                    {
                        updatePrefs(contentResolver);
                    }
                }
                else
                {
                    mPrefsInited = false;
                }
            }
        }
       
        private void updatePrefs(ContentResolver resolver)
        {
            boolean cap = System.getInt(resolver, System.TEXT_AUTO_CAPS, 1) > 0;
            boolean text = System.getInt(resolver, System.TEXT_AUTO_REPLACE, 1) > 0;
            boolean period = System.getInt(resolver,
                    System.TEXT_AUTO_PUNCTUATE,
                    1) > 0;
            boolean pw = System.getInt(resolver, System.TEXT_SHOW_PASSWORD, 1) > 0;
           
            mPrefs = (cap ? AUTO_CAP : 0) | (text ? AUTO_TEXT : 0)
                    | (period ? AUTO_PERIOD : 0) | (pw ? SHOW_PASSWORD : 0);
        }
       
        //TextKeyListener������ end==================================================================
       
        public void afterTextChanged(Editable s)
        {
        }
       
        public void onFocusChanged(View view, CharSequence sourceText,
                boolean focused, int direction, Rect previouslyFocusedRect)
        {
            if (!focused)
            {
                if (sourceText instanceof Spannable)
                {
                    Spannable sp = (Spannable) sourceText;
                   
                    removeVisibleSpans(sp);
                }
            }
        }
       
        private static void removeVisibleSpans(Spannable sp)
        {
            Visible[] old = sp.getSpans(0, sp.length(), Visible.class);
            for (int i = 0; i < old.length; i++)
            {
                sp.removeSpan(old[i]);
            }
        }
       
        private static class PasswordCharSequence implements CharSequence,
                GetChars
        {
            public PasswordCharSequence(CharSequence source)
            {
                mSource = source;
            }
           
            public int length()
            {
                return mSource.length();
            }
           
            public char charAt(int i)
            {
                if (mSource instanceof Spanned)
                {
                    Spanned sp = (Spanned) mSource;
                   
                    int st = sp.getSpanStart(ACTIVE);
                    int en = sp.getSpanEnd(ACTIVE);
                   
                    if (i >= st && i < en)
                    {
                        return mSource.charAt(i);
                    }
                   
                    Visible[] visible = sp.getSpans(0,
                            sp.length(),
                            Visible.class);
                   
                    for (int a = 0; a < visible.length; a++)
                    {
                        if (sp.getSpanStart(visible[a].mTransformer) >= 0)
                        {
                            st = sp.getSpanStart(visible[a]);
                            en = sp.getSpanEnd(visible[a]);
                           
                            if (i >= st && i < en)
                            {
                                return mSource.charAt(i);
                            }
                        }
                    }
                }
                return DOT;
            }
           
            public CharSequence subSequence(int start, int end)
            {
                char[] buf = new char[end - start];
               
                getChars(start, end, buf, 0);
                return new String(buf);
            }
           
            public String toString()
            {
                return subSequence(0, length()).toString();
            }
           
            public void getChars(int start, int end, char[] dest, int off)
            {
                TextUtils.getChars(mSource, start, end, dest, off);
               
                int st = -1, en = -1;
                int nvisible = 0;
                int[] starts = null, ends = null;
               
                if (mSource instanceof Spanned)
                {
                    Spanned sp = (Spanned) mSource;
                   
                    st = sp.getSpanStart(ACTIVE);
                    en = sp.getSpanEnd(ACTIVE);
                   
                    Visible[] visible = sp.getSpans(0,
                            sp.length(),
                            Visible.class);
                    nvisible = visible.length;
                    starts = new int[nvisible];
                    ends = new int[nvisible];
                   
                    for (int i = 0; i < nvisible; i++)
                    {
                        if (sp.getSpanStart(visible[i].mTransformer) >= 0)
                        {
                            starts[i] = sp.getSpanStart(visible[i]);
                            ends[i] = sp.getSpanEnd(visible[i]);
                        }
                    }
                }
               
                for (int i = start; i < end; i++)
                {
                    if (!(i >= st && i < en))
                    {
                        boolean visible = false;
                       
                        for (int a = 0; a < nvisible; a++)
                        {
                            if (i >= starts[a] && i < ends[a])
                            {
                                visible = true;
                                break;
                            }
                        }
                       
                        if (!visible)
                        {
                            dest[i - start + off] = DOT;
                        }
                    }
                }
            }
           
            private CharSequence mSource;
        }
       
        /**
         * ��������ϢתΪ* ��Ĭ����ʱ1.5�룩
         */
        private static class Visible extends Handler implements UpdateLayout,
                Runnable
        {
            public Visible(Spannable sp, PasswordTransformationMethod ptm)
            {
                mText = sp;
                mTransformer = ptm;
                postAtTime(this, SystemClock.uptimeMillis() + 1500);
            }
           
            public void run()
            {
                mText.removeSpan(this);
            }
           
            private Spannable mText;
           
            private PasswordTransformationMethod mTransformer;
        }
       
        /**
         * Used to stash a reference back to the View in the Editable so we
         * can use it to check the settings.
         */
        private static class ViewReference extends WeakReference<View>
                implements NoCopySpan
        {
            public ViewReference(View v)
            {
                super(v);
            }
        }
       
        private static PasswordTransformationMethod sInstance;
       
        private static char DOT = '*';
    }
   
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值