2

I'm trying to implement a listView with EditText Controls. Problem is when I edit one of the fields, some other fields are also modified in the view. However, my Java objects are reflecting the changes that i make only (and not the other EditTexts that get set)

My Android Activity

public class LoanRepaymentActivity extends ListActivity implements View.OnClickListener {

private Location lastKnownLocation;
private ArrayList<CurrentRepaymentInstallment> loansForRepayment;
@Override
public void onCreate(Bundle savedInstanceState){
    lastKnownLocation = Utility.getLastKnownLocation(this);
    super.onCreate(savedInstanceState);

    Intent intent = getIntent();

    RepaymentInfo repaymentInfo = (RepaymentInfo)intent.getSerializableExtra(Constants.CURRENT_REPAYMENT_INSTALLMENT);
    loansForRepayment = repaymentInfo.getLoansForRepayment();
    boolean repaymentsNotPresent = loansForRepayment == null || loansForRepayment.isEmpty(); 
    if(repaymentsNotPresent){
        Dialog dialog = Utility.getDialogWithText(LoanRepaymentActivity.this, getText(R.string.noLoansForRepayment).toString());
        Utility.getDialogButton(dialog, LoanRepaymentActivity.this, PartnerGroupListActivity.class, intent.getStringExtra(Constants.ACECSS_TOKEN_PARAM));
        dialog.show();
    }

    ArrayAdapter<CurrentRepaymentInstallment> adapter = new LoanRepaymentListAdapter(this, loansForRepayment);

    View footer = getLayoutInflater().inflate(R.layout.loan_disbursement_footer, null);
    getListView().addFooterView(footer);

    setListAdapter(adapter);
/*       if(!repaymentsNotPresent)  {
        TextView textView = (TextView)findViewById(R.id.screenTitle);
        String currentInstallmentLabel = getText(R.string.currentInstallmentLabel).toString() + repaymentInfo.getCurrentGroupInstallment();
        textView.setText(currentInstallmentLabel);
    }*/

    Button button = (Button)findViewById(R.id.disburse);
    button.setOnClickListener(this);
}

My XML Layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>

<TextView android:id="@+id/screenTitle" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" >
</TextView>

 <ListView
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@+layout/loan_disbursement_footer"
     />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
    android:id="@+id/borrowerName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@+id/label"
    android:textSize="14sp"
     >
</TextView>

<TextView
    android:id="@+id/loanAmount"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@+id/label"
    android:textSize="14sp"
     >
</TextView>

<TextView
    android:id="@+id/installmentNumber"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@+id/label"
    android:textSize="12sp"
    >
</TextView>

<TextView
    android:id="@+id/estimatedTotal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@+id/label"
    android:textSize="12sp"
    >
</TextView>

</LinearLayout>
<EditText
    android:id="@+id/repaymentAmount"
    android:layout_width="100sp"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:inputType="numberDecimal"
    android:textSize="12sp"
     >
</EditText>
</RelativeLayout>

The Custom Array Adapter Used to set the ListView

public class LoanRepaymentListAdapter extends ArrayAdapter<CurrentRepaymentInstallment> {

private final List<CurrentRepaymentInstallment> loansForRepayment;
private final Activity context;

public LoanRepaymentListAdapter(Activity context, List<CurrentRepaymentInstallment> loansForRepayment) {
    super(context, R.layout.loan_repayments, loansForRepayment);
    this.context = context;
    this.loansForRepayment = loansForRepayment;
}

static class ViewHolder {
    protected TextView borrowerName;
    protected TextView loanAmount;
    protected TextView installmentNumber;
    protected TextView estimatedTotal;
    protected EditText repaymentAmount;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    View view = null;
    if (convertView == null) {
        LayoutInflater inflator = context.getLayoutInflater();
        view = inflator.inflate(R.layout.loan_repayments, null);
        final ViewHolder viewHolder = new ViewHolder();
        viewHolder.borrowerName = (TextView) view.findViewById(R.id.borrowerName);
        viewHolder.loanAmount = (TextView) view.findViewById(R.id.loanAmount);
        viewHolder.installmentNumber = (TextView) view.findViewById(R.id.installmentNumber);
        viewHolder.estimatedTotal = (TextView) view.findViewById(R.id.estimatedTotal);
        viewHolder.repaymentAmount = (EditText) view.findViewById(R.id.repaymentAmount);
//          viewHolder.repaymentAmount.setEditableFactory(Editable.Factory.getInstance());
        viewHolder.repaymentAmount.addTextChangedListener(new TextWatcher() {
            @Override
            public void afterTextChanged(Editable arg0) {

            }
            @Override
            public void beforeTextChanged(CharSequence s, int start,
                    int count, int after) {
                // TODO Auto-generated method stub

            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                CurrentRepaymentInstallment loanRepayment = (CurrentRepaymentInstallment) viewHolder.repaymentAmount.getTag();
                String repaymentAmount =  s.toString();
                loanRepayment.setRepaymentAmount(repaymentAmount);
            }
        });
        view.setTag(viewHolder);
        viewHolder.repaymentAmount.setTag(loansForRepayment.get(position));
    } else {
        view = convertView;
        ((ViewHolder) view.getTag()).repaymentAmount.setTag(loansForRepayment.get(position));
    }
    ViewHolder holder = (ViewHolder) view.getTag();
    holder.borrowerName.setText(loansForRepayment.get(position).getLoanProfileBasicInfo().getBorrowerBasicInfo().getFirstName());
    holder.loanAmount.setText("Rs. " + Float.toString(loansForRepayment.get(position).getLoanProfileBasicInfo().getLoanAmountInPaisa()/100));
    holder.estimatedTotal.setText("Rs. " + Float.toString(loansForRepayment.get(position).getEstimatedTotalAmount()/100));
    holder.installmentNumber.setText("Inst no : " + Integer.toString(loansForRepayment.get(position).getInstallmentNumber()));
    float repaymentAmt = loansForRepayment.get(position).getRepaymentAmount();
    if(repaymentAmt != 0.0) holder.repaymentAmount.setText(Float.toString(repaymentAmt));
    return view;
    }
}
Arvind Sridharan
  • 3,885
  • 4
  • 29
  • 54
  • Place your `addTextChangeListener`-line outside and after the if-statement. You can also give you position to the _TextWatcher_ like `new TextWatcher(position)` and use that position. – DroidBender Jun 27 '12 at 11:06
  • @MartijnVanMierloo should i place it inside the else block or outside the else block too? – Arvind Sridharan Jun 27 '12 at 12:01
  • Outside of the if- and else-block :) – DroidBender Jun 27 '12 at 12:17
  • @MartijnVanMierloo - i left the code in the same place .. I got the tag of the holder and set the object value. So now the java objects are setting properly. Only thing left is the multiple EditTexts showing – Arvind Sridharan Jun 27 '12 at 12:29

2 Answers2

3

The reason being Android ListView recycling.. Please have a look at the accepted answer in the below link EditText in ListView without it recycling input

Hope this helps.

Community
  • 1
  • 1
Sam
  • 555
  • 4
  • 13
0

The solution to this is removing the added textwatcher before setting the text. Otherwise, the previous textwatcher on that view will still be called along with the new textwatcher. Store the textwatcher as a tag on the EditText to keep track of it.

Object oldWatcher = viewHolder.quantitySold.getTag();
if(oldWatcher != null){
    viewHolder.quantitySold.removeTextChangedListener((CustomTextWatcher)oldWatcher);
} 
String oldText =  inputValues.get("key"+position);
Log.d(TAG, "oldText: "+oldText+" position: "+position);
viewHolder.quantitySold.setText(oldText == null ? "" : oldText);
CustomTextWatcher watcher = new CustomTextWatcher(
        cursor.getString(SKUFragment.COL_NAME),
        cursor.getInt(SKUFragment.COL_ID),
        cursor.getDouble(SKUFragment.COL_UNIT_PRICE),
        position
) {
    @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) {
        if (s != null) {
            int quantity = 0;
            if (!TextUtils.isEmpty(s.toString())) {
                quantity = Integer.parseInt(s.toString());
                inputValues.put("key"+mPosition, "" + quantity);
            }else{
                inputValues.put("key"+mPosition, "");
            }
            double value = quantity * skuPrice;
            mListener.onQuantityChanged(skuName+", position: "+mPosition, skuId, quantity, value);
        }
    }
};
viewHolder.quantitySold.setTag(watcher);
viewHolder.quantitySold.addTextChangedListener(watcher);
SimuMax
  • 11
  • 1