【Android】登錄界面的實現

資料來源:https://github.com/tyzlmjj/AndroidUI/tree/master/ClearEditText

先把ClearEditText.java和PasswordEditText.java複製到java/包名/中,然後在佈局文件中寫入

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
    <ImageView/>
    <包名.ClearEditText
        android:hint="請輸入註冊手機號/賬號"
        android:theme="@style/MyEditText"
        />

    <包名.PasswordEditText
        android:hint="請輸入密碼"
        android:textSize="12sp"
        android:inputType="numberPassword"
        android:theme="@style/MyEditText"
        />

    <Button
        android:text="登錄"
        />
    <LinearLayout>
        <TextView
            android:text="忘記密碼?"
            />
        <TextView
            android:text="註冊"
            />
    </LinearLayout>
</LinearLayout>

改變下劃線的顏色,灰色和黃色
values/styles.xml

<resources>
    <style
        name="MyEditText"
        parent="Theme.AppCompat.Light">
        <item name="colorControlNormal">#a4a4a3</item>
        <item name="colorControlActivated">#febf22</item>
    </style>
</resources>

這裏寫圖片描述

實現的效果是,輸入內容就出現“x”,當密碼輸入到達6位時,登錄按鈕變色,然後點擊登錄會提示抖動密碼錯誤


import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Created by 123 on 2017/08/07.
 */

public class LoginActivity extends Activity implements View.OnClickListener{

    private ClearEditText mAccountEditText;
    private ClearEditText mPasswordEditText;


    private Button mLoginButton;

    private TextView mForgetPasswordTextView;
    private TextView mSignTextView;

    private String mAccountString;
    private String mPasswordString;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);

        setContentView(R.layout.login_layout);
        initView();
        intiData();
        initEvent();

    }

    private void initView(){

        mAccountEditText=findViewById(R.id.id_login_account_edit_text);
        mPasswordEditText=findViewById(R.id.id_login_password_edit_text);



        mLoginButton=findViewById(R.id.id_login_login_button);

        mForgetPasswordTextView=findViewById(R.id.id_login_forget_password_text_view);
        mSignTextView=findViewById(R.id.id_login_sign_text_view);

    }

    private void intiData(){

        mPasswordString=mPasswordEditText.getText().toString();

    }

    private void initEvent(){

        mLoginButton.setOnClickListener(this);
        mLoginButton.setClickable(false);
        mForgetPasswordTextView.setOnClickListener(this);
        mSignTextView.setOnClickListener(this);

        //edit監聽事件
        mPasswordEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                if (editable.toString().length()>5){
                    setLoginButton(1);
                }
                else setLoginButton(0);
            }
        });


    }

    private void setLoginButton(int effective){
        //按鍵有效
        if (effective==1){
            mLoginButton.setTextColor(Color.parseColor("#000000"));//黑
            mLoginButton.setBackgroundColor(Color.parseColor("#febf22"));//黃杖
            mLoginButton.setClickable(true);
        }else {
            mLoginButton.setClickable(false);
            mLoginButton.setTextColor(Color.parseColor("#ffffff"));//白
            mLoginButton.setBackgroundColor(Color.parseColor("#a4a4a3"));//灰
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.id_login_login_button:
                mPasswordEditText.setError("密碼輸入錯誤");
                mPasswordEditText.startShakeAnimation();
                break;

            case R.id.id_login_sign_text_view:
                mAccountString=mAccountEditText.getText().toString();

                Bundle bundle=new Bundle();
                bundle.putString("account key",mAccountString);

                //Intent intent=new Intent(this,SignActivity.class);
                //intent.putExtra("login bundle",bundle);

                //startActivity(intent);

                break;
            case R.id.id_login_forget_password_text_view:
                pf("R.id.id_login_forget_password_text_view");
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_BACK){
            ActivityCollector.finishAll();
            System.exit(0);

            return true;

        }
        return super.onKeyDown(keyCode, event);
    }

    private void pf(String string){
        Toast.makeText(this, string,Toast.LENGTH_SHORT).show();
    }
}

ClearEditText.java



import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.Animation;
import android.view.animation.CycleInterpolator;
import android.view.animation.TranslateAnimation;

public class ClearEditText extends AppCompatEditText {

    //按鈕資源
    private final int CLEAR = R.drawable.clearfill;
    //動畫時長
    private final int ANIMATOR_TIME = 200;
    //按鈕左右間隔,單位DP
    private final int INTERVAL = 5;
    //清除按鈕寬度,單位DP
    private final int WIDTH_OF_CLEAR = 23;


    //間隔記錄
    private int Interval;
    //清除按鈕寬度記錄
    private int mWidth_clear;
    //右內邊距
    private int mPaddingRight;
    //清除按鈕的bitmap
    private Bitmap mBitmap_clear;
    //清除按鈕出現動畫
    private ValueAnimator mAnimator_visible;
    //消失動畫
    private ValueAnimator mAnimator_gone;
    //是否顯示的記錄
    private boolean isVisible = false;
    //右邊添加其他按鈕時使用
    private int mRight = 0;

    public ClearEditText(final Context context) {
        super(context);
        init(context);
    }

    public ClearEditText(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ClearEditText(final Context context, final AttributeSet attrs, final int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {

        mBitmap_clear = createBitmap(CLEAR,context);

        Interval = dp2px(INTERVAL);
        mWidth_clear = dp2px(WIDTH_OF_CLEAR);
        mPaddingRight = Interval + mWidth_clear + Interval ;
        mAnimator_gone = ValueAnimator.ofFloat(1f, 0f).setDuration(ANIMATOR_TIME);
        mAnimator_visible = ValueAnimator.ofInt(mWidth_clear + Interval,0).setDuration(ANIMATOR_TIME);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //設置內邊距
        setPadding(getPaddingLeft(), getPaddingTop(), mPaddingRight+ mRight, getPaddingBottom());

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));//抗鋸齒
        if (mAnimator_visible.isRunning()) {
            int x = (int) mAnimator_visible.getAnimatedValue();
            drawClear(x,canvas);
            invalidate();
        }else if (isVisible){
            drawClear(0,canvas);
        }

        if(mAnimator_gone.isRunning()){
            float scale = (float) mAnimator_gone.getAnimatedValue();
            drawClearGone(scale, canvas);
            invalidate();
        }
    }

    /**
     * 繪製清除按鈕出現的圖案
     * @param translationX 水平移動距離
     * @param canvas
     */
    protected void drawClear( int translationX,Canvas canvas){
        int right = getWidth()+getScrollX() - Interval - mRight +translationX;
        int left = right-mWidth_clear;
        int top = (getHeight()-mWidth_clear)/2;
        int bottom = top + mWidth_clear;
        Rect rect = new Rect(left,top,right,bottom);
        canvas.drawBitmap(mBitmap_clear, null, rect, null);

    }

    /**
     * 繪製清除按鈕消失的圖案
     * @param scale 縮放比例
     * @param canvas
     */
    protected void drawClearGone( float scale,Canvas canvas){
        int right = (int) (getWidth()+getScrollX()- Interval - mRight -mWidth_clear*(1f-scale)/2f);
        int left = (int) (getWidth()+getScrollX()- Interval - mRight -mWidth_clear*(scale+(1f-scale)/2f));
        int top = (int) ((getHeight()-mWidth_clear*scale)/2);
        int bottom = (int) (top + mWidth_clear*scale);
        Rect rect = new Rect(left,top,right,bottom);
        canvas.drawBitmap(mBitmap_clear, null, rect, null);
    }

    /**
     * 開始清除按鈕的顯示動畫
     */
    private void startVisibleAnimator() {
        endAnaimator();
        mAnimator_visible.start();
        invalidate();
    }

    /**
     * 開始清除按鈕的消失動畫
     */
    private void startGoneAnimator() {
        endAnaimator();
        mAnimator_gone.start();
        invalidate();
    }

    /**
     * 結束所有動畫
     */
    private void endAnaimator(){
        mAnimator_gone.end();
        mAnimator_visible.end();
    }

    /**
     * Edittext內容變化的監聽
     * @param text
     * @param start
     * @param lengthBefore
     * @param lengthAfter
     */
    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);

        if(text.length()>0) {
            if (!isVisible) {
                isVisible = true;
                startVisibleAnimator();
            }
        }else{
            if (isVisible) {
                isVisible = false;
                startGoneAnimator();
            }
        }
    }

    /**
     * 觸控執行的監聽
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {

            boolean touchable = ( getWidth() - Interval - mRight - mWidth_clear < event.getX() ) && (event.getX() < getWidth() - Interval - mRight);
            if (touchable) {
                setError(null);
                this.setText("");
            }
        }
        return super.onTouchEvent(event);
    }

    /**
     * 開始晃動動畫
     */
    public void startShakeAnimation(){
        if(getAnimation() == null){
            this.setAnimation(shakeAnimation(4));
        }
        this.startAnimation(getAnimation());
    }

    /**
     * 晃動動畫
     * @param counts 0.5秒鐘晃動多少下
     * @return
     */
    private Animation shakeAnimation(int counts){
        Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);
        translateAnimation.setInterpolator(new CycleInterpolator(counts));
        translateAnimation.setDuration(500);
        return translateAnimation;
    }

    /**
     * 給圖標染上當前提示文本的顏色並且轉出Bitmap
     * @param resources
     * @param context
     * @return
     */
    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 drawableToBitamp(wrappedDrawable);
    }

    /**
     * drawable轉換成bitmap
     * @param drawable
     * @return
     */
    private Bitmap drawableToBitamp(Drawable drawable)
    {
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
        Bitmap bitmap = Bitmap.createBitmap(w, h, config);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }

    public int dp2px(float dipValue) {
        final float scale = getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    //----------------以下方法爲方便子類繼承,只使用ClearEditText就沒有用處---------------------------------------------------------------------

    public int getInterval() {
        return  Interval;
    }

    public int getmWidth_clear() {
        return mWidth_clear;
    }

    public Bitmap getmBitmap_clear() {
        return mBitmap_clear;
    }

    public void addRight(int right){
        mRight += right;
    }



}

PasswordEditText .java



import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * Created by 家傑 on 2015/11/20.
 */
public class PasswordEditText extends ClearEditText{

    //資源
    private final int INVISIBLE = R.drawable.close;
    private final int VISIBLE = R.drawable.open;
    //按鈕寬度dp
    private int mWidth;
    //按鈕的bitmap
    private Bitmap mBitmap_invisible;
    private Bitmap mBitmap_visible;
    //間隔
    private int Interval;
    //內容是否可見
    private boolean isVisible = false;

    public PasswordEditText(final Context context) {
        super(context);
        init(context);
    }

    public PasswordEditText(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PasswordEditText(final Context context, final AttributeSet attrs, final int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        setSingleLine();
        //設置EditText文本爲隱藏的(注意!需要在setSingleLine()之後調用)
        setTransformationMethod(PasswordTransformationMethod.getInstance());

        mWidth = getmWidth_clear();
        Interval = getInterval();
        addRight(mWidth+Interval);
        mBitmap_invisible = createBitmap(INVISIBLE,context);
        mBitmap_visible = createBitmap(VISIBLE,context);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int right = getWidth()+getScrollX()- Interval ;
        int left = right-mWidth;
        int top = (getHeight()-mWidth)/2;
        int bottom = top + mWidth;
        Rect rect = new Rect(left,top,right,bottom);

        if(isVisible){
            canvas.drawBitmap(mBitmap_visible, null, rect, null);
        }else{
            canvas.drawBitmap(mBitmap_invisible, null, rect, null);
        }
    }

    /**
     * 改寫父類的方法
     */
    @Override
    protected void drawClear(int translationX, Canvas canvas) {
        float scale = 1f - (float)(translationX)/(float)(getmWidth_clear()+Interval);
        int right = (int) (getWidth()+getScrollX()- Interval-mWidth-Interval -getmWidth_clear()*(1f-scale)/2f);
        int left = (int) (getWidth()+getScrollX()- Interval-mWidth-Interval -getmWidth_clear()*(scale+(1f-scale)/2f));
        int top = (int) ((getHeight()-getmWidth_clear()*scale)/2);
        int bottom = (int) (top + getmWidth_clear()*scale);
        Rect rect = new Rect(left,top,right,bottom);
        canvas.drawBitmap(getmBitmap_clear(), null, rect, null);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            boolean touchable = ( getWidth() - mWidth - Interval < event.getX() ) && (event.getX() < getWidth() - Interval);
            if (touchable) {
                isVisible = !isVisible;
                if (isVisible){
                    //設置EditText文本爲可見的
                    setTransformationMethod(HideReturnsTransformationMethod.getInstance());
                }else{
                    //設置EditText文本爲隱藏的
                    setTransformationMethod(PasswordTransformationMethod.getInstance());
                }
            }
        }
        return super.onTouchEvent(event);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章