問題描述
在 EditText 中輸入輸入后,如果快速向上或向下滾動,則輸入值會在 RecyclerView 的另一個 EditText 中交換其位置.
滾動數(shù)據(jù)之前是在第一個 EditText 中.
上下滾動后,第一個 EditText 的值將其位置更改為第四個,并且交換是隨機(jī)的.有什么辦法可以穩(wěn)定數(shù)據(jù).
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.
這是一個示例截圖
這是模型類:
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:
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);
}
}
}
推薦答案
我已經(jīng)解決了問題.
問題是我在 onBindViewHolder 中添加了 addTextChangedListener.所以 EditText 中的值總是很混亂,因?yàn)楫?dāng)焦點(diǎn)轉(zhuǎn)移時,另一個 addTextChangedListener 被注冊了.所以我所做的是,我實(shí)現(xiàn)了另一個名為 CustomEtListener 的自定義類并實(shí)現(xiàn)了 TextWatcher.所以現(xiàn)在我在 onCreateViewHolder 中為每個 EditText 注冊了自定義監(jiān)聽器.并采用 array 字符串來存儲編輯文本的值.數(shù)組的大小是 RecyclerView 中的項(xiàng)目數(shù).updatePosition 方法用于獲取焦點(diǎn)項(xiàng)目的位置.然后 onTextChanged 我只是將 editText 的值存儲在數(shù)組中,并在 onBindViewHolder 中更新了該 EditText 的值.之后每次滾動時,EditText 的值都不會改變.
I've sorted out the problem.
The problem was that i added the addTextChangedListener in onBindViewHolder. So the values in the EditText always got jumbled, cause when the focus shifted another addTextChangedListener was registered. So what i did is that, i implemented another Custom Class called CustomEtListener and implemented the TextWatcher. So now i registered the custom listener in onCreateViewHolder for each EditText. And took an array of string to store the values of the edit text. And the size of the array was the number of items in the RecyclerView. And the method updatePosition was there to get the position of the focused item. Then onTextChanged i just stored the value of the editText in the array, and updated the value of that EditText in onBindViewHolder. After that every time i scroll, the value of the EditText won't change.
這是我的適配器類.
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 列的值.在我上下滾動之后,值就改變了.所以我必須實(shí)現(xiàn)一個回調(diào)偵聽器來立即獲取 Total 列的值.我現(xiàn)在有一個接口 TextCallBackListener,并在 Adapters ProductListHoldersClass 上實(shí)現(xiàn)了它.因此,每當(dāng)調(diào)用 onTextChanged 時,它都會觸發(fā)我的 updateText 方法來更改該行 Total 的值.看不懂的,問題里有截圖.
Still i had a problem. I wasn't able to update the Total column's values. After i scroll up and down, then the value changed. So i had to implement a call backListener to get the value of the Total column right away. I have now an interface TextCallBackListener, and implemented it on the Adapters ProductListHoldersClass. So whenever the onTextChanged was called it triggered my updateText method to change the value of that rows Total. if you don't understand the view, there is a screenshot in the question.
這里是TextCallBackListener接口.
Here is the interface TextCallBackListener.
public interface TextCallBackListener {
public void updateText(String val);
}
這是我更改后的適配器類.
Here is my changed adapter class.
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) {
}
}
}
這篇關(guān)于為什么 EditText 中的輸入值在 RecyclerView 中滾動時會交換位置?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!