精华内容
下载资源
问答
  • Android 密码输入框

    千次阅读 2017-11-06 15:55:49
    好久没写blog了,今天抽空写一个Android里面都能用到的自定义控件,密码输入框。简单介绍一下这个密码输入框的样子吧,当软键盘弹出在输入适合,会有删除的图标显示,点击删除会清空Edittext,后面也会有个眼睛的...

    好久没写blog了,今天抽空写一个Android里面都能用到的自定义控件,密码输入框。简单介绍一下这个密码输入框的样子吧,当软键盘弹出在输入适合,会有删除的图标显示,点击删除会清空Edittext,后面也会有个眼睛的图标,点击切换是否加密显示和明文显示,当软键盘消失适合,后面那个删除的图标是消失的,其它的功能是和Edittext一样的,毕竟也是对于一个Edittext的自定义控件吧。下面就来看看我截的几个图。

    下面就来介绍一下基本实现,完整代码在最后也会给出。

     

        // 按钮宽度dp
        private int           mWidth;
        // 按钮的bitmap
        private Bitmap mBitmapInvisible;
        private Bitmap mBitmapVisible;
        // 按钮是否可见
        private boolean       isVisible;
        // 清除按钮出现动画
        private ValueAnimator mAnimatorVisible;
        // 消失动画
        private ValueAnimator mAnimatorGone;
        // 间隔
        private int           Interval;
        // 内容是否是明文
        private boolean isPlaintext = false;
        // 是否只在获得焦点后显示
        private boolean focusedShow = false;


    先了解这些变量含义。

     

     

    /**
         * 绘制内容是否是明文的ICON
         */
        private void drawVisible(float scale, Canvas canvas) {
            int right  = (int) (getWidth() + getScrollX() - getmPaddingRight() - Interval - mWidth * (1f - scale) / 2f);
            int left   = (int) (getWidth() + getScrollX() - getmPaddingRight() - Interval - mWidth * (scale + (1f - scale) / 2f));
            int top    = (int) ((getHeight() - mWidth * scale) / 2);
            int bottom = (int) (top + mWidth * scale);
    
            rect.set(left, top, right, bottom);
            if (isPlaintext) {
                canvas.drawBitmap(mBitmapVisible, null, rect, null);
            } else {
                canvas.drawBitmap(mBitmapInvisible, null, rect, null);
            }
        }

     

     /**
         * 只在获得焦点后显示
         */
        private void focusedShow() {
            focusedShow(isFocusable());
        }
    
        /**
         * 只在获得焦点后显示
         */
        private void focusedShow(boolean focused) {
            if (!TextUtil.isEmpty(getText()) && isEditThis() && focused) {
                if (!isVisible) {
                    isVisible = true;
                    mAnimatorGone.end();
                    mAnimatorVisible.end();
                    mAnimatorVisible.start();
                    invalidate();
                }
            } else {
                if (isVisible) {
                    isVisible = false;
                    mAnimatorGone.end();
                    mAnimatorVisible.end();
                    mAnimatorGone.start();
                    invalidate();
                }
            }
        }

     

    // 按钮资源
        private final int CLEAR = R.mipmap.icon_clear;
        // 动画时长
        protected final int ANIMATOR_TIME = 200;
        // 按钮左右间隔,单位PX
        private int Interval;
        // 清除按钮宽度,单位PX
        private int mWidthClear;
        // 左内边距
        private int mPaddingLeft;
        // 右内边距
        private int mPaddingRight;
        // 右侧多出的空间(间隔 + 按钮宽度)
        private int mExtraWidth;
        // 清除按钮的bitmap
        private Bitmap mBitmapClear;
        // 清除按钮出现动画
        private ValueAnimator mAnimatorVisible;
        // 消失动画
        private ValueAnimator mAnimatorGone;
        // 是否显示的记录
        private boolean isVisible = false;
        // 右边添加其他按钮时使用
        private int mRight = 0;

     

        /**
         * EditText内容变化的监听
         */
        @Override
        protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
            if (getInputType() == (InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_CLASS_NUMBER) && !TextUtils.isEmpty(text) && text.charAt(0) == '.') {
                if (text.length() == 1) {
                    setText("0.");
                } else {
                    setText(getText().replace(0, 0, "0."));
                }
                setSelection(getText().length());
            }
            super.onTextChanged(text, start, lengthBefore, lengthAfter);
            if (text.length() > 0 && isFocused() && isEditThis()) {
                if (!isVisible) {
                    isVisible = true;
                    startVisibleAnimator();
                }
            } else {
                if (isVisible) {
                    isVisible = false;
                    startGoneAnimator();
                }
            }
        }
       @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int additional = 0;
            if (getGravity() == Gravity.CENTER || getGravity() == Gravity.CENTER_HORIZONTAL) {
                additional = mExtraWidth + mRight + mPaddingRight;
            }
            // 设置内边距
            setPadding(mPaddingLeft + additional, getPaddingTop(), mExtraWidth + mRight + mPaddingRight, getPaddingBottom());
    
            if (!TextUtil.isEmpty(getText()) && isEditThis()) {
                if (!isVisible) {
                    isVisible = true;
                    startVisibleAnimator();
                }
            } else {
                if (isVisible) {
                    isVisible = false;
                    startGoneAnimator();
                }
            }
        }
      /**
         * 晃动动画
         *
         * @param counts 0.5秒钟晃动多少下
         */
        private Animation shakeAnimation(int counts) {
            Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
            translateAnimation.setInterpolator(new CycleInterpolator(counts));
            translateAnimation.setDuration(500);
            return translateAnimation;
        }
    
        /**
         * 给图标染上当前提示文本的颜色并且转出Bitmap
         */
        public Bitmap createBitmap(int resources, Context context) {
            final Drawable drawable = ContextCompat.getDrawable(context, resources);
            final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
            DrawableCompat.setTint(wrappedDrawable, getCurrentHintTextColor());
            return drawableToBitmap(wrappedDrawable);
        }

     

     

     

     

     

       /**
         * 触控执行的监听
         */
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                boolean touchable = (getWidth() - mPaddingRight - Interval - mRight - mWidthClear < event.getX())
                        && (event.getX() < getWidth() - mPaddingRight - Interval - mRight);
                if (touchable && isVisible) {
                    setError(null);
                    this.setText("");
                }
            }
            return super.onTouchEvent(event);
        }

     

    其实主要的就是一些绘制和一些动画的显示,基本原理还是遵从Edittext的属性来的。

     

    完整代码下载地址:

    http://download.csdn.net/download/greatdaocaoren/10106019

     

    展开全文
  • 实现效果图:实现流程:1、定义6位密码输入View思路:要绘制边框矩形,绘制分割线,绘制圆点。绘制圆的数目要与字符串的长度有关,添加或者删除都要修改字符串,输入6位后就是要关闭弹框,拿到密码,做判断工作了。...
    实现效果图:

    d5c1724455e0537c77764c056d7cebba.png

    实现流程:

    1、定义6位密码输入View 

    思路:要绘制边框矩形,绘制分割线,绘制圆点。绘制圆的数目要与字符串的长度有关,添加或者删除都要修改字符串,输入6位后就是要关闭弹框,拿到密码,做判断工作了。

    public class PasswordEditText extends AppCompatEditText {    // 画笔    private Paint mPaint;    // 一个密码所占的宽度    private int mPasswordItemWidth;    // 密码的个数默认为6位数    private int mPasswordNumber = 6;    // 背景边框颜色    private int mBgColor = Color.parseColor("#FFDDDDDD");    // 背景边框大小    private int mBgSize = 1;    // 背景边框圆角大小    private int mBgCorner = 8;    // 分割线的颜色    private int mDivisionLineColor = mBgColor;    // 分割线的大小    private int mDivisionLineSize = 1;    // 密码圆点的颜色    private int mPasswordColor = Color.parseColor("#FF000000");    // 密码圆点的半径大小    private int mPasswordRadius = 6;    public PasswordEditText(Context context) {        this(context, null);    }    public PasswordEditText(Context context, AttributeSet attrs) {        super(context, attrs);        initAttributeSet(context, attrs);        initPaint();        // 默认只能够设置数字和字母        setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);    }    /**     * 初始化画笔     */    private void initPaint() {        mPaint = new Paint();        // 抗锯齿        mPaint.setAntiAlias(true);        // 防抖动        mPaint.setDither(true);    }    /**     * 初始化属性     */    private void initAttributeSet(Context context, AttributeSet attrs) {        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText);        // 获取大小        //分割线的大小        mDivisionLineSize = (int) array.getDimension(R.styleable.PasswordEditText_divisionLineSize, dip2px(mDivisionLineSize));        //圆点的半径        mPasswordRadius = (int) array.getDimension(R.styleable.PasswordEditText_passwordRadius, dip2px(mPasswordRadius));        //背景边框大小        mBgSize = (int) array.getDimension(R.styleable.PasswordEditText_bgSize, dip2px(mBgSize));        //背景边框圆角大小        mBgCorner = (int) array.getDimension(R.styleable.PasswordEditText_bgCorner, mBgCorner);        // 获取边框颜色        mBgColor = array.getColor(R.styleable.PasswordEditText_bgColor, mBgColor);        // 分割线颜色        mDivisionLineColor = array.getColor(R.styleable.PasswordEditText_divisionLineColor, mDivisionLineColor);        //圆点颜色        mPasswordColor = array.getColor(R.styleable.PasswordEditText_passwordColor, mPasswordColor);        array.recycle();    }    /**     * dip 转 px     */    private float dip2px(int dip) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,                dip, getResources().getDisplayMetrics());    }    @Override    protected void onDraw(Canvas canvas) {        // 一个密码的宽度 [View宽度 - 边框的宽度(背景边框与分割线)]/6        mPasswordItemWidth = (getWidth() - 2 * mBgSize - (mPasswordNumber - 1) * mDivisionLineSize) / mPasswordNumber;        // 画背景        drawBg(canvas);        // 画分割线        drawDivisionLine(canvas);        // 画密码        drawPassword(canvas);        // 当前密码是不是满了        if (mListener != null) {            String password = getText().toString().trim();            if (password.length() >= mPasswordNumber) {                mListener.passwordFull(password);            }        }    }    /**     * 绘制密码     */    private void drawPassword(Canvas canvas) {        // 密码绘制是实心        mPaint.setStyle(Paint.Style.FILL);        // 设置密码的颜色        mPaint.setColor(mPasswordColor);        // 获取当前text        String text = getText().toString().trim();        // 获取密码的长度        int passwordLength = text.length();        // 不断的绘制密码        for (int i = 0; i < passwordLength; i++) {            int cy = getHeight() / 2;            int cx = mBgSize + i * mPasswordItemWidth + i * mDivisionLineSize + mPasswordItemWidth / 2;            canvas.drawCircle(cx, cy, mPasswordRadius, mPaint);        }    }    /**     * 绘制分割线     */    private void drawDivisionLine(Canvas canvas) {        // 给画笔设置大小        mPaint.setStrokeWidth(mDivisionLineSize);        // 设置分割线的颜色        mPaint.setColor(mDivisionLineColor);        //画竖线,x值不变        for (int i = 0; i < mPasswordNumber - 1; i++) {            int startX = mBgSize + (i + 1) * mPasswordItemWidth + i * mDivisionLineSize;            int startY = mBgSize;            int endX = startX;            int endY = getHeight() - mBgSize;            canvas.drawLine(startX, startY, endX, endY, mPaint);        }    }    /**     * 绘制背景     */    private void drawBg(Canvas canvas) {        //背景矩形        RectF rect = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);        // 给画笔设置大小        mPaint.setStrokeWidth(mBgSize);        // 设置背景的颜色        mPaint.setColor(mBgColor);        // 画空心        mPaint.setStyle(Paint.Style.STROKE);        // 绘制背景  drawRect , drawRoundRect  ,        // 如果有圆角那么就绘制drawRoundRect,否则绘制drawRect        if (mBgCorner == 0) {            canvas.drawRect(rect, mPaint);        } else {            //rx:x方向上的圆角半径。ry:y方向上的圆角半径。            canvas.drawRoundRect(rect, mBgCorner, mBgCorner, mPaint);        }    }    /**     * 添加一个密码     */    public void addPassword(String number) {        // 把之前的密码取出来        String password = getText().toString().trim();        if (password.length() >= mPasswordNumber) {            // 密码不能超过当前密码个输            return;        }        // 密码叠加        password += number;        setText(password);    }    /**     * 删除最后一位密码     */    public void deleteLastPassword() {        String password = getText().toString().trim();        // 判断当前密码是不是空        if (TextUtils.isEmpty(password)) {            return;        }        password = password.substring(0, password.length() - 1);        setText(password);    }    // 设置当前密码是否已满的接口回掉    private PasswordFullListener mListener;    public void setOnPasswordFullListener(PasswordFullListener listener) {        this.mListener = listener;    }    public void clear() {        setText("");    }    /**     * 密码已经全部填满     */    public interface PasswordFullListener {        public void passwordFull(String password);    }}

    2、键盘View

    思路:主要是点击数字后,拿到数字,在给PasswordEditText它。点击删除后,删除PasswordEditText里面的一个字符。逻辑都是在Dialog里面控制的。
    public class CustomerKeyboard extends LinearLayout implements View.OnClickListener {    public CustomerKeyboard(Context context) {        this(context, null);    }    public CustomerKeyboard(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CustomerKeyboard(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        // 直接加载布局        inflate(context, R.layout.ui_customer_keyboard, this);        setItemClickListener(this);    }    /**     * 设置子View的ClickListener     */    private void setItemClickListener(View view) {        if (view instanceof ViewGroup) {            ViewGroup viewGroup = (ViewGroup) view;            int childCount = viewGroup.getChildCount();            for (int i = 0; i < childCount; i++) {                //不断的递归给里面所有的View设置OnClickListener                View childView = viewGroup.getChildAt(i);                setItemClickListener(childView);            }        } else {            view.setOnClickListener(this);        }    }    @Override    public void onClick(View v) {        if (v instanceof TextView) {            if ("删除".equals(((TextView) v).getText().toString().trim())) {                // 点击的是删除                if (mListener != null) {                    mListener.delete();                }            } else {                // 点击的是数字                String number = ((TextView) v).getText().toString().trim();                if (mListener != null) {                    mListener.click(number);                }            }        }    }    // 设置点击回掉监听    private CustomerKeyboardClickListener mListener;    public void setOnCustomerKeyboardClickListener(CustomerKeyboardClickListener listener) {        this.mListener = listener;    }    /**     * 点击键盘的回调监听     */    public interface CustomerKeyboardClickListener {        public void click(String number);        public void delete();    }}
    3、对话框
    /** * 支付密码对话框 */public class PayPWDialogFragment extends DialogFragment implements CustomerKeyboard.CustomerKeyboardClickListener, PasswordEditText.PasswordFullListener {    private PasswordEditText mPasswordEt;    private OnCompleteListener mOnCompleteListener;    private OnCancelListener mOnCancelListener;    private static PayPWDialogFragment payPWDialogFragment;    //写一个静态方法产生实例    public static PayPWDialogFragment newInstance() {        if (payPWDialogFragment == null) {            payPWDialogFragment = new PayPWDialogFragment();        }        return payPWDialogFragment;    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.pay_password_dialog_layout, container, false);        mPasswordEt = (PasswordEditText) view.findViewById(R.id.password_et);        CustomerKeyboard mCustomerKeyboard = view.findViewById(R.id.custom_key_board);        mCustomerKeyboard.setOnCustomerKeyboardClickListener(this);        mPasswordEt.setEnabled(false);        mPasswordEt.setOnPasswordFullListener(this);        return view;    }    @Override    public void onCreate(Bundle savedInstanceState) { //此处可以设置Dialog的style等等        super.onCreate(savedInstanceState);    }    @Override    public Dialog onCreateDialog(Bundle savedInstanceState) {        Dialog dialog = new Dialog(getActivity(), R.style.CustomDialog);        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);        dialog.setContentView(R.layout.pay_password_dialog_layout);        dialog.setCanceledOnTouchOutside(false);        /**         * 设置宽度全屏,要设置在show的后面         */        WindowManager.LayoutParams layoutParams = dialog.getWindow().getAttributes();        layoutParams.gravity = Gravity.BOTTOM;        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;        dialog.getWindow().getDecorView().setPadding(0, 0, 0, 0);        dialog.getWindow().setAttributes(layoutParams);        return dialog;    }    @Override    public void click(String number) {        mPasswordEt.addPassword(number);    }    @Override    public void delete() {        mPasswordEt.deleteLastPassword();    }    @Override    public void passwordFull(String password) {        if (mOnCompleteListener != null)            mOnCompleteListener.onComplete(password);        dismiss();        mPasswordEt.clear();    }    public interface OnCompleteListener {        void onComplete(String content);    }    public interface OnCancelListener {        void onCancel();    }    public PayPWDialogFragment setOnCompleteListener(OnCompleteListener listener) {        this.mOnCompleteListener = listener;        return this;    }    public PayPWDialogFragment setOnCancelListener(OnCancelListener listener) {        this.mOnCancelListener = listener;        return this;    }}
    4、使用
    PayPWDialogFragment.newInstance().setOnCompleteListener(new PayPWDialogFragment.OnCompleteListener() {                    @Override                    public void onComplete(String content) {                    }                }).show(getFragmentManager(), "payPWDialogFragment");
    配置:
        <style name="CustomDialog" parent="@android:style/Theme.Dialog">                <item name="android:windowFrame">@nullitem>                <item name="android:windowIsFloating">trueitem>                <item name="android:windowContentOverlay">@nullitem>        <item name="android:windowAnimationStyle">@android:style/Animation.Dialogitem>        <item name="android:windowSoftInputMode">stateUnspecified|adjustPanitem>style>
    ui_customer_keyboard.xml
    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="#FFE6E6E6"    android:orientation="vertical">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="1dp">        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="1"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="2"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="3"            android:textColor="#ff444444"            android:textSize="30sp" />    LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="1dp">        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="4"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="5"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="6"            android:textColor="#ff444444"            android:textSize="30sp" />    LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="1dp">        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="7"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="8"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="9"            android:textColor="#ff444444"            android:textSize="30sp" />    LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="1dp"        android:orientation="horizontal">        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:gravity="center"            android:padding="8dp"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_marginRight="1dp"            android:layout_weight="1"            android:background="#FFFFFF"            android:gravity="center"            android:padding="8dp"            android:text="0"            android:textColor="#ff444444"            android:textSize="30sp" />        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_gravity="center_vertical"            android:layout_weight="1"            android:gravity="center"            android:padding="8dp"            android:text="删除"            android:textColor="#ff444444" />    LinearLayout>LinearLayout>
    pay_password_dialog_layout.xml
    <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    xmlns:ver="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="#FFFFFFFF"    android:orientation="vertical">    <TextView        android:id="@+id/tv_title"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_horizontal"        android:paddingTop="18dp"        android:paddingBottom="18dp"        android:text="请输入支付密码"        android:textColor="#ff252525"        android:textSize="16sp" />    <TextView        android:layout_width="match_parent"        android:layout_height="1dp"        android:background="#FFEEEEEE" />    <com.example.paybox.PasswordEditText        android:id="@+id/password_et"        android:layout_width="match_parent"        android:layout_height="47dp"        android:layout_marginTop="20dp"        android:layout_marginStart="15dp"        android:layout_marginEnd="15dp"        android:layout_marginBottom="40dp"        android:background="@null" />    <com.example.paybox.CustomerKeyboard        android:id="@+id/custom_key_board"        android:layout_width="match_parent"        android:layout_height="wrap_content" />LinearLayout>
    到这里就结束啦。

    往期精彩回顾

    • Android指纹识别详解

    • Android使用SurfaceView实现花瓣飘落效果

    • Android实现清理缓存功能

    • 换肤框架Android-skin-support的使用

    • Android实现商城购物车功能

    94b81c0fb97efc390e053c7d53fc8753.png

    展开全文
  • 接上篇https://blog.csdn.net/qq_35605213/article/details/82691871,... "space" //每个输入框之间的间距; "strokeWidth" //边框的高度; "checkedColor" //已输入的颜色 "defaultColor" //未输入的默认颜...

    接上篇https://blog.csdn.net/qq_35605213/article/details/82691871,优化了一下代码,添加一些属性;

          "space" //每个输入框之间的间距;
           "strokeWidth" //边框的高度;
           "checkedColor"  //已输入的颜色
           "defaultColor" //未输入的默认颜色
           "textLength"  //规定输入长度
           "backColor"   //输入框的背景颜色
           "textColor"   //字体颜色
            "circle"   //密文密码 ● 的大小;
            "round"   //输入框的圆角弧度
            "textSize"   //字体大小
            "isPwd"   //是否密文输入 默认true
            "waitInputColor"   //待输入线的颜色
           "isWaitInput"  //是否显示待输入线 默认false

    GiaHub源码 : https://github.com/CuiChenbo/PwdInputEditText

    如何使用:

    public class MainActivity extends AppCompatActivity {
    
        private PwdEditText p;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            p = findViewById(R.id.p);
            p.setOnTextChangeListener(new PwdEditText.OnTextChangeListener() {
                @Override
                public void onTextChange(String pwd) {
                    if (pwd.length() == p.getTextLength()){
                        //输入监听
                        Toast.makeText(MainActivity.this,pwd,Toast.LENGTH_SHORT).show();
                    }
                }
            });
            findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    p.clearText(); //清空输入内容
                }
            });
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
       <c.c.b.pwdinputedittext.PwdEditText
           android:id="@+id/p"
           android:layout_centerInParent="true"
           android:layout_width="330dp"
           android:layout_height="wrap_content"
           />
       <Button
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="清空"
           android:id="@+id/btn"
           android:layout_below="@id/p"
           android:layout_centerHorizontal="true"
           />
    
    </RelativeLayout>
    
    

    看代码,PwdEditText :

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import android.support.v7.widget.AppCompatEditText;
    import android.text.InputType;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.view.ViewGroup;
    import java.util.ArrayList;
    import java.util.List;
    
    public class PwdEditText extends AppCompatEditText {
    
         private Paint sidePaint , backPaint , textPaint;
         private Context mC;
        private String mText;
        private List<RectF> rectFS;
        private int StrokeWidth,spzceX ,spzceY,textSize;
        private int checkedColor,defaultColor,backColor ,textColor ,waitInputColor;
        private int textLength;
        private int Circle,Round;
        private boolean isPwd , isWaitInput;
    
        public PwdEditText(Context context) {
            super(context);
    
            mC = context;
            setAttrs( null);
            init();
        }
    
        public PwdEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
            mC = context;
            setAttrs( attrs);
            init();
        }
    
        public PwdEditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mC = context;
            setAttrs( attrs);
            init();
        }
    
        private void setAttrs(AttributeSet attrs) {
             TypedArray t = mC.obtainStyledAttributes(attrs, R.styleable.PwdEditText);
             if (t != null) {
                 textLength = t.getInt(R.styleable.PwdEditText_textLength,6);
                 spzceX = t.getDimensionPixelSize(R.styleable.PwdEditText_space, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
                 spzceY = t.getDimensionPixelSize(R.styleable.PwdEditText_space, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
                StrokeWidth = t.getDimensionPixelSize(R.styleable.PwdEditText_strokeWidth, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics()));
                Round = t.getDimensionPixelSize(R.styleable.PwdEditText_round, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics()));
                Circle = t.getDimensionPixelSize(R.styleable.PwdEditText_circle, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,7,getResources().getDisplayMetrics()));
                 textSize = t.getDimensionPixelSize(R.styleable.PwdEditText_textSize, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
                checkedColor = t.getColor(R.styleable.PwdEditText_checkedColor,0xff44ce61);
                defaultColor = t.getColor(R.styleable.PwdEditText_defaultColor,0xffd0d0d0);
                backColor = t.getColor(R.styleable.PwdEditText_backColor,0xfff1f1f1);
                textColor = t.getColor(R.styleable.PwdEditText_textColor,0xFF444444);
                waitInputColor = t.getColor(R.styleable.PwdEditText_waitInputColor,0xFF444444);
                isPwd = t.getBoolean(R.styleable.PwdEditText_isPwd,true);
                isWaitInput = t.getBoolean(R.styleable.PwdEditText_isWaitInput,false);
                t.recycle();
             }
        }
    
        private void init() {
            setTextColor(0X00ffffff); //把用户输入的内容设置为透明
            setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
            sidePaint = new Paint();
            backPaint = new Paint();
            textPaint = new Paint();
    
            rectFS = new ArrayList<>();
            mText = "" ;
    
            this.setBackgroundDrawable(null);
            setLongClickable(false);
            setTextIsSelectable(false);
            setCursorVisible(false);
    
        }
    
        @Override
        protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
            super.onTextChanged(text, start, lengthBefore, lengthAfter);
            if (mText == null) {return;}
            //如果字数不超过用户设置的总字数,就赋值给成员变量mText;
            // 如果字数大于用户设置的总字数,就只保留用户设置的几位数字,并把光标制动到最后,让用户可以删除;
            if (text.toString().length() <= textLength){
                mText = text.toString();
            }else{
                setText(mText);
                setSelection(getText().toString().length());  //光标制动到最后
                //调用setText(mText)之后键盘会还原,再次把键盘设置为数字键盘;
                setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
            }
            if (OnTextChangeListener != null) OnTextChangeListener.onTextChange(mText);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            switch (heightMode){
                case MeasureSpec.EXACTLY:
                    heightSize = MeasureSpec.getSize(heightMeasureSpec);
                    break;
                case MeasureSpec.AT_MOST:
                    heightSize = widthSize/textLength;
                    break;
            }
            setMeasuredDimension(widthSize,heightSize);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //边框画笔
            sidePaint.setAntiAlias(true);//消除锯齿
            sidePaint.setStrokeWidth(StrokeWidth);//设置画笔的宽度
            sidePaint.setStyle(Paint.Style.STROKE);//设置绘制轮廓
            sidePaint.setColor(defaultColor);
            //背景色画笔
            backPaint.setStyle(Paint.Style.FILL);
            backPaint.setColor(backColor);
            //文字的画笔
            textPaint.setTextSize(textSize);
            textPaint.setStyle(Paint.Style.FILL);
            textPaint.setColor(textColor);
    
            int Wide = Math.min(getMeasuredHeight(), getMeasuredWidth() / textLength);
    
            for (int i = 0; i < textLength; i++) {
                //区分已输入和未输入的边框颜色
                if (mText.length() >= i){
                    sidePaint.setColor(checkedColor);
                }else {
                    sidePaint.setColor(defaultColor);
                }
    
                //RectF的参数(left,  top,  right,  bottom); 画出每个矩形框并设置间距,间距其实是增加左边框距离,缩小上下右边框距离;
                RectF rect = new RectF(i * Wide + spzceX, spzceY,i * Wide + Wide - spzceX,Wide - spzceY); //四个值,分别代表4条线,距离起点位置的线
                canvas.drawRoundRect(rect,Round,Round,backPaint); //绘制背景色
                canvas.drawRoundRect(rect,Round,Round,sidePaint); //绘制边框;
                rectFS.add(rect);
    
                if (isWaitInput && i == mText.length()) {  //显示待输入的线
                    Paint l = new Paint();
                    l.setStrokeWidth(3);
                    l.setStyle(Paint.Style.FILL);
                    l.setColor(waitInputColor);
                    canvas.drawLine(i * Wide + Wide / 2, Wide / 2 - Wide / 5, i * Wide + Wide / 2, Wide / 2 + Wide / 5, l);
                }
            }
            //画密码圆点
            for (int j = 0; j < mText.length(); j++) {
                if (isPwd) {
                    canvas.drawCircle(rectFS.get(j).centerX(), rectFS.get(j).centerY(), Circle, textPaint);
                }else {
                    canvas.drawText(mText.substring(j,j+1),rectFS.get(j).centerX()-(textSize - spzceX)/2, rectFS.get(j).centerY()+(textSize - spzceY)/2, textPaint);
    //                Rect textRect = new Rect();
    //                textPaint.getTextBounds(mText.substring(j, j + 1), 0, 1, textRect);
    //                canvas.drawText(mText.substring(j, j + 1), rectFS.get(j).left + (rectFS.get(j).right - rectFS.get(j).left) / 2 - textRect.width() / 2,
    //                        rectFS.get(j).top + ((rectFS.get(j).bottom - rectFS.get(j).top) / 2) + textRect.height() / 2, textPaint);
                }
            }
        }
    
        private int dp2px(float dpValue){
            float scale=mC.getResources().getDisplayMetrics().density;
            return (int)(dpValue*scale+0.5f);
        }
    
        /**
         * 输入监听
         */
        interface OnTextChangeListener{
            void onTextChange(String pwd);
        }
        private OnTextChangeListener OnTextChangeListener;
        public void setOnTextChangeListener(OnTextChangeListener OnTextChangeListener){
            this.OnTextChangeListener = OnTextChangeListener;
        }
    
        /**
         * 清空所有输入的内容
         */
        public void clearText(){
            setText("");
            setInputType(InputType.TYPE_CLASS_NUMBER|InputType.TYPE_NUMBER_VARIATION_NORMAL);
        }
        /**
         * 设置密码框间距
         */
        public void setSpace(int space){
            spzceX = space;
            spzceY = space;
        }
        /**
         * 设置密码框个数
         */
        public void setTextLength(int textLength){
            this.textLength = textLength;
        }
        /**
         * 获得密码框个数
         */
        public int getTextLength(){
            return this.textLength;
        }
        /**
         * 设置已输入密码框颜色
         */
        public void setcheckedColorColor(int checkedColor){
            this.checkedColor = checkedColor;
        }
        /**
         * 设置未输入密码框颜色
         */
        public void setdefaultColorColor(int defaultColor){
            this.defaultColor = defaultColor;
        }
        /**
         * 设置密码框背景色
         */
        public void setBackColor(int backColor){
            this.backColor = backColor;
        }
        /**
         * 设置密码圆点的颜色
         */
        public void setPwdTextColor(int textColor){
            this.textColor = textColor;
        }
        /**
         * 设置密码框 边框的宽度
         */
        public void setStrokeWidth(int width){
            StrokeWidth = width;
        }
    
        /**
         * 密码的圆点大小
         */
        public void setCircle(int Circle){
            this.Circle = Circle;
        }
        /**
         * 密码边框的圆角大小
         */
        public void setRound(int Round){
            this.Round = Round;
        }
    
        public int getStrokeWidth() {
            return StrokeWidth;
        }
    
        public int getSpzceX() {
            return spzceX;
        }
    
        public int getSpzceY() {
            return spzceY;
        }
    
        public int getCheckedColor() {
            return checkedColor;
        }
    
        public int getDefaultColor() {
            return defaultColor;
        }
    
        public int getBackColor() {
            return backColor;
        }
    
        public int getTextColor() {
            return textColor;
        }
    
        public int getCircle() {
            return Circle;
        }
    
        public int getRound() {
            return Round;
        }
        public int gettextSize() {
            return textSize;
        }
    
        public void settextSize(int textSize) {
            this.textSize = textSize;
        }
    
        public boolean isPwd() {
            return isPwd;
        }
    
        /**
         * 是否密文输入
         * @param pwd
         */
        public void setPwd(boolean pwd) {
            isPwd = pwd;
        }
    
        public int getWaitInputColor() {
            return waitInputColor;
        }
    
        /**\
         * 待输入线的颜色
         * @param waitInputColor
         */
        public void setWaitInputColor(int waitInputColor) {
            this.waitInputColor = waitInputColor;
        }
    
        public boolean isWaitInput() {
            return isWaitInput;
        }
    
        /**
         * 是否显示待输入的线
         * @param waitInput
         */
        public void setWaitInput(boolean waitInput) {
            isWaitInput = waitInput;
        }
    
    }
    

    style中的代码:

        <declare-styleable name="PwdEditText">
            <attr name="space" format="dimension"/>
            <attr name="strokeWidth" format="dimension"/>
            <attr name="checkedColor" format="color"/>
            <attr name="defaultColor" format="color"/>
            <attr name="textLength" format="integer"/>
            <attr name="backColor" format="color"/>
            <attr name="textColor" format="color"/>
            <attr name="circle" format="dimension"/>
            <attr name="round" format="dimension"/>
            <attr name="textSize" format="dimension"/>
            <attr name="isPwd" format="boolean"/>
            <attr name="waitInputColor" format="color"/>
            <attr name="isWaitInput" format="boolean"/>
        </declare-styleable>

     

    展开全文
  • 新闻Android即将获得类AirDrop功能:可向附近设备快速分享文件[1]谷歌为安卓文件管理应用引入可安全隐藏资料的Safe Folder功能[2]Android TV新主界面将显示电影、电视节目和应用推荐内容[3]泄露的Android文档暗示了...

    f20d53bc5ab6e2abfc4729a8b013d77c.png

    新闻

    1. Android即将获得类AirDrop功能:可向附近设备快速分享文件[1]

    2. 谷歌为安卓文件管理应用引入可安全隐藏资料的Safe Folder功能[2]

    3. Android TV新主界面将显示电影、电视节目和应用推荐内容[3]

    4. 泄露的Android文档暗示了传说中的谷歌Pixel 5a与折叠屏新机[4]

    5. 谷歌发布Android 11 Beta 3 距离正式版仅咫尺之遥[5]

    6. Android将迎来新的应用内评价API 以缓解当前评价方式的困扰[6]

    教程

    1. 谈一谈Android上的SurfaceTexture

    2. 在 Kotlin 中使用 Dagger 会遇到的陷阱和优化方法

    3. Android 存储空间的最佳实践 (上)

    开源库

    1. RoundWidget[7]

      Java 实现的 Android 原生圆角矩形控件,圆角 FrameLayout 和圆角 ImageView

      ed6f247a77db51ea4d3b802cc9815d65.png
    2. Tasker[8]

      Tasker is intended to enable proper and easy use of the UI and background thread. It lets you perform operations in the background. When they’ve finished running, it then allows you to update views in the main event thread.

    3. SplitEditTextView[9]

      Android类似支付宝密码输入框,美团外卖验证码输入框,验证码粘贴等;有效果图,有demo;支持下划线,方框,连体框样式;可设置光标、光标颜色,下划线输入时高亮,边框大小、颜色、圆角等等;设置密码显示的

    4. WuDaozi[10]

      Android image selector, written with Kotlin, inspired by zhihu/Matisse.

    5. MapHelper[11]

      ? MapHelper是一个整合了高德地图、百度地图、腾讯地图、谷歌地图等相关路线规划和导航的地图帮助类库

    6. BlurImageSwitcher[12]

      Lightweight Blurred ImageSwitcher Library

    7. integration-android[13]

      Virtusize is a widget which opens when clicking on the Virtusize button, which is located next to the size selection on the product page.

      e02c797d56e5d604029337200fb5e1ab.png
    8. turbine[14]

      A small testing library for kotlinx.coroutines Flow

    9. DevUtils[15]

      一个 Android 工具库, 主要根据不同功能模块,封装快捷使用的工具类及 API 方法调用。该项目尽可能的便于开发人员,快捷、快速开发安全可靠的项目,以及内置部分常用的资源文件,如 color.xml

      60c448acb8bcdfd804c18957649445e6.png
    10. JCL[16]

      ar Class Loader, a configurable and dynamic custom classloader designed to create, manage and manipulate isolated Java classloaders in IoC frameworks and web applications.

    11. Printama[17]

      A very well documented android library for bluetooth thermal printer. Tested for 2 inch printers

      2c93efdb8a69c019629278c96619e726.png
    12. tinylog[18]

      tinylog is a lightweight logging framework for Java, Kotlin, Scala, and Android

    13. flowcamera[19]

      使用最新的CameraX 相机库 实现仿微信拍照和拍小视频(Based on the Camerax, faster and better compatibility)

      05d6a3b9a63c8530df810cdd20680f11.png
    14. DocumentReader[20]

      This library reads word documents (.doc and .docx), txt and PDF files, and gives the output content of the document as a String.

    15. CameraView[21]

      仿微信拍照Android控件(轻触拍照,长按摄像)

      83f45899c9c87e6a8b8c17c9077e2cb4.png
    16. NetworkResponseAdapter[22]

      A Kotlin Coroutines based Retrofit call adapter that handles errors as a part of state

    17. FormFiller[23]

      Android helper library to populate form fields with predefined data set

      cc0b75e40e9c37e7be34d7da2ce8dafc.gif
    18. ThirdPartyLicenseDisplay[24]

      Displays third party license information

    19. audioswitch[25]

      An Android audio management library for real-time communication apps.

      7d1e7482527bbb3a5c6ea09a4390c41c.png
    20. tempo[26]

      ⌚Kotlin intuitive Date extensions.

    21. pesticide[27]

      A Library To Write Domain-Driven Tests, written in Kotlin on top of Junit5

    22. kvision[28]

      Object oriented web framework for Kotlin/JS

    插件

    1. apkscale[29]

      A Gradle plugin to measure the app size impact of Android libraries

    App

    1. GitExplorer[30]

      Git Explorer is a simple android application to search git command on one click. Dedicated to all Software Developers with ❤️.

      736da5635c5592d1b2889c78877b73aa.png
    2. PopCornShow[31]

      Banco de dados com informações de filmes e séries.

      80864e657109ead7c91c7c40c388a52b.png
    3. StreetComplete[32]

      Easy to use OpenStreetMap editor for Android

      34b68034d5be7f258aa21633041bda77.png
    4. deltachat-android[33]

      Email-based instant messaging for Android.

      95ad3d2d26272f39b7262205664340b6.png
    5. moviespreview[34]

      An application to show movies data based on TheMovieDB API.

      2d93767049518cb588e4c9c79d1eeaf3.png
    6. AndroidPlanisphere[35]

      A simple star chart that shows sun, moon and stars as well as constellations and planets.

    7. EasyBook[36]

      Java/Android多站点小说爬虫库,并发搜索,epub/txt下载,在线书源等,已实现小说app

      c32c9114e97887121bb657a3ab0e300a.png

    示例

    1. SwipeBackLayoutTouTiao[37]

      仿今日头条、腾讯新闻界面滑动关闭 下层activity有缩放效果

      420acf9efafac209d90d662ff983f29c.gif
    2. Cherry[38]

      一款采用谷歌最新mvvm架构和Jetpack架构组件,kotlin 携程网络请求,Arouter组件化开发的干货集中营客户端"

    工具

    1. android-layout-inspector[39]

      More stable Android Layout inspector than Android Studio Layout Inspector. Allows you to switch between displaying dimensions in PX and DP (only for new layout captures, not for opened files)

      cae4fc4f64d15357fd6b043d0855266a.png
    2. Recaf[40]

      A modern Java bytecode editor

      4fdd64be5a26a585c25abacf1d7ccf1c.gif

    活动

    f1d8c0753e2cfe6f431f31b3337ea449.png

    ? 链接

    [1]

    Android即将获得类AirDrop功能:可向附近设备快速分享文件: https://www.cnbeta.com/articles/tech/1011719.htm

    [2]

    谷歌为安卓文件管理应用引入可安全隐藏资料的Safe Folder功能: https://www.cnbeta.com/articles/tech/1011995.htm

    [3]

    Android TV新主界面将显示电影、电视节目和应用推荐内容: https://www.cnbeta.com/articles/tech/1012277.htm

    [4]

    泄露的Android文档暗示了传说中的谷歌Pixel 5a与折叠屏新机: https://www.cnbeta.com/articles/tech/1012419.htm

    [5]

    谷歌发布Android 11 Beta 3 距离正式版仅咫尺之遥: https://www.cnbeta.com/articles/tech/1012759.htm

    [6]

    Android将迎来新的应用内评价API 以缓解当前评价方式的困扰: https://www.cnbeta.com/articles/tech/1012851.htm

    [7]

    RoundWidget: https://github.com/xiaofei-dev/RoundWidget

    [8]

    Tasker: https://github.com/AlShakib/Tasker

    [9]

    SplitEditTextView: https://github.com/Chen-keeplearn/SplitEditTextView

    [10]

    WuDaozi: https://github.com/JosephusZhou/WuDaozi

    [11]

    MapHelper: https://github.com/jenly1314/MapHelper

    [12]

    BlurImageSwitcher: https://github.com/Chrisvin/BlurImageSwitcher

    [13]

    integration-android: https://github.com/virtusize/integration_android

    [14]

    turbine: https://github.com/cashapp/turbine

    [15]

    DevUtils: https://github.com/afkT/DevUtils

    [16]

    JCL: https://github.com/kamranzafar/JCL

    [17]

    Printama: https://github.com/anggastudio/Printama

    [18]

    tinylog: https://github.com/pmwmedia/tinylog

    [19]

    flowcamera: https://github.com/xionger0520/flowcamera

    [20]

    DocumentReader: https://github.com/Asutosh11/DocumentReader

    [21]

    CameraView: https://github.com/CJT2325/CameraView

    [22]

    NetworkResponseAdapter: https://github.com/haroldadmin/NetworkResponseAdapter

    [23]

    FormFiller: https://github.com/soarcn/FormFiller

    [24]

    ThirdPartyLicenseDisplay: https://github.com/ligi/ThirdPartyLicenseDisplay

    [25]

    audioswitch: https://github.com/twilio/audioswitch

    [26]

    tempo: https://github.com/cesarferreira/tempo

    [27]

    pesticide: https://github.com/uberto/pesticide

    [28]

    kvision: https://github.com/rjaros/kvision

    [29]

    apkscale: https://github.com/twilio/apkscale

    [30]

    GitExplorer: https://github.com/KulkarniAtharva/GitExplorer

    [31]

    PopCornShow: https://github.com/icaronunes/PopCornShow

    [32]

    StreetComplete: https://github.com/westnordost/StreetComplete

    [33]

    deltachat-android: https://github.com/deltachat/deltachat-android

    [34]

    moviespreview: https://github.com/perettijuan/moviespreview

    [35]

    AndroidPlanisphere: https://github.com/tengel/AndroidPlanisphere

    [36]

    EasyBook: https://github.com/Zzzia/EasyBook

    [37]

    SwipeBackLayoutTouTiao: https://github.com/JustRight815/SwipeBackLayoutTouTiao

    [38]

    Cherry: https://github.com/Victor2018/Cherry

    [39]

    android-layout-inspector: https://github.com/Grigory-Rylov/android-layout-inspector

    [40]

    Recaf: https://github.com/Col-E/Recaf

    ? 往期周报

    9f3020858e6886955a386acd73373b7b.png439b32d2a9a45d2845f5e5ec2cd05648.png382282719f2a70999b6e5d44d14b23db.png

    2bf0c77e6a272cd76938a34ca02e1805.png

    扫一扫关注公众号和投稿分享你的文章/开源项目

    觉得内容不错点个「在看」哦♥️

    展开全文
  • Android 密码输入框强力实现

    千次阅读 2013-12-04 10:41:03
    editText.setInputType(0x81) 很变态的办法,但是很有用。
  • // 按钮宽度dp private int mWidth; // 按钮的bitmap private Bitmap mBitmapInvisible; private Bitmap mBitmapVisible; // 按钮是否可见 private boolean isVisible;...// 清除按钮出现动画 private ValueAnimator ...
  • textView.setLongClickable(false); textView.setCustomSelectionActionModeCallback(new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { ...
  • Android支付密码输入框

    2016-07-23 12:53:07
    Android的一个支付密码输入框控件,类似于微信和支付宝那种,可以设置支付密码长度,输入完时自动处理输入结果,可以监听每次输入的类容,可以查看明文密码等。
  • 自定义密码输入框 github地址
  • 刚撸出来的密码输入框,注释和逻辑看着挺清晰的,一些属性还没有添加,下个博客把属性添加上去; 看一下图: 直接看代码吧! import android.content.Context; import android.graphics.Canvas; import ...
  • 密码输入框

    2017-11-06 16:12:46
    Android密码输入框,Edittext的自定义,密文和明文显示。
  • Android自定义密码输入框 项目地址 项目需要用到密码框输入,并且使用自定义的键盘,但是密码框需要区分输入完成、待输入、未输入颜色百度一番没有结果就自己自定义一个了 自定义键盘 (我做的比较简单就不累赘了) ...
  • 主要为大家详细介绍了Android自定义密码输入框和数字键盘的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 最近做个项目自定义密码输入框功能,下面小编把实现思路分享到脚本之家平台,需要的朋友参考下吧
  • 仿支付宝密码输入
  • 简介: Android 验证码和密码输入框,能自定义输入框个数和样式(连体,下划线和方形框) 类似微信支付宝的密码输入框等 更多:作者提 Bug 标签: Android 验证码和密码输入框,能自定义输入框个数和样式(连体...
  • 在项目中遇到需要提供给用户一个密码输入框明文/密文切换显示的需求,今天小编借脚本之家平台给大家分享下Android 实现密码输入框动态明文/密文切换显示效果,需要的朋友参考下
  • 主要为大家详细介绍了android仿支付宝密码输入框效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 本文实例为大家分享了android密码输入框效果展示的具体代码,供大家参考,具体内容如下 老规矩,先看效果;这是现在商城类app中很常见的支付密码效果,首先说下这个不是自定义控件,是github上的开源库; ...
  • Android四方形输入框密码

    千次阅读 2018-08-31 17:49:25
    Android四方形输入框密码框 一、自定义view继承EditText,代码中控制输入框的个数和是否为可见密码格式 package com.example.testcostumview.inputbox; import android.content.Context; import ...
  • android 仿支付宝密码输入框

    千次阅读 2016-08-07 23:45:27
    android 仿支付宝密码输入框

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 701
精华内容 280
关键字:

android密码输入框