RecyclerView 完美嵌套EditText

RecyclerView中item嵌套EditText,总是会出现,焦点错乱,数据错乱

主要原因在于,EditText焦点发生变化的时候,监听也在变化,数据就会不断变化

解决方法:监听焦点变化,有焦点就添加:addTextChangedListener ;没有焦点就移除:removeTextChangedListener

关键代码:

mEtCleanGoodsDiscount.setOnFocusChangeListener((v, hasFocus) -> {
    if (hasFocus) {
        //有焦点,添加监听 addTextChangedListener
        addTextWatch(mEtCleanGoodsDiscount, 100.0f);
    } else {
        //无焦点,移除监听 removeTextChangedListener
        removeTextWatch(mEtCleanGoodsDiscount);
    }
});

以下是项目中的案例:列表中修改商品价格,折扣和价格联动变化(修改折扣,同时计算价格,反之,同理)

1、下面我自定义了一个View

/**
 * @filename ItemPriceView
 * @author:sen
 * @date 2020-01-04  18:22
 * @function: 列表嵌套EditView 价格编辑
 */
public class ItemPriceView extends FrameLayout {

    private EditText mEtCleanGoodsDiscount;
    private EditText mEtCleanGoodsPrice;
    private PriceTextWatcher mPriceTextWatcher;

    public ItemPriceView(@NonNull Context context) {
        super(context);
        init();
    }

    public ItemPriceView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs, 0);
        init();
    }

    public ItemPriceView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        View view = LayoutInflater.from(getContext()).inflate(R.layout.item_clean_goods_price_view, this, true);
        // 折扣
        mEtCleanGoodsDiscount = view.findViewById(R.id.et_clean_goods_discount);
        // 清仓价
        mEtCleanGoodsPrice = view.findViewById(R.id.et_clean_goods_price);

    }

    private WxGoods mWxGoods;

    public void setData(WxGoods wxGoods) {
        this.mWxGoods = wxGoods;


        mEtCleanGoodsDiscount.setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus) {
                //有焦点,添加监听,折扣最大值100
                addTextWatch(mEtCleanGoodsDiscount, 100.0f);
            } else {
                //无焦点,移除监听
                removeTextWatch(mEtCleanGoodsDiscount);
            }
        });

        mEtCleanGoodsPrice.setOnFocusChangeListener((v, hasFocus) -> {
            if (hasFocus) {
                //有焦点,添加监听,价格最大值
                addTextWatch(mEtCleanGoodsPrice, wxGoods.price);
            } else {
                //无焦点,移除监听
                removeTextWatch(mEtCleanGoodsPrice);
            }
        });


        mEtCleanGoodsDiscount.setText(String.format("%.2f", mWxGoods.getCleanDiscount()));
        mEtCleanGoodsPrice.setText(String.format("%.2f", wxGoods.getCleanPrice()));

    }

    private void addTextWatch(EditText editText, double max) {
        InputFilter inputFilter = (source, start, end, dest, dstart, dend) -> {
            // 删除等特殊字符,直接返回
            if (TextUtils.isEmpty(source)) {
                return null;
            }
            String dValue = dest.toString();
            String[] splitArray = dValue.split("\\.");
            if (splitArray.length > 1) {
                String dotValue = splitArray[1];
                // 2 表示输入框的小数位数
                int diff = dotValue.length() + 1 - 2;
                if (diff > 0) {
                    return source.subSequence(start, end - diff);
                }
            }
            return null;
        };

        editText.setFilters(new InputFilter[]{inputFilter});
        mPriceTextWatcher = new PriceTextWatcher(editText, max);
        editText.addTextChangedListener(mPriceTextWatcher);
    }

    private void removeTextWatch(EditText editText) {
        editText.removeTextChangedListener(mPriceTextWatcher);
    }

    private class PriceTextWatcher extends SimpleTextWatcher {

        private EditText editText;
        private double max = 100.0;

        public PriceTextWatcher(EditText editText, double max) {
            this.editText = editText;
            this.max = max;
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            String str = s.toString();
            if (str.startsWith(".")) {
                editText.setText("");
                return;
            }
            if (str.startsWith("00")) {
                editText.setText("0");
                editText.setSelection("0".length());
                return;
            }
            if (StringUtils.countMatches(str, ".") > 1 && str.endsWith(".")) {
                String content = str.substring(0, str.length() - 1);
                editText.setText(content);
                editText.setSelection(content.length());
                return;
            }

            if (NumberUtils.toDouble(str) > max) {
                String content = String.valueOf(max);
                editText.setText(content);
                editText.setSelection(content.length());
                return;
            }

            doResult(NumberUtils.toDouble(str), editText.getId() == R.id.et_clean_goods_discount);
        }

    }

    private void doResult(double data, boolean isDiscount) {
        if (isDiscount) {
            //当前是折扣,开始计算清仓价
            LogUtils.d("当前是折扣,开始计算清仓价>>>>>" + data);
            mWxGoods.clean_discount = data;
            if (data == 0) {
                mEtCleanGoodsPrice.setText(String.format("%.2f", 0.0f));
                mWxGoods.clean_price = 0.0;
                return;
            }
            mWxGoods.clean_price = mWxGoods.price * data / 100.0f;
            mEtCleanGoodsPrice.setText(String.format("%.2f", mWxGoods.getCleanPrice()));
        } else {
            //当前是清仓价,开始计算折扣
            LogUtils.d("当前是清仓价,开始计算折扣>>>>>" + data);
            mWxGoods.clean_price = data;
            if (data == 0) {
                mEtCleanGoodsDiscount.setText(String.format("%.2f", 0.0f));
                mWxGoods.clean_discount = 0.0;
                return;
            }
            mWxGoods.clean_discount = data / mWxGoods.price * 100.0f;
            mEtCleanGoodsDiscount.setText(String.format("%.2f", mWxGoods.getCleanDiscount()));
        }
    }
}

2、item_clean_goods_price_view.xml  布局文件



    

    

    

    

    

    

你可能感兴趣的:(知识点记录,Android,RecyclerView,嵌套EditText,列表EditText)