Android EditText与GridLayout实现表格效果

Android EditText与GridLayout实现表格效果,实现ExclExcle效果,统计手机价格总和的简单实现

demo下载地址:DouYinWu-master案例集合.zip

效果图:

1.主函数布局:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <!--6行4列
    实现占满整个屏幕-->

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <com.example.qd.douyinwu.utils.ExtendedEditText
            android:id="@+id/input"
            style="@android:style/Widget.Holo.EditText"
            android:layout_width="400dp"
            android:layout_height="60dp"
            android:padding="4dp"
            android:gravity="top"
            android:textSize="24dp"
            android:hint="top"
            android:inputType="textPassword"
            app:buttonMargin="10dp"
            app:buttonAlwaysCenter="false" />
        <com.example.qd.douyinwu.utils.BiuEditText
            style="@android:style/Widget.Holo.EditText"
            android:layout_width="400dp"
            android:layout_height="60dp"
            android:padding="4dp"
            android:gravity="top"
            android:textSize="24dp"
            android:hint="top"
            android:inputType="textPassword"
            app:buttonMargin="10dp"
            app:buttonAlwaysCenter="false" />

    <GridLayout
        android:layout_marginTop="10dp"
        android:layout_width="325dp"
        android:layout_height="match_parent"
        android:columnCount="4"
        android:layout_gravity="center_horizontal"
        android:background="#333"
        android:rowCount="4">
        <!--跨四列 自动填充 权重2-->
        <TextView
            android:text=""
            android:background="@color/white"
            android:layout_gravity="center"
            android:layout_width="80dp"
            android:gravity="center"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginTop="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />

        <TextView
            android:text="售价"
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginTop="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:text="奖金"
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginTop="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:text="补贴"
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_marginTop="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />

        <!--第二行-->
        <TextView
            android:text="小米"
            android:background="@color/white"
            android:layout_gravity="center"
            android:layout_width="80dp"
            android:gravity="center"
            android:layout_height="match_parent"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20sp" />

        <com.example.qd.douyinwu.utils.BiuEditText
            android:id="@+id/et_mi_price"
            android:background="@color/white"
            android:gravity="center"
            android:inputType="number"
            android:maxLength="5"
            android:singleLine="true"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <!--第三行-->
        <TextView
            android:text="华为"
            android:background="@color/white"
            android:layout_gravity="center"
            android:layout_width="80dp"
            android:gravity="center"
            android:layout_height="match_parent"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20sp" />

        <EditText
            android:id="@+id/et_hw_price"
            android:background="@color/white"
            android:gravity="center"
            android:inputType="number"
            android:maxLength="5"
            android:singleLine="true"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <!--第四行-->
        <TextView
            android:text="合计:"
            android:background="@color/white"
            android:layout_gravity="center"
            android:layout_width="80dp"
            android:gravity="center"
            android:layout_height="match_parent"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20sp" />

        <EditText
            android:id="@+id/et_total_price"
            android:background="@color/white"
            android:gravity="center"
            android:enabled="false"
            android:layout_width="80dp"
            android:inputType="number"
            android:maxLength="5"
            android:singleLine="true"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
        <TextView
            android:background="@color/white"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="1dp"
            android:layout_marginLeft="1dp"
            android:layout_marginBottom="1dp"
            android:textColor="#00F"
            android:textSize="20dp" />
    </GridLayout>
    </LinearLayout>
</ScrollView>

2.主函数代码:

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;

import com.example.qd.douyinwu.R;
import com.example.qd.douyinwu.utils.EditTextUtils;
import com.example.qd.douyinwu.utils.ExtendedEditText;

/**
 * 网格布局使用
 * https://www.cnblogs.com/Chenshuai7/p/5321766.html  计算器的布局
 *
 *
 * GridLayout 使用总结
 * https://blog.csdn.net/weixin_39251617/article/details/79711668
 *
 *
 * Android自定义控件仿黑客帝国数字雨
 * https://github.com/skateboard1991/NumberRain
 */
public class GridLayoutActivity extends AppCompatActivity {

    private EditText etMiPrice;
    private EditText etHwPrice;
    private EditText etTotalPrice;
    private double dMiPrice;
    private double dHwPrice;
    private double mTotalPriceMax = 99.0;//总价格最大值
    private double mPriceMax = 60.0;//单价最大值

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_numberrain);//Android自定义控件仿黑客帝国数字雨
        setContentView(R.layout.activity_gv_layout);

        initView();
        initData();

//        setSupportActionBar(toolbar);
        ExtendedEditText mInputView = (ExtendedEditText) findViewById(R.id.input);
        mInputView.setClearDrawable(getResources().getDrawable(R.drawable.ic_clear));
//        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
//        fab.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View view) {
//                mInputView.setClearDrawable(getResources().getDrawable(R.drawable.ic_clear));
//            }
//        });
    }

    /**
     * 逻辑处理
     * 小米手机单价不得大于60.00元人民币
     * 华为手机单价不得大于60.00元人民币
     * 小米、华为手机的总价不得大于99.00元人民币
     */
    private void initData() {
        //
        java.text.DecimalFormat df = new java.text.DecimalFormat("#.0");//保留一位小数
//        df.format(20);
//        etMiPrice.setText(df.format(20)+"");
//        etHwPrice.setText(df.format(30)+"");
        //小米价格监听
        EditTextUtils.setMiTextWatcher(etMiPrice,etHwPrice,etTotalPrice,"");
//        etMiPrice.addTextChangedListener(new TextWatcher() {
//            @Override
//            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//
//            }
//
//            @Override
//            public void onTextChanged(CharSequence s, int start, int before, int count) {
//
//            }
//
//            @Override
//            public void afterTextChanged(Editable s) {
//                String MiPrice = s.toString();
//                //将输入数值转成Double类型,保留一位小数
//                if(!TextUtils.isEmpty(MiPrice)){
//                    //判断是否含有点,有则截取,否则转行类型会报异常
//                    if(MiPrice.contains(".")){
//                        String result = MiPrice.substring(0, MiPrice.indexOf("."));
//                        if(!TextUtils.isEmpty(result)){
//                            dMiPrice = Double.parseDouble(result);
//                        }
//                    }else {
//                        dMiPrice = Double.parseDouble(MiPrice);
//                    }
//                    if(dMiPrice > mPriceMax){
//                        etMiPrice.setError("小米手机单价不得大于" + mPriceMax + "元");
//                        etMiPrice.setText(mPriceMax+"");
//                        etMiPrice.setSelection(MiPrice.length());
//                        Animation shake = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.shake);
//                        etMiPrice.startAnimation(shake);
//                    }
//
//                    //计算手机总价
//                    //判断华为手机价格
//                    String hwPrice = etHwPrice.getText().toString();
//                    if(!TextUtils.isEmpty(hwPrice)){
//                        if(hwPrice.contains(".")){
//                            String result = hwPrice.substring(0, hwPrice.indexOf("."));
//                            dHwPrice = Double.parseDouble(result);
//                        }else {
//                            dHwPrice = Double.parseDouble(hwPrice);
//                        }
//                        if(dHwPrice + dMiPrice > mTotalPriceMax){
//                            etMiPrice.setError("小米、华为手机总价不得大于" + mTotalPriceMax + "元");
//                            etMiPrice.setText("");
                            etMiPrice.setSelection(MiPrice.length());
//                        }
//                    }
//
//                    if(!TextUtils.isEmpty(hwPrice)&&!TextUtils.isEmpty(MiPrice)){
//                        etTotalPrice.setText(dHwPrice+dMiPrice+"");
//                    }
//                }
//
//            }
//        });

        //华为价格监听
        EditTextUtils.setHwTextWatcher(etHwPrice,etMiPrice,etTotalPrice,"");
//        etHwPrice.addTextChangedListener(new TextWatcher() {
//            @Override
//            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//
//            }
//
//            @Override
//            public void onTextChanged(CharSequence s, int start, int before, int count) {
//
//            }
//
//            @Override
//            public void afterTextChanged(Editable s) {
//                String HwPrice = s.toString();
//                //将输入数值转成Double类型,保留一位小数
//                if(!TextUtils.isEmpty(HwPrice)){
//                    //判断是否含有点,有则截取,否则转行类型会报异常
//                    if(HwPrice.contains(".")){
//                        String result = HwPrice.substring(0, HwPrice.indexOf("."));
//                        dHwPrice = Double.parseDouble(result);
//
//                    }else {
//                        dHwPrice = Double.parseDouble(HwPrice);
//                    }
//                    if(dHwPrice > mPriceMax){
//                        etHwPrice.setError("华为手机单价不得大于" + mPriceMax + "元");
//                        etHwPrice.setText(mPriceMax+"");
                        etHwPrice.setSelection(HwPrice.length());
//                    }
//                    //计算手机总价
//                    //判断小米手机价格
//                    String miPrice = etMiPrice.getText().toString();
//                    if(!TextUtils.isEmpty(miPrice)){
//                        if(miPrice.contains(".")){
//                            String result = miPrice.substring(0, miPrice.indexOf("."));
//                            dMiPrice = Double.parseDouble(result);
//                        }else {
//                            dMiPrice = Double.parseDouble(miPrice);
//                        }
//                        if(dHwPrice + dMiPrice > mTotalPriceMax){
//                            etHwPrice.setError("小米、华为手机总价不得大于" + mTotalPriceMax + "元");
//                            etHwPrice.setText("");
                                etHwPrice.setSelection(HwPrice.length());
//                        }
//                    }
//                    String hwPrice = etHwPrice.getText().toString();
//
//                    if(!TextUtils.isEmpty(hwPrice)&&!TextUtils.isEmpty(miPrice)){
//                        etTotalPrice.setText(dHwPrice+dMiPrice+"");
//                    }
//                }
//
//            }
//        });
    }

    /**
     * 初始化控件
     */
    private void initView() {
        etMiPrice = findViewById(R.id.et_mi_price);//小米手机官方售价
        etHwPrice = findViewById(R.id.et_hw_price);//华为手机官方售价
        etTotalPrice = findViewById(R.id.et_total_price);//官方售价合计
    }
}

3.EditText工具类:

package com.example.qd.douyinwu.utils;

import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;

import com.example.qd.douyinwu.R;

/**
 * EditText监听工具类
 */
public class EditTextUtils {

    private static double dHwPrice;
    private static double dMiPrice;
    private static double mPriceMax = 60.0;//单价最大值
    private static double mTotalPriceMax = 99.0;//总价格最大值

    /**
     * 设置华为价格监听逻辑
     * @param hwEditText
     * @param miEditText
     * @param totalEditText
     * @param str
     */
    public static void setHwTextWatcher(final EditText hwEditText,final EditText miEditText, final EditText totalEditText,String str){
        //华为价格监听
        hwEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                String HwPrice = s.toString();
                //将输入数值转成Double类型,保留一位小数
                if(!TextUtils.isEmpty(HwPrice)){
                    //判断是否含有点,有则截取,否则转行类型会报异常
                    if(HwPrice.contains(".")){
                        String result = HwPrice.substring(0, HwPrice.indexOf("."));
                        dHwPrice = Double.parseDouble(result);

                    }else {
                        dHwPrice = Double.parseDouble(HwPrice);
                    }
                    if(dHwPrice > mPriceMax){
                        hwEditText.setError("华为手机单价不得大于" + mPriceMax + "元");
                        hwEditText.setText(mPriceMax+"");
//                        etHwPrice.setSelection(HwPrice.length());
                    }
                    //计算手机总价
                    //判断小米手机价格
                    String miPrice = miEditText.getText().toString();
                    if(!TextUtils.isEmpty(miPrice)){
                        if(miPrice.contains(".")){
                            String result = miPrice.substring(0, miPrice.indexOf("."));
                            dMiPrice = Double.parseDouble(result);
                        }else {
                            dMiPrice = Double.parseDouble(miPrice);
                        }
                        if(dHwPrice + dMiPrice > mTotalPriceMax){
                            hwEditText.setError("小米、华为手机总价不得大于" + mTotalPriceMax + "元");
                            hwEditText.setText("");
//                                etHwPrice.setSelection(HwPrice.length());
                        }
                    }
                    String hwPrice = hwEditText.getText().toString();

                    if(!TextUtils.isEmpty(hwPrice)&&!TextUtils.isEmpty(miPrice)){
                        totalEditText.setText(dHwPrice+dMiPrice+"");
                    }
                }

            }
        });
    }

    public static void setMiTextWatcher(final EditText miEditText,final EditText hwEditText, final EditText totalEditText,String str){
        //小米价格监听
        miEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                String MiPrice = s.toString();
                //将输入数值转成Double类型,保留一位小数
                if(!TextUtils.isEmpty(MiPrice)){
                    //判断是否含有点,有则截取,否则转行类型会报异常
                    if(MiPrice.contains(".")){
                        String result = MiPrice.substring(0, MiPrice.indexOf("."));
                        if(!TextUtils.isEmpty(result)){
                            dMiPrice = Double.parseDouble(result);
                        }
                    }else {
                        dMiPrice = Double.parseDouble(MiPrice);
                    }
                    if(dMiPrice > mPriceMax){
                        miEditText.setError("小米手机单价不得大于" + mPriceMax + "元");
                        miEditText.setText(mPriceMax+"");
//                        miEditText.setSelection(MiPrice.length());
//                        Animation shake = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.shake);
//                        miEditText.startAnimation(shake);
                    }

                    //计算手机总价
                    //判断华为手机价格
                    String hwPrice = hwEditText.getText().toString();
                    if(!TextUtils.isEmpty(hwPrice)){
                        if(hwPrice.contains(".")){
                            String result = hwPrice.substring(0, hwPrice.indexOf("."));
                            dHwPrice = Double.parseDouble(result);
                        }else {
                            dHwPrice = Double.parseDouble(hwPrice);
                        }
                        if(dHwPrice + dMiPrice > mTotalPriceMax){
                            miEditText.setError("小米、华为手机总价不得大于" + mTotalPriceMax + "元");
                            miEditText.setText("");
//                            etMiPrice.setSelection(MiPrice.length());
                        }
                    }

                    if(!TextUtils.isEmpty(hwPrice)&&!TextUtils.isEmpty(MiPrice)){
                        totalEditText.setText(dHwPrice+dMiPrice+"");
                    }
                }

            }
        });
    }
}

 4.带有删除功能的输入框:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;

/**
 * ExtendedEditText is an extended EditText.
 * To allow users to clear all input text
 * and view(or hide) password.
 *
 * <p>
 * <b>XML attributes</b>
 * <p>
 * @see {@link R.styleable#ExtendedEditText ExtendedEditText Attributes},
 *
 * @attr ref R.styleable#ExtendedEditText_clearDrawable
 * @attr ref R.styleable#ExtendedEditText_eyeDrawable
 * @attr ref R.styleable#ExtendedEditText_eyeOffDrawable
 * @attr ref R.styleable#ExtendedEditText_enableClear
 * @attr ref R.styleable#ExtendedEditText_enableEye
 * @attr ref R.styleable#ExtendedEditText_buttonMargin
 * @attr ref R.styleable#ExtendedEditText_buttonAlwaysCenter
 */

public class ExtendedEditText extends EditText {

    private static final String LOG_TAG = "ExtendedEditText";

    private Drawable mClearDrawable;
    private Drawable mEyeDrawable;
    private Drawable mEyeOffDrawable;

    /** Whether this view allows users to clear text. */
    private boolean mEnableClear;

    /** Whether this view allows users to view password.  */
    private boolean mEnableEye;

    /** The right margin of clear(eye) button. */
    private int mButtonMargin;

    /** Whether the buttons are always in the center of the view */
    private boolean mButtonAlwaysCenter;

    /** The input type set by users */
    private int mInputType;

    private Rect mClearRect;
    private Rect mDrawClearRect;
    private Rect mEyeRect;
    private Rect mDrawEyeRect;

    /** The right padding set by users */
    private int mOriginalPaddingRight;

    /** Whether the password is visible */
    private boolean mIsEyeOff = false;

    public ExtendedEditText(Context context) {
        this(context, null);
    }

    public ExtendedEditText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ExtendedEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mInputType = getInputType();

        /* Get right padding set by users */
        mOriginalPaddingRight = getPaddingRight();

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ExtendedEditText,
                defStyleAttr, 0);

        mClearDrawable = a.getDrawable(R.styleable.ExtendedEditText_clearDrawable);
        if (mClearDrawable == null) {
            mClearDrawable = context.getResources()
                    .getDrawable(R.drawable.default_extended_edit_text_clear_drawable);
        }

        mEyeDrawable = a.getDrawable(R.styleable.ExtendedEditText_eyeDrawable);
        if (mEyeDrawable == null) {
            mEyeDrawable = context.getResources()
                    .getDrawable(R.drawable.default_extended_edit_text_eye_drawable);
        }

        mEyeOffDrawable = a.getDrawable(R.styleable.ExtendedEditText_eyeOffDrawable);
        if (mEyeOffDrawable == null) {
            mEyeOffDrawable = context.getResources()
                    .getDrawable(R.drawable.default_extended_edit_text_eye_off_drawable);
        }

        mEnableClear = a.getBoolean(R.styleable.ExtendedEditText_enableClear, true);
        mEnableEye = a.getBoolean(R.styleable.ExtendedEditText_enableEye, true);
        enableEye(mEnableEye);

        mButtonMargin = a.getDimensionPixelSize(R.styleable.ExtendedEditText_buttonMargin,
                context.getResources().getDimensionPixelSize(
                        R.dimen.default_extended_edit_text_button_margin));

        mButtonAlwaysCenter = a.getBoolean(R.styleable.ExtendedEditText_buttonAlwaysCenter, true);
        a.recycle();

        /* Set new padding with clear button and eye button */
        setPadding(getPaddingLeft(), getPaddingTop(), mOriginalPaddingRight, getPaddingBottom());

        mClearRect = new Rect();
        mDrawClearRect = new Rect();
        mEyeRect = new Rect();
        mDrawEyeRect = new Rect();
    }

    public void setClearDrawable(Drawable drawable) {
        mClearDrawable = drawable;
        invalidate();
    }

    public void setEyeDrawable(Drawable drawable) {
        mEyeDrawable = drawable;
        invalidate();
    }

    public void setEyeOffDrawable(Drawable drawable) {
        mEyeOffDrawable = drawable;
        invalidate();
    }

    public void setButtonMargin(int margin) {
        mButtonMargin = margin;
        invalidate();
    }

    public void setButtonAlwaysCenter(boolean alwaysCenter) {
        mButtonAlwaysCenter = alwaysCenter;
        requestLayout();
    }

    public void enableClear(boolean enable) {
        mEnableClear = enable;
        invalidate();
    }

    public void enableEye(boolean enable) {
        mEnableEye = enable && isPasswordInputType();
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        final int scrollX = getScrollX();
        final int scrollY = getScrollY();

        if (isClearEnable()) {
            mDrawClearRect.set(
                    mClearRect.left + scrollX,
                    mClearRect.top+ scrollY,
                    mClearRect.right + scrollX,
                    mClearRect.bottom+ scrollY
            );
            mClearDrawable.setBounds(mDrawClearRect);
            mClearDrawable.draw(canvas);
        }

        if (isEyeEnable()) {
            mDrawEyeRect.set(
                    mEyeRect.left + scrollX,
                    mEyeRect.top+ scrollY,
                    mEyeRect.right + scrollX,
                    mEyeRect.bottom+ scrollY);
            mEyeDrawable.setBounds(mDrawEyeRect);

            if (mIsEyeOff && mEyeOffDrawable != null) {
                mEyeOffDrawable.setBounds(mDrawEyeRect);
                mEyeOffDrawable.draw(canvas);

            } else if (!mIsEyeOff) {
                mEyeDrawable.draw(canvas);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /*
         * If users touch inside clear button and enable clear, clear text.
         * Else if users touch inside eye button and enable view password,
         * show the text if it's invisible, else, hide it.
         */
        float x;
        float y;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                x = event.getX();
                y = event.getY();
                if ((isInsideClear(x, y) && isClearEnable())
                        || (isInsideEye(x, y) && isEyeEnable())) {
                    return true;
                }
                break;
            }

            case MotionEvent.ACTION_UP: {
                x = event.getX();
                y = event.getY();

                if (isInsideClear(x, y) && isClearEnable()) {
                    clear();
                    return false;
                }

                if (isEyeEnable() && isInsideEye(x, y)) {
                    if (mIsEyeOff) {
                        mIsEyeOff = false;
                        setInputType(mInputType);
                        setSelection(getText().length());
                    } else {
                        mIsEyeOff = true;
                        setInputType(InputType.TYPE_CLASS_TEXT);
                        setSelection(getText().length());
                    }
                    return false;
                }
                break;
            }

        }
        return super.onTouchEvent(event);
    }

    private boolean isInsideClear(float x, float y) {
        return mClearRect.contains((int) x, (int) y);
    }

    private boolean isInsideEye(float x, float y) {
        return mEyeRect.contains((int) x, (int) y);
    }

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

        final int width = getMeasuredWidth();
        final int height = getMeasuredHeight();

        final int gravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;

        int offset = 0;
        int left;
        int top;

        /* Calculates the bounding rectangles of mEyeDrawable, mEyeOffDrawable,
         * and mClearDrawable. The rectangle indicates the location of drawable
         * int this view.
         */
        if (mEnableEye && mEyeDrawable != null) {
            offset += mButtonMargin + mEyeDrawable.getIntrinsicWidth();
            left = width - offset;

            if (mButtonAlwaysCenter) {
                top = (height - mEyeDrawable.getIntrinsicHeight()) / 2;
            } else {
                if (gravity == Gravity.TOP) {
                    top = getPaddingTop();
                } else if (gravity == Gravity.BOTTOM) {
                    top = height - getPaddingBottom() - mEyeDrawable.getIntrinsicHeight();
                } else {
                    top = (height - mEyeDrawable.getIntrinsicHeight()) / 2;
                }
            }

            mEyeRect.set(left, top, left + mEyeDrawable.getIntrinsicWidth(),
                    top + mEyeDrawable.getIntrinsicHeight());
            mEyeDrawable.setBounds(mEyeRect);
            if (mEyeOffDrawable != null) {
                mEyeOffDrawable.setBounds(mEyeRect);
            }
        }

        if (mEnableClear && mClearDrawable != null) {
            offset += mButtonMargin + mClearDrawable.getIntrinsicWidth();
            left = width - offset;

            if (mButtonAlwaysCenter) {
                top = (height - mClearDrawable.getIntrinsicHeight()) / 2;
            } else {
                if (gravity == Gravity.TOP) {
                    top = getPaddingTop();
                } else if (gravity == Gravity.BOTTOM) {
                    top = height - getPaddingBottom() - mClearDrawable.getIntrinsicHeight();
                } else {
                    top = (height - mClearDrawable.getIntrinsicHeight()) / 2;
                }
            }

            // top = getPaddingTop() + (height - mClearDrawable.getIntrinsicHeight()) / 2;
            mClearRect.set(left, top,
                    left + mClearDrawable.getIntrinsicWidth(),
                    top + mClearDrawable.getIntrinsicHeight());
            mClearDrawable.setBounds(mClearRect);
        }
    }

    @Override
    public void setPadding(int left, int top, int right, int bottom) {
        mOriginalPaddingRight = right;
        super.setPadding(left, top, getRealPaddingRight(right), bottom);
    }

    /**
     * Returns new right padding. If it is enable to view password, plus
     * the width of {@link #mEyeDrawable} and {@link #mButtonMargin}.
     * If it is enable to clear text, plus the width of
     * {@link #mClearDrawable} and {@link #mButtonMargin}.
     *
     * @param right The original right padding set by users
     * @return The new right padding
     */
    private int getRealPaddingRight(int right) {
        if (mEnableEye && mEyeDrawable != null) {
            right += mButtonMargin + mEyeDrawable.getIntrinsicWidth();
        }

        if (mEnableClear && mClearDrawable != null) {
            right += mButtonMargin + mClearDrawable.getIntrinsicWidth();
        }

        return right;
    }

    /**
     * Sets text null.
     */
    private void clear() {
        setText(null);
    }

    private boolean isEmpty() {
        return TextUtils.isEmpty(getText().toString());
    }

    private boolean isClearEnable() {
        return mEnableClear && !isEmpty() && mClearDrawable != null;
    }

    private boolean isEyeEnable() {
        return mEnableEye && !isEmpty() && mEyeDrawable != null;
    }

    /**
     * Returns whether the input type is password type.
     */
    private boolean isPasswordInputType() {
        final int variation =
                mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
        final boolean passwordInputType = variation
                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
        final boolean webPasswordInputType = variation
                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD);
        final boolean numberPasswordInputType = variation
                == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);

        return passwordInputType || webPasswordInputType || numberPasswordInputType;
    }
}

attrs.xml:

<declare-styleable name="ExtendedEditText">
        <!-- supports clear or not -->
        <attr name="enableClear" format="boolean" />
        <!-- drawable for btn to clear all text inputted -->
        <attr name="clearDrawable" format="reference" />
        <!-- supports viewing password or not  -->
        <attr name="enableEye" format="boolean" />
        <!-- drawable for btn when show password-->
        <attr name="eyeDrawable" format="reference" />
        <!-- drawable for btn when hide password -->
        <attr name="eyeOffDrawable" format="reference" />
        <!-- margin of button -->
        <attr name="buttonMargin" format="dimension" />
        <!-- if true, buttons are always in the center;
             if false, the gravity of buttons are the same with the view's gravity. -->
        <attr name="buttonAlwaysCenter" format="boolean" />
    </declare-styleable>

config.xml:(图片请自己去找 https://www.iconfont.cn/)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <drawable name="default_extended_edit_text_clear_drawable">@drawable/ic_clear_black_24dp</drawable>
    <drawable name="default_extended_edit_text_eye_drawable">@drawable/ic_visibility_black_24dp</drawable>
    <drawable name="default_extended_edit_text_eye_off_drawable">@drawable/ic_visibility_off_black_24dp</drawable>
    <dimen name="default_extended_edit_text_button_margin">8dp</dimen>
</resources>

5.  EditText文字输入飞入效果       https://blog.csdn.net/shenggaofei/article/details/52233128

参考:

https://github.com/vickykang/ExtendedEditText 

https://github.com/HITGIF/TextFieldBoxes

https://github.com/HITGIF/TextFieldBoxes

https://www.jianshu.com/p/e4a6757c2bd0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值