Android 为什么EditText中的输入值在循环视图中滚动时交换其位置?
将输入放入EditText后,如果向上或向下快速滚动,则输入值将在RecyclerView中的另一个EditText中交换位置。Android 为什么EditText中的输入值在循环视图中滚动时交换其位置?,android,android-edittext,android-recyclerview,android-viewholder,Android,Android Edittext,Android Recyclerview,Android Viewholder,将输入放入EditText后,如果向上或向下快速滚动,则输入值将在RecyclerView中的另一个EditText中交换位置。 滚动前,数据在第一次编辑文本中。 上下滚动后,first EditText的值将其位置更改为第四个,并且交换是随机的。是否有稳定数据的方法 以下是模型类: public class Product { public int pId; public String pName; public double unit_pri
滚动前,数据在第一次编辑文本中。
上下滚动后,first EditText的值将其位置更改为第四个,并且交换是随机的。是否有稳定数据的方法 以下是模型类:
public class Product {
public int pId;
public String pName;
public double unit_price;
public double discount;
}
以下是适配器类:
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductListHolder> {
Context context;
List<Product> productList;
public ProductAdapter(Context c, List<Product> lp){
this.context = c;
this.productList = lp;
}
public class ProductListHolder extends RecyclerView.ViewHolder{
TextView tvName;
TextView tvPrice;
TextView tvDiscount;
TextView tvTotal;
EditText etQuantity;
public ProductListHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
tvDiscount = (TextView) itemView.findViewById(R.id.tvDiscount);
tvTotal = (TextView) itemView.findViewById(R.id.tvTotal);
etQuantity = (EditText) itemView.findViewById(R.id.etQuantity);
}
}
@Override
public ProductListHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_row, viewGroup, false);
ProductListHolder ph = new ProductListHolder(v);
return ph;
}
@Override
public void onBindViewHolder(final ProductListHolder productListHolder, final int i) {
productListHolder.tvName.setText(productList.get(i).pName);
productListHolder.tvPrice.setText(String.valueOf(productList.get(i).unit_price));
productListHolder.tvDiscount.setText(String.valueOf(productList.get(i).discount));
productListHolder.etQuantity.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) {
if (!s.toString().equals("")){
double totalPrice = (productList.get(i).unit_price-productList.get(i).discount)* (Double.valueOf(s.toString()));
productListHolder.tvTotal.setText(String.valueOf(totalPrice));
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@Override
public int getItemCount() {
return productList.size();
}
公共类ProductAdapter扩展了RecyclerView.Adapter{
语境;
列出产品清单;
公共产品适配器(上下文c,列表lp){
this.context=c;
this.productList=lp;
}
公共类ProductListHolder扩展了RecyclerView.ViewHolder{
文本视图tvName;
文本视图价格;
TextView电视折扣;
TextView-tvTotal;
编辑文本数量;
公共产品列表持有者(查看项目视图){
超级(项目视图);
tvName=(TextView)itemView.findViewById(R.id.tvName);
tvPrice=(TextView)itemView.findViewById(R.id.tvPrice);
tvDiscount=(TextView)itemView.findViewById(R.id.tvDiscount);
tvTotal=(TextView)itemView.findViewById(R.id.tvTotal);
etQuantity=(EditText)itemView.findViewById(R.id.etQuantity);
}
}
@凌驾
公共产品列表持有者onCreateViewHolder(视图组视图组,int i){
视图v=LayoutInflater.from(viewGroup.getContext()).flate(R.layout.single_行,viewGroup,false);
ProductListHolder ph=新ProductListHolder(v);
回流ph值;
}
@凌驾
BindViewHolder上的公共无效(最终产品列表持有人ProductListHolder,最终int i){
productListHolder.tvName.setText(productList.get(i.pName));
productListHolder.tvPrice.setText(String.valueOf(productList.get(i).单价));
productListHolder.tvDiscount.setText(String.valueOf(productList.get(i.discount));
productListHolder.etQuantity.addTextChangedListener(新的TextWatcher(){
@凌驾
更改前文本之前的公共void(字符序列s、int start、int count、int after){
}
@凌驾
public void onTextChanged(字符序列、int start、int before、int count){
如果(!s.toString().equals(“”){
double totalPrice=(productList.get(i).unit_price-productList.get(i).折扣)*(double.valueOf(s.toString());
productListHolder.tvTotal.setText(String.valueOf(totalPrice));
}
}
@凌驾
公共无效后文本已更改(可编辑){
}
});
}
@凌驾
public int getItemCount(){
返回productList.size();
}
}
以下是主要活动:
public class MainActivity extends AppCompatActivity {
List<Product> productList;
RecyclerView recyclerView;
RecyclerView.Adapter mAdapter;
String[] names = {"A", "B", "C","D"};
double[] prices = {1000, 2000, 3000, 100};
double[] discounts = {10, 20, 30, 2};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initRecyclerView(); // Initializing Recycler View
new MyTask().execute();
}
public void initRecyclerView(){
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
}
private class MyTask extends AsyncTask<Void, Void, List<Product>> {
@Override
protected List<Product> doInBackground(Void... params) {
int sz = 24;
productList = new ArrayList<Product>();
for(int i=0; i<sz; i++){
Product p = new Product();
p.pId = i%4;
p.pName = names[i%4];
p.unit_price = prices[i%4];
p.discount = discounts[i%4];
productList.add(p);
}
return productList;
}
@Override
protected void onPostExecute(List<Product> products) {
super.onPostExecute(products);
mAdapter = new ProductAdapter(MainActivity.this, productList);
recyclerView.setAdapter(mAdapter);
}
}
}
public类MainActivity扩展了AppCompatActivity{
列出产品清单;
回收视图回收视图;
RecyclerView.适配器制造商;
字符串[]名称={“A”、“B”、“C”、“D”};
双[]价格={1000,2000,3000,100};
双[]折扣={10,20,30,2};
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initRecyclerView();//初始化回收器视图
新建MyTask().execute();
}
public void initRecyclerView(){
recyclerView=(recyclerView)findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
setLayoutManager(新的LinearLayoutManager(MainActivity.this));
}
私有类MyTask扩展了AsyncTask{
@凌驾
受保护列表doInBackground(无效…参数){
int sz=24;
productList=新的ArrayList();
对于(int i=0;i您正在调用etQuantity.addTextChangedListener
,但您从未删除侦听器,因此当视图持有者被回收时(也称为用于显示另一项),它将添加另一个文本更改侦听器(因此将注册两个不同的文本更改侦听器)
最简单的解决方法可能是在CreateViewHolder中只调用一次addTextChangedListener
,然后使用getAdapterPosition
而不是i
来获得位置。我已经解决了问题。
问题是,我在onBindViewHolder中添加了addTextChangedListener。因此EditText中的值总是混乱,因为当焦点转移时,另一个addTextChangedListener被注册。因此,我实现了另一个名为CustomEtListener的自定义类,并实现了它在TextWatcher中注册了自定义侦听器。因此,现在我在onCreateViewHolder中为每个EditText注册了自定义侦听器。并使用字符串数组来存储编辑文本的值。数组的大小是RecyclerView中的项数。方法updatePosition就在那里获取焦点项目的位置。然后,onTextChanged我只是将editText的值存储在数组中,并在onBindViewHolder中更新该editText的值。此后,每次滚动时,editText的值都不会更改
这是我的适配器类
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductListHolder> {
Context context;
List<Product> productList;
String[] etValArr;
double[] totalValue;
public ProductAdapter(Context c, List<Product> lp) {
this.context = c;
this.productList = lp;
// Create a new array which size matches the number of Edit Texts
etValArr = new String[productList.size()];
// and an array for holding all the values of each edit text
totalValue = new double[productList.size()];
}
public class ProductListHolder extends RecyclerView.ViewHolder {
TextView tvName;
TextView tvPrice;
TextView tvDiscount;
TextView tvTotal;
EditText etQuantity;
// Instance of a Custom edit text listener
public CustomEtListener myCustomEditTextListener;
public ProductListHolder(View itemView, CustomEtListener myLis) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
tvDiscount = (TextView) itemView.findViewById(R.id.tvDiscount);
tvTotal = (TextView) itemView.findViewById(R.id.tvTotal);
etQuantity = (EditText) itemView.findViewById(R.id.etQuantity);
// assign a new instance of addTextChangedListener for each item
myCustomEditTextListener = myLis;
etQuantity.addTextChangedListener(myCustomEditTextListener);
}
}
@Override
public ProductListHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_row, viewGroup, false);
ProductListHolder ph = new ProductListHolder(v, new CustomEtListener());
return ph;
}
@Override
public void onBindViewHolder(final ProductListHolder productListHolder, int i) {
productListHolder.tvName.setText(productList.get(i).pName);
productListHolder.tvPrice.setText(String.valueOf(productList.get(i).unit_price));
productListHolder.tvDiscount.setText(String.valueOf(productList.get(i).discount));
// Update the position when focus changes
productListHolder.myCustomEditTextListener.updatePosition(i);
// Setting the values accordingly
productListHolder.etQuantity.setText(etValArr[i]);
productListHolder.tvTotal.setText(String.valueOf(totalValue[i]));
}
@Override
public int getItemCount() {
return productList.size();
}
/**
* Custom class which implements Text Watcher
*/
private class CustomEtListener implements TextWatcher {
private int position;
/**
* Updates the position according to onBindViewHolder
*
* @param position - position of the focused item
*/
public void updatePosition(int position) {
this.position = position;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// Change the value of array according to the position
etValArr[position] = charSequence.toString();
// Doing the calculation
if (!etValArr[position].equals("")) {
totalValue[position] = (productList.get(position).unit_price - productList.get(position).discount) * (Double.valueOf(etValArr[position]));
} else {
totalValue[position] = 0.00;
}
}
@Override
public void afterTextChanged(Editable editable) {
}
}
}
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductListHolder> {
Context context;
List<Product> productList;
String[] etValArr;
double[] totalValue;
public ProductAdapter(Context c, List<Product> lp) {
this.context = c;
this.productList = lp;
// Create a new array which size matches the number of Edit Texts
etValArr = new String[productList.size()];
// and an array for holding all the values of each edit text
totalValue = new double[productList.size()];
}
public class ProductListHolder extends RecyclerView.ViewHolder implements TextCallBackListener {
TextView tvName;
TextView tvPrice;
TextView tvDiscount;
TextView tvTotal;
EditText etQuantity;
// Instance of a Custom edit text listener
public CustomEtListener myCustomEditTextListener;
public ProductListHolder(View itemView, CustomEtListener myLis) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
tvDiscount = (TextView) itemView.findViewById(R.id.tvDiscount);
tvTotal = (TextView) itemView.findViewById(R.id.tvTotal);
etQuantity = (EditText) itemView.findViewById(R.id.etQuantity);
// assign a new instance of addTextChangedListener for each item
myCustomEditTextListener = myLis;
etQuantity.addTextChangedListener(myCustomEditTextListener);
}
@Override
public void updateText(String val) {
tvTotal.setText(val);
}
}
@Override
public ProductListHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_row, viewGroup, false);
ProductListHolder ph = new ProductListHolder(v, new CustomEtListener());
return ph;
}
@Override
public void onBindViewHolder(final ProductListHolder productListHolder, int i) {
productListHolder.tvName.setText(productList.get(i).pName);
productListHolder.tvPrice.setText(String.valueOf(productList.get(i).unit_price));
productListHolder.tvDiscount.setText(String.valueOf(productList.get(i).discount));
// Update the position when focus changes
productListHolder.myCustomEditTextListener.updatePosition(i, productListHolder);
// Setting the values accordingly
productListHolder.etQuantity.setText(etValArr[i]);
//productListHolder.tvTotal.setText(String.valueOf(totalValue[i]));
}
@Override
public int getItemCount() {
return productList.size();
}
/**
* Custom class which implements Text Watcher
*/
private class CustomEtListener implements TextWatcher {
private int position;
TextCallBackListener textCallBackListener;
/**
* Updates the position according to onBindViewHolder
*
* @param position - position of the focused item
* @param pa - object of ProductListHolder Class
*/
public void updatePosition(int position, ProductListHolder pa) {
this.position = position;
// assigning it to the instance of the CallBackListener
textCallBackListener = (TextCallBackListener) pa;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// Change the value of array according to the position
etValArr[position] = charSequence.toString();
// Doing the calculation
if (!etValArr[position].equals("")) {
totalValue[position] = (productList.get(position).unit_price - productList.get(position).discount) * (Double.valueOf(etValArr[position]));
// triggering the callback function to update the total
textCallBackListener.updateText(String.valueOf(totalValue[position]));
} else {
totalValue[position] = 0.00;
textCallBackListener.updateText("0.00");
}
}
@Override
public void afterTextChanged(Editable editable) {
}
}
}
这是我更改的适配器类
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductListHolder> {
Context context;
List<Product> productList;
String[] etValArr;
double[] totalValue;
public ProductAdapter(Context c, List<Product> lp) {
this.context = c;
this.productList = lp;
// Create a new array which size matches the number of Edit Texts
etValArr = new String[productList.size()];
// and an array for holding all the values of each edit text
totalValue = new double[productList.size()];
}
public class ProductListHolder extends RecyclerView.ViewHolder {
TextView tvName;
TextView tvPrice;
TextView tvDiscount;
TextView tvTotal;
EditText etQuantity;
// Instance of a Custom edit text listener
public CustomEtListener myCustomEditTextListener;
public ProductListHolder(View itemView, CustomEtListener myLis) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
tvDiscount = (TextView) itemView.findViewById(R.id.tvDiscount);
tvTotal = (TextView) itemView.findViewById(R.id.tvTotal);
etQuantity = (EditText) itemView.findViewById(R.id.etQuantity);
// assign a new instance of addTextChangedListener for each item
myCustomEditTextListener = myLis;
etQuantity.addTextChangedListener(myCustomEditTextListener);
}
}
@Override
public ProductListHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_row, viewGroup, false);
ProductListHolder ph = new ProductListHolder(v, new CustomEtListener());
return ph;
}
@Override
public void onBindViewHolder(final ProductListHolder productListHolder, int i) {
productListHolder.tvName.setText(productList.get(i).pName);
productListHolder.tvPrice.setText(String.valueOf(productList.get(i).unit_price));
productListHolder.tvDiscount.setText(String.valueOf(productList.get(i).discount));
// Update the position when focus changes
productListHolder.myCustomEditTextListener.updatePosition(i);
// Setting the values accordingly
productListHolder.etQuantity.setText(etValArr[i]);
productListHolder.tvTotal.setText(String.valueOf(totalValue[i]));
}
@Override
public int getItemCount() {
return productList.size();
}
/**
* Custom class which implements Text Watcher
*/
private class CustomEtListener implements TextWatcher {
private int position;
/**
* Updates the position according to onBindViewHolder
*
* @param position - position of the focused item
*/
public void updatePosition(int position) {
this.position = position;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// Change the value of array according to the position
etValArr[position] = charSequence.toString();
// Doing the calculation
if (!etValArr[position].equals("")) {
totalValue[position] = (productList.get(position).unit_price - productList.get(position).discount) * (Double.valueOf(etValArr[position]));
} else {
totalValue[position] = 0.00;
}
}
@Override
public void afterTextChanged(Editable editable) {
}
}
}
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductListHolder> {
Context context;
List<Product> productList;
String[] etValArr;
double[] totalValue;
public ProductAdapter(Context c, List<Product> lp) {
this.context = c;
this.productList = lp;
// Create a new array which size matches the number of Edit Texts
etValArr = new String[productList.size()];
// and an array for holding all the values of each edit text
totalValue = new double[productList.size()];
}
public class ProductListHolder extends RecyclerView.ViewHolder implements TextCallBackListener {
TextView tvName;
TextView tvPrice;
TextView tvDiscount;
TextView tvTotal;
EditText etQuantity;
// Instance of a Custom edit text listener
public CustomEtListener myCustomEditTextListener;
public ProductListHolder(View itemView, CustomEtListener myLis) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
tvDiscount = (TextView) itemView.findViewById(R.id.tvDiscount);
tvTotal = (TextView) itemView.findViewById(R.id.tvTotal);
etQuantity = (EditText) itemView.findViewById(R.id.etQuantity);
// assign a new instance of addTextChangedListener for each item
myCustomEditTextListener = myLis;
etQuantity.addTextChangedListener(myCustomEditTextListener);
}
@Override
public void updateText(String val) {
tvTotal.setText(val);
}
}
@Override
public ProductListHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_row, viewGroup, false);
ProductListHolder ph = new ProductListHolder(v, new CustomEtListener());
return ph;
}
@Override
public void onBindViewHolder(final ProductListHolder productListHolder, int i) {
productListHolder.tvName.setText(productList.get(i).pName);
productListHolder.tvPrice.setText(String.valueOf(productList.get(i).unit_price));
productListHolder.tvDiscount.setText(String.valueOf(productList.get(i).discount));
// Update the position when focus changes
productListHolder.myCustomEditTextListener.updatePosition(i, productListHolder);
// Setting the values accordingly
productListHolder.etQuantity.setText(etValArr[i]);
//productListHolder.tvTotal.setText(String.valueOf(totalValue[i]));
}
@Override
public int getItemCount() {
return productList.size();
}
/**
* Custom class which implements Text Watcher
*/
private class CustomEtListener implements TextWatcher {
private int position;
TextCallBackListener textCallBackListener;
/**
* Updates the position according to onBindViewHolder
*
* @param position - position of the focused item
* @param pa - object of ProductListHolder Class
*/
public void updatePosition(int position, ProductListHolder pa) {
this.position = position;
// assigning it to the instance of the CallBackListener
textCallBackListener = (TextCallBackListener) pa;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// Change the value of array according to the position
etValArr[position] = charSequence.toString();
// Doing the calculation
if (!etValArr[position].equals("")) {
totalValue[position] = (productList.get(position).unit_price - productList.get(position).discount) * (Double.valueOf(etValArr[position]));
// triggering the callback function to update the total
textCallBackListener.updateText(String.valueOf(totalValue[position]));
} else {
totalValue[position] = 0.00;
textCallBackListener.updateText("0.00");
}
}
@Override
public void afterTextChanged(Editable editable) {
}
}
}
公共类ProductAdapter扩展了RecyclerView.Adapter{
语境;
列出产品清单;
字符串[]etValArr;
双[]总价值;
公共产品适配器(上下文c,列表lp){
this.context=c;
this.productList=lp;
//创建一个大小与编辑文本数量匹配的新数组
etValArr=新字符串[productList.size()];
//以及一个数组,用于保存每个编辑文本的所有值
totalValue=新的双精度[productList.size()];
}
公共类ProductListHolder扩展了RecyclerView.ViewHolder实现了TextCallBackListener{
文本视图tvName;
文本视图价格;
TextView电视折扣;
TextView-tvTotal;
编辑文本数量;
//自定义编辑文本侦听器的实例
公共CustomEtListener myCustomEditTextListener;
for (int i = 0; i < mFieldAdapter.getItemCount(); i++) {
// update each item itself
mFieldAdapter.notifyItemChanged(i, fields.get(i));
}
private HashMap<String, String> txtValueMap = new HashMap<String, String>();
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final PanelVO item1 = (PanelVO) mDataArrayList.get(position);
//set text on Exittext
holder.et_panel.setText( item1.getPanelName() );
//add key and value pair data on HashMap data list
//using this line when you scroll listview not interchange Edittext data
//if comment this line so input value in EditText swaps its position while scrolling in a RecyclerView
txtValueMap.put(item1.getPanelId(),holder.et_panel.getText().toString());
//add key and value pair data on txtValueMap
holder.et_panel.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) {
txtValueMap.put(item1.getPanelId(),holder.et_panel.getText().toString());
final PanelVO item1 = (PanelVO) mDataArrayList.get(position);
Iterator myVeryOwnIterator = txtValueMap.keySet().iterator();
while(myVeryOwnIterator.hasNext()) {
String key=(String)myVeryOwnIterator.next();
String value=(String) txtValueMap.get(key);
if(key.equalsIgnoreCase(item1.getPanelId())){
//update data in your listview
item1.setPanelName(holder.et_panel.getText().toString());
}
}
}
});
}