Android - EditTexts в ListView привязан к Custom ArrayAdapter - отслеживание изменений - PullRequest
8 голосов
/ 12 октября 2011

У меня есть активность Android, в которой у меня есть ListView, связанный с пользовательским адаптером ArrayAdapter.Каждая строка ListView имеет два поля EditText (числовые).

ArrayAdapter изначально заполняется из БД SQLite.Однако пользователь может добавить строку в конец ListView или (долгим нажатием на строку) удалить любую строку в ListView.Когда они нажимают кнопку «Сохранить», их изменения сохраняются.

Я отслеживаю изменения по мере их внесения, прикрепляя CustomTextWatcher для события AfterTextChanged () к каждому EditText в методе getView () ArrayAdapter.(передавая EditText и соответствующий объект в список элементов ArrayAdapter), а затем устанавливая свойство сопоставления этого объекта на содержимое EditText.Это сделано для того, чтобы при сохранении я мог просто перебирать базовый список объектов и вносить соответствующие изменения в БД, зная, что список объектов обновлен.

Код для класса адаптера и CustomTextWatcher:

private class CustomAdapter extends ArrayAdapter<DataItem> {
    private ArrayList<DataItem> items;

    public CustomAdapter(Context context, int textViewResourceId, ArrayList<DataItem> items) {
        super(context, textViewResourceId, items);
        this.items = items;
}

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;

            DataItem wed = items.get(position);

            if (v == null) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.log_exercise_row, null);
            }

            if(wed != null)
            {
                     EditText text1 = (EditText) v.findViewById(R.id.text1);
                     EditText text2 = (EditText) v.findViewById(R.id.text2);

                text1.addTextChangedListener(new CustomTextWatcher(text1,wed));
                text2.addTextChangedListener(new CustomTextWatcher(text2,wed));


                int weight = wed.getWeight();

                if(weight != -1)
                {
                   text1.setText(weight+"");
                }


                int reps = wed.getReps();

                if(reps != -1)
                {
                    text2.setText(reps+"");
                }


            }

            return v;
    }

private class CustomTextWatcher implements TextWatcher {

    private EditText EditText; 
    private DataItem item;

    public CustomTextWatcher(EditText e, DataItem item)
    {
        this.EditText = e;
        this.item = item;
    }

    @Override
    public void afterTextChanged(Editable arg0) {

        String text = arg0.toString();

        if(text != null && text.length() > 0)
        {
            int val;

            try
            {
                val =Integer.parseInt(text);
            }

            catch(NumberFormatException e)
            {
                val=-1;
            }

            if(EditText.getId()==R.id.weightEditText)
            {
                item.setWeight(val);
            }

            else if(EditText.getId()==R.id.repsEditText)
            {
                item.setRepetitions(val);
            }
        }
    }

Все это прекрасно работает, за исключением случаев, когда элементы добавляются или удаляются, когда происходит нежелательное дублирование содержимого EditText.

Для иллюстрации на примере:

Начните с 3 строк, весь текст EditText пуст
В строке 2 введите «5», «6»
Нажмите «Еще» ->Добавляет (пустую) строку в конец.Теперь 4 строки.
Удалите последнюю отображаемую строку-> 3 строки, НО 2-я и 3-я строки теперь отображают '5', '6' -> ???????

Это выглядит как относительныйположение объектов EditText в ListView не стабильно после повторного связывания, что вызывает проблему.Например, объект EditText 'X' начинается в позиции 3, затем после повторного связывания он находится в позиции 1, но к нему все еще прикреплен CustomTextWatcher, ссылающийся на объект данных в позиции 3. Другая проблема заключается в том, что addTextChangedListener () невлияют на TextWatchers, уже прикрепленные к EditText.

Я довольно новичок в Android, поэтому я не уверен, что есть лучший подход для решения моей проблемы.Любая помощь приветствуется.

1 Ответ

10 голосов
/ 13 октября 2011

Похоже, что пользовательский класс ('ViewHolder') был тем, что мне было нужно для правильной синхронизации ссылок между EditText и связанным с ним объектом данных при каждом «связывании» данных. Кроме того, размещение вызовов прослушивателя событий, когда объект convertView был нулевым в методе getView (), означало, что для каждого объекта EditText был добавлен только один прослушиватель.

Спасибо http://www.vogella.de/articles/AndroidListView/article.html#listsactivity за указание в правильном направлении.

public class CustomAdapter extends ArrayAdapter<DataItem> {
private ArrayList<DataItem> items;
private Activity Context;

public CustomAdapter(Activity context, int textViewResourceId, ArrayList<DataItem> items) {
    super(context, textViewResourceId, items);
    this.items = items;
    this.Context = context; 
}

static class ViewHolder {
    protected EditText weight;
    protected EditText reps;

}

 public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;

        DataItem wed = items.get(position);


        if (v == null) {
            LayoutInflater inflator = Context.getLayoutInflater();
            v = inflator.inflate(R.layout.log_exercise_row, null);
            final ViewHolder viewHolder = new ViewHolder();
            viewHolder.text1 = (EditText) v.findViewById(R.id.text1);
            viewHolder.text2 = (EditText) v.findViewById(R.id.text2);


            viewHolder.text1.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text1));
            viewHolder.text2.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text2));

            v.setTag(viewHolder);
            viewHolder.text1.setTag(wed);
            viewHolder.text2.setTag(wed);

        }

        else
        {
            ViewHolder holder = (ViewHolder) v.getTag();
            holder.text1.setTag(wed);
            holder.text2.setTag(wed);   
        }

        ViewHolder holder = (ViewHolder) v.getTag();

        // set values

        if(wed.getWeight() != -1)
        {
            holder.text1.setText(wed.getWeight()+"");
        }

        else
        {
            holder.weight.setText("");
        }

        if(wed.getRepetitions() != -1)
        {
            holder.text2.setText(wed.getRepetitions()+"");
        }

        else
        {
            holder.reps.setText("");
        }

        return v;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...