2015-01-02 2 views
2

세 개의 편집 텍스트가있는 목록 항목이 하나있는 사용자 지정 목록 어댑터가 있습니다. 그리고 나는 그들 중 한 명에게 데이트 피커를 가지고있다. 날짜가 설정되면 어댑터의 일치 모델에 날짜가 올바르게 저장됩니다. 그러나 다른 편집 텍스트의 경우 입력 한 텍스트를 목록에 저장하기 만하면됩니다. 텍스트 워처를 사용하여 작업을 수행합니다. 내 문제는보기의 단일 항목에 대해 텍스트 관찰자가 여러 번 (정확히 5 번) 발생한다는 것입니다.edittext 및 textwatcher를 사용한 목록보기. Textwatcher가 여러 번 실행됩니다 (3 회 이상)

편집 텍스트 중 하나가 올바르게 작동하면 왜 다른 텍스트가 표시되지 않습니까? 나는 약간의 도움을 정말로 사용할 수있다. 지금까지 어떤 성공도 찾을 수 없었습니다.

public class AddExpensesAdapter extends BaseAdapter{ 
private Activity activity; 
private ArrayList<AddExpensesModel> addExpensesList; 
private LayoutInflater inflater; 
private TextView totalAmount; 
private ArrayList<String> array_amount= new ArrayList<String>(); 
private ArrayList<String> array_name= new ArrayList<String>(); 
public AddExpensesAdapter(Activity activity, ArrayList<AddExpensesModel> addExpensesList)  { 
    this.activity = activity; 
    this.addExpensesList = addExpensesList; 
    this.inflater = (LayoutInflater) this.activity 
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

@Override 
public int getCount() { 
    return addExpensesList.size(); 
} 

@Override 
public Object getItem(int position) { 
    return null; 
} 

@Override 
public long getItemId(int position) { 
    return 0; 
} 

public AddExpensesModel getExpenseModel(int position) 
{ 
    return addExpensesList.get(position); 
} 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    final ViewHolder viewHolder; 
    if (convertView == null) { 
     viewHolder = new ViewHolder(); 
     convertView = inflater.inflate(R.layout.a_add_expenses_listitem, null); 


     viewHolder.expenseName = (EditText) convertView.findViewById(R.id.add_expenses_et_expense_name); 
     viewHolder.dateTime = (EditText) convertView.findViewById(R.id.add_expenses_et_date_time); 
     viewHolder.amount = (EditText) convertView.findViewById(R.id.add_expenses_et_amount); 
     viewHolder.editDate = (ImageView) convertView.findViewById(R.id.add_expenses_edit_date); 
     viewHolder.number = (TextView) convertView.findViewById(R.id.add_expenses_tv_serial_number); 
     viewHolder.deleteExpense = (ImageView) convertView.findViewById(R.id.add_expenses_delete_expense); 
     // viewHolder.totalfriends = (TextView) 
     // convertView.findViewById(R.id.eventtotalfriends); 

     convertView.setTag(viewHolder); 
     viewHolder.ref = position; 
    } else { 
     viewHolder = (ViewHolder) convertView.getTag(); 

    } 


    final AddExpensesModel addExpenseModel = addExpensesList.get(position); 

    viewHolder.expenseName.setText(addExpenseModel.getExpenseName()); 
    viewHolder.dateTime.setText(addExpenseModel.getDateTime()); 
    viewHolder.amount.setText(addExpenseModel.getAmount()); 
    viewHolder.number.setText(""+(position+1)+"."); 




    viewHolder.editDate.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      try { 
       setDate(addExpenseModel); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 

    viewHolder.deleteExpense.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      addExpensesList.remove(position); 
      notifyDataSetChanged(); 
     } 
    }); 


     viewHolder.amount.addTextChangedListener(new TextWatcher() { 

      @Override 
      public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { 

      } 

      @Override 
      public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { 

      } 

      @Override 
      public void afterTextChanged(Editable editable) { 

       if(!editable.toString().equals("")) 
       { 


           addExpenseModel.setAmount(editable.toString()); 

         } 


        notifyDataSetChanged(); 

      } 
     }); 

    return convertView; 
} 



public void setDate(final AddExpensesModel model) throws Exception { 

    final String dateFormatPattern = "MMM, dd yyyy"; 
    final SimpleDateFormat sdf = new SimpleDateFormat(dateFormatPattern, 
      Locale.getDefault()); 

    DatePickerDialog.OnDateSetListener date = new DatePickerDialog.OnDateSetListener() { 
     @Override 
     public void onDateSet(DatePicker view, int year, int monthOfYear, 
           int dayOfMonth) { 
      Calendar cal = Calendar.getInstance(); 
      cal.set(Calendar.YEAR, year); 
      cal.set(Calendar.MONTH, monthOfYear); 
      cal.set(Calendar.DAY_OF_MONTH, dayOfMonth); 
      model.setDateTime(sdf.format(cal.getTime())); 
      notifyDataSetChanged(); 
     } 
    }; 

    Calendar cal = Calendar.getInstance(); 
    cal.setTime(sdf.parse(model.getDateTime())); 
    new DatePickerDialog(this.activity, date, cal.get(Calendar.YEAR), 
      cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)).show(); 
} 

static class ViewHolder { 
    EditText expenseName; 
    EditText dateTime; 
    EditText amount; 
    ImageView editDate; 
    ImageView deleteExpense; 
    TextView number; 

} 

}

+3

ListView가 뷰를 재활용하기 때문에 convertview가 null이 아닐 때마다 이미 EditText에 TextWatcher가 첨부되어 있습니다. –

+1

viewHolder.amount.setText 전에 TextWatcher를 제거하려고 시도하면이 콜백도 트리거됩니다. TextWatcher의 단일 인스턴스를 사용하기 위해 일부 논리를 사용하십시오. – Krish

+0

@TomislavNovoselec 감사합니다. –

답변

4

나는 늦었다 고 알고있다. 그러나 나는 미래의 독자들을 위해 이것을 남겨 둘 것이다. Textwatchers는 재활용 성질로 인해 목록보기 항목으로 설정하는 것이 좋으며 Textwatchers는 편집 텍스트에 추가되고 대체되지 않기 때문에 약간 까다 롭습니다. 따라서 행 뷰가 생성되거나 새로운 데이터에 바인딩 될 때마다 잘못된 뷰어를 제거하고 새로운 관찰자를 추가해야합니다. 다음 구현을 시도하십시오.

1) 사용자 지정 텍스트 감시자.

private class CustomWatcher implements TextWatcher 
{ 
    private Object item; 

    private CustomWatcher(Object item) 
    { 
     this.item = item; 
    } 

    @Override 
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) 
    { 

    } 

    @Override 
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) 
    { 

    } 

    @Override 
    public void afterTextChanged(Editable editable) 
    { 

    } 
} 

2) 글고 치기에 textwatcher를 추가하고의 getView 내부() 함수 이전을 제거 (개체 항목은 행의 데이터가 들어있는 개체입니다).

CustomWatcher oldWatcher = (CustomWatcher)holder.editDate.getTag(); 
    if(oldWatcher != null) 
     holder.editDate.removeTextChangedListener(oldWatcher); 

//populate your editText with the model data here (before adding the new text watcher) 

CustomWatcher newWatcher = new CustomWatcher(rowItem); 
    holder.editDate.setTag(newWatcher); 
    holder.editDate.addTextChangedListener(newWatcher); 

완료. 이제 해당 행 데이터 객체에 텍스트를 저장할 수 있습니다. 이렇게하면 Textwatchers는 유용성을 초과하고 메모리 누수를 막을 때 제거됩니다.

1

그것 때문에 당신의 텍스트 편집에 텍스트 감시자의의는, 사용자가 입력 할 때마다이 문자 텍스트 감시자가 호출 될 때마다 여러분의 notifyDataSetChanged()이 취소됩니다.

예를 들어, 금액 453을 저장한다고 가정하면 3 번 해고됩니다.

+0

답변 해 주셔서 감사합니다. –

0

내 문제 중 하나를 해결하려고했는데 목록보기에서 텍스트를 볼 때 위치를 확인할 수 없습니다. - 내가 텍스트를 편집 할 텍스트 감시자 리스너 추가 오전 때

, 나는 또한 아래 라인

edittext.setTag을 추가 (

GET보기에서 :

나를 위해 일한 솔루션입니다 R.id.position, 위치) 당신의 afterTextChanged에

- INT 위치 = edittext.getTag (R.id.position)

올바른 위치 번호를 지정하고 위치 번호를 기반으로 수정할 수 있습니다.