android - 为什么在 RecyclerView 中滚动时 EditText 中的输入值会交换其位置?

标签 android android-edittext android-recyclerview android-viewholder

在 EditText 中输入内容后,如果快速向上或向下滚动,输入值将交换其在 RecyclerView 中另一个 EditText 中的位置。
在滚动之前,数据位于第一个 EditText 中。
上下滚动后,第一个 EditText 的值将其位置更改为第四个,并且交换是随机的。是否有任何解决方法来稳定数据。

Here is a sample screenshot

这是模型类:

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);
    }
  }    
}

最佳答案

我认为你做得很好。但是您解决的问题可以很容易地解决。你只需要实现一个 Overridden 方法:

public int getItemViewType(int position) { return super.getItemViewType(position); }

代替-

return super.getItemViewType(position);

只是返回-

return 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;
}    
}

关于android - 为什么在 RecyclerView 中滚动时 EditText 中的输入值会交换其位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32493958/

相关文章:

android - 错误: Could not find method viewBinding() for arguments

android - 编辑扩展列表中的文本

java - 安卓/Java : Set textview with char from index of string

android - 无法在 ViewPager 中膨胀 recyclerView

android - 具有滚动背景的 Recyclerview

android - Android 应用程序中的字符串保护

android - 无法在 Eclipse IDE 上获取项目的系统库

android - Android 自定义 View 上的文本输入

android - Kindle 的 Android 应用程序如何处理字典查找的点击

android - 在 Recyclerview 适配器上设置 notifyDataSetChanged()