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 布局文件
<?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="45dp" android:orientation="horizontal" android:paddingHorizontal="20dp"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="折扣率:" android:textColor="@color/color_text_333333" android:textSize="14sp" /> <EditText android:id="@+id/et_clean_goods_discount" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@null" android:contentDescription="折扣" android:gravity="center" android:inputType="numberDecimal" android:paddingHorizontal="5dp" android:selectAllOnFocus="true" android:singleLine="true" android:textColor="@color/color_text_333333" android:textSize="14sp" android:textStyle="bold" /> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="%" android:textColor="@color/color_text_333333" android:textSize="14sp" /> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="20dp" android:gravity="center" android:text="*" android:textColor="@color/red" android:textSize="14sp" /> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="清仓价:" android:textColor="@color/color_text_333333" android:textSize="14sp" /> <EditText android:id="@+id/et_clean_goods_price" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@null" android:contentDescription="清仓价" android:gravity="center" android:inputType="numberDecimal" android:paddingHorizontal="5dp" android:selectAllOnFocus="true" android:singleLine="true" android:textColor="@color/color_text_333333" android:textSize="14sp" android:textStyle="bold" /> </LinearLayout>