Android Обработка многих полей EditText в ListView - PullRequest
6 голосов
/ 14 ноября 2011

Просто простой вопрос: если у меня есть несколько десятков полей EditText, которые являются частью ListAdapter, как отдельные поля EditText могут знать, к какой строке они принадлежат?

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

Однако, когда появляется программная клавиатура, позиции, соответствующие различным полям EditText, перемешиваются.

Как я могу отследить поля EditText в их правильном положении?

Я использую GridView, чтобы выложить вещи.Макет каждого элемента представляет собой ImageView с полями TextView и EditText под ним.

Текст для каждого EditText содержится в глобальном массиве String, называемом строками.Первоначально он пуст и обновляется моим классом TextWatcher.

public void initList()
    {
        ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, R.layout.shape, strings)
        {
            @Override
            public View getView(final int position, View convertView, ViewGroup parent)  {
                if (convertView == null)  {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.shape, null);
                }
                final String theData = getItem(position);
                final EditText editText = (EditText) convertView.findViewById(R.id.shape_edittext);
                editText.setText(theData);
                editText.addTextChangedListener(
                        new MyTextWatcher(position, editText)
                );

                ImageView image = (ImageView) convertView.findViewById(R.id.shape_image);
                image.setBackgroundResource(images[position]);

                TextView text = (TextView) convertView.findViewById(R.id.shape_text);
                if (gameType == SHAPES_ABSTRACT)
                    text.setText("Seq:");
                else
                    text.setVisibility(View.GONE);  

                return convertView;
            }

            @Override
            public String getItem(int position) {        return strings[position];       }
        };

        grid.setAdapter(listAdapter);
    }


private class MyTextWatcher implements TextWatcher {
    private int index;
    private EditText edittext;
    public MyTextWatcher(int index, EditText edittext) { 
               this.index = index; 
               this.edittext = edittext;    
        }
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    public void onTextChanged(CharSequence s, int start, int before, int count) {}
    public void afterTextChanged(Editable s) {  strings[index] = s.toString();      }
    public void setIndex(int newindex) {  index = newindex;    }
}

Когда я нажимаю на первый EditText (см. Рисунок), EditText смещается к тому, что под смайликом.

Shows how the EditText fields are layed out

Ответы [ 5 ]

5 голосов
/ 14 ноября 2011

Не принимая во внимание, хороший ли это дизайн пользовательского интерфейса, вот как вы это сделаете:

public class TestList
{
    public void blah()
    {
        ArrayAdapter<DataBucket> listAdapter = new ArrayAdapter<DataBucket>()
        {

            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null);
                }

                final DataBucket dataBucket = getItem(position);
                final EditText editText = (EditText) convertView.findViewById(R.id.theText);
                editText.setText(dataBucket.getSomeData());
                editText.addTextChangedListener(new TextWatcher()
                {
                    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
                    {

                    }

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

                    }

                    public void afterTextChanged(Editable editable)
                    {
                        dataBucket.setSomeData(editable.toString());
                    }
                });

                return convertView;
            }
        };
    }

    public static class DataBucket
    {
        private String someData;

        public String getSomeData()
        {
            return someData;
        }

        public void setSomeData(String someData)
        {
            this.someData = someData;
        }
    }
}

'DataBucket' является заполнителем. Вы должны использовать любой класс, который вы создали, для хранения данных, которые вводятся и редактируются в тексте редактирования. TextWatcher будет иметь ссылку на объект данных, на который ссылаются. При прокрутке текстовые поля для редактирования должны обновляться с текущими данными, а изменения текста должны сохраняться. Вы можете хотеть отследить, какие объекты были изменены пользователем, чтобы сделать обновления данных / сети более эффективными.

* Редактировать *

Чтобы использовать позицию int вместо прямой ссылки на объект:

ArrayAdapter<DataBucket> listAdapter = new ArrayAdapter<DataBucket>()
{

    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    {
        if (convertView == null)
        {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null);
        }

        final DataBucket dataBucket = getItem(position);
        final EditText editText = (EditText) convertView.findViewById(R.id.theText);
        editText.setText(dataBucket.getSomeData());
        editText.addTextChangedListener(new TextWatcher()
        {
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
            {

            }

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

            }

            public void afterTextChanged(Editable editable)
            {
                getItem(position).setSomeData(editable.toString());
            }
        });

        return convertView;
    }
};

* Изменить еще раз *

Я чувствую себя обязанным сказать для потомков, я бы на самом деле не кодировал это так. Я предполагаю, что вам нужны немного более структурированные данные, чем массив String, и вы поддерживаете массив String снаружи, а также ArrayAdapter, так что это своего рода странная параллельная ситуация. Тем не менее, это будет работать нормально.

У меня есть данные в одном массиве String, а не в многомерном массиве. Причина в том, что модель данных, поддерживающая GridView, представляет собой простой список. Это может быть нелогичным, но так оно и есть. GridView должен выполнять разметку самостоятельно, и если его оставить для своих собственных устройств, он заполнит строку переменным числом ячеек, в зависимости от того, сколько у вас данных и насколько широкий экран (AFAIK).

Достаточно чата. Код:

public class TestList extends Activity
{
    private String[] guess;

    //Other methods in here, onCreate, etc

    //Call me from somewhere else. Probably onCreate.
    public void initList()
    {
        ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, /*some resourse id*/, guess)
        {

            @Override
            public View getView(final int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.testlayout, null);
                }

                final String theData = getItem(position);
                final EditText editText = (EditText) convertView.findViewById(R.id.theText);
                editText.setText(theData);
                editText.addTextChangedListener(
                        new MyTextWatcher(position)
                );

                return convertView;
            }
        };

        gridView.setAdapter(listAdapter);
    }

    class MyTextWatcher extends TextWatcher {
         private int position;

         public MyTextWatcher(int position) {
                 this.position = position;
         }

         public void afterTextChanged(Editable s) {
                 guess[position] = s.toString();
         }

     // other methods are created, but empty
    }
}
3 голосов
/ 14 ноября 2011

Для отслеживания номера строки каждый слушатель в EditText должен сохранить ссылку на элемент в списке и использовать getPosition(item), чтобы получить позицию в ListView. В моем примере используется Button, но я думаю, что его можно применить к EditText.

class DoubleAdapter extends ArrayAdapter<Double> {
    public DoubleAdapter(Context context, List<Double> list) {
        super(context, android.R.layout.simple_list_item_1, list);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_row, null);
        }

        // keep a reference to an item in a list
        final Double d = getItem(position);

        TextView lblId = (TextView) convertView.findViewById(R.id.lblId);
        lblId.setText(d.toString());

        Button button1 = (Button) convertView.findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // the button listener has a reference to an item in the list
                // so it can know its position in the ListView
                int i = getPosition(d);
                Toast.makeText(getContext(), "" + i, Toast.LENGTH_LONG).show();
                remove(d);
            }
        });

        return convertView;
    }
}
1 голос
/ 14 ноября 2011

Я не уверен, что у вас хороший дизайн, так как контент EditText будет иметь хорошие шансы на проблемы (перетасовывание контента, пропущенный текст) после прокрутки списка.подумайте над тем, чтобы опробовать идею m6tt.

, но если вы действительно хотите идти своим путем, можете ли вы опубликовать какой-то код, в частности, вашего TextWatcher?

1 голос
/ 14 ноября 2011

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

Хотя я не знаю, как устроено ваше приложение, я бы порекомендовал немного переосмыслить ваш пользовательский интерфейс, чтобы при нажатии на элемент списка отображалось редактирование одного текста. Таким образом, вы можете просто получить ссылку на элементы списка, как вы это обычно делаете с помощью адаптера списка, сохранять его, пока пользователь редактирует, и обновлять его по завершении.

0 голосов
/ 26 апреля 2017

Я пытался решить эту проблему, и, как вы можете видеть, есть простой метод - я выкладываю ответ здесь, поскольку он может быть полезен для кого-то.

Невозможно получить позицию при просмотре списка ->Редактировать текст имеет наблюдателя текста.

Это решение, которое сработало для меня:

В режиме просмотра -

, когда я добавляю слушателя наблюдателя текста для редактирования текста, ятакже добавили нижнюю строку

edittext.setTag(R.id.position<any unique string identitiy>, position)

в вашем afterTextChanged -

 int position = edittext.getTag(R.id.position) 

Дает правильный номер позиции, и вы можете вносить изменения в зависимости от номера позиции.

...