After putting an input in the EditText, if a scroll up or down very fast the input values swaps its position in another EditText in a RecyclerView.
Before scrolling the data was in the first EditText.
After scrolling up and down the value of the first EditText changed its postion to the 4th one and the swapping is random. Is there any work around to steady the data.
Here is the Model Class:
public class Product {
public int pId;
public String pName;
public double unit_price;
public double discount;
}
Here is the adapter Class:
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();
}
}
Here is the 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);
}
}
}
I think you have done a great job. But the problem you solved, can be solved in a very easy way. You just need to implement a Overridden method:
public int getItemViewType(int position) { return super.getItemViewType(position); }
In place of-
return super.getItemViewType(position);
Just Return-
return position;
I think all of your problem will be solved in a easy way. Here is your Adapter Class which I modified a little bit:
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;
}
}