在EditText中输入输入后,如果向上或向下滚动非常快,输入值会在RecyclerView中的另一个EditText中交换其位置。
在滚动之前,数据位于第一个EditText中
在向上和向下滚动之后,第一个EditText的值将其位置更改为第4个,并且交换是随机的。是否有任何工作来稳定数据。
这是模型类:
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();
}
}
以下是MainActivity:
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);
}
}
}
答案 0 :(得分:13)
我认为你做得很好。但是你解决的问题可以通过一种非常简单的方式解决。您只需要实现重写方法:
public int getItemViewType(int position){ return super.getItemViewType(position); }
取代 -
返回super.getItemViewType(position);
回归 -
返回位置;
我认为您的所有问题都将以简单的方式解决。这是我修改过的适配器类:
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, final int i) {
View v = LayoutInflater.from(context).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) {
productListHolder.tvTotal.setText(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@Override
public int getItemCount() {
return productList.size();
}
@Override
public int getItemViewType(int position) {
return position;
}
}
答案 1 :(得分:5)
你正在调用etQuantity.addTextChangedListener
,但你永远不会删除监听器,所以当视图持有者被回收(也就是用于显示另一个项目)时,它会添加另一个文本更改的监听器(所以它将有两个不同的文本更改的侦听器注册。)
最简单的解决方法可能只需在addTextChangedListener
中拨打onCreateViewHolder
一次,然后使用getAdapterPosition
代替i
来获取该位置。
答案 2 :(得分:5)
问题是我在 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) {
}
}
}
我还有问题。我无法更新Total列的值。我向上和向下滚动后,值改变了。所以我必须实现一个调用backListener来立即获取Total列的值。我现在有一个接口 TextCallBackListener ,并在Adapters ProductListHoldersClass上实现它。因此,每当调用 onTextChanged 时,它都会触发我的 updateText 方法来更改行Total的值。如果您不理解该视图,则问题中会有截图。
这是接口TextCallBackListener。
public interface TextCallBackListener {
public void updateText(String val);
}
这是我更改的适配器类。
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) {
}
}
}
答案 3 :(得分:0)
简单修复:
将 mFieldAdapter.notifyDataSetChanged();
替换为:
for (int i = 0; i < mFieldAdapter.getItemCount(); i++) {
// update each item itself
mFieldAdapter.notifyItemChanged(i, fields.get(i));
}