Android EditText与GridLayout实现表格效果

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

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

效果图:

Android EditText与GridLayout实现表格效果_第1张图片

1.主函数布局:



    

    
        
        

    
        
        

        
        
        

        
        

        
        
        
        
        

        
        
        
        
        

        
        
        
    
    

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.
 *
 * 

* XML attributes *

* @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:


        
        
        
        
        
        
        
        
        
        
        
        
        
        
    

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



    @drawable/ic_clear_black_24dp
    @drawable/ic_visibility_black_24dp
    @drawable/ic_visibility_off_black_24dp
    8dp

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

你可能感兴趣的:(EditText)