Android, как сделать EditText редактируемым внутри ListView - PullRequest
6 голосов
/ 26 января 2012

У меня есть ListView с редактируемым текстом в каждом элементе, и я хочу знать, как я могу сделать EditText редактируемым. Кажется, это работает нормально, если я установил android:windowSoftInputMode="adjustPan" в манифест, но только на некоторых устройства. На некоторых устройствах программная клавиатура закрывает текст редактирования.

С другой стороны, если я не введу android:windowSoftInputMode="adjustPan" в манифест, EditText теряет фокус после отображения экранной клавиатуры, и мне приходится несколько раз касаться EditText, чтобы выбрать его и напиши в нем.

Пожалуйста, помогите мне решить эту проблему.

Примечание: Я видел этот пост: Фокусируемый EditText внутри ListView и оттуда ничего не помогло, и у меня совершенно другая проблема, кроме этой

Ответы [ 2 ]

4 голосов
/ 31 января 2012

После неудачной попытки создать интерфейс с EditTexts внутри ListView все, что я могу вам сказать, это «Не надо!». У вас будет гораздо больше проблем, когда у вас будет достаточно предметов для прокрутки вашего ListView, фокус будет переключаться тут и там, вам придется сохранять состояние EditText и так далее. Похоже, что общая идея заключается в том, что использование EditText в ListView не стоит.

После долгих исследований я могу предложить следующий метод, который мне помог: Я унаследовал ListView и переопределил метод layoutChildren, внутри него я делаю следующее:

@Override
protected void layoutChildren() {
    super.layoutChildren();
    final EditText tv = (EditText)this.getTag();
    if (tv != null)
    {
        Log.d("RUN", "posting delayed");
        this.post(new Runnable() {

            @Override
            public void run() {
                Log.d("RUN", "requesting focus in runnable");
                tv.requestFocusFromTouch();
                tv.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN , tv.getWidth(), tv.getHeight(), 0));
                tv.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP , tv.getWidth(), tv.getHeight(), 0));
            }
        });
    }
}

Когда я знаю, какой EditText должен получить фокус (я знаю это при вызове getView моих адаптеров), я устанавливаю этот конкретный EditText в качестве тега на ListView. Затем ListView выкладывается сам, и моя ветка сообщений ставится в очередь. Он запускается и запрашивает фокусировку, однако, поскольку в моем случае этого было недостаточно, я также генерирую два MotionEvents, которые просто имитируют касание. Очевидно, этого достаточно, чтобы появилась программная клавиатура. Причины этого объясняются в ответе здесь: Вкладки панели действий Android и фокус клавиатуры

0 голосов
/ 20 февраля 2012

Я сделал обходной путь для этого, хотя .. может быть, поможет кому-то

public class EditTextListAdapter extends BaseAdapter {

    /* notes list */
    private ArrayList<SomeData> mSomeData = null;
    /* layout inflater instance */
    private LayoutInflater mInflater;
    /* activity context */
    private Context mContext;

    /* ensure that this constant is greater than the maximum list size */
    private static final int DEFAULT_ID_VALUE = -1;
    /* used to keep the note edit text row id within the list */
    private int mNoteId = DEFAULT_ID_VALUE;

    /**
     * EditTextListAdapter adapter class constructor
     *
     * @param context               activity context
     */
    public FirstTimesListAdapter(Context context) {

        /* get a layout inflater instance */
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        /* load the data */
        mSomeData = SomeData.instance().getData(); 
        /* keep the context */
        mContext = context;
    }

    /**
     * Returns the selected item
     *
     * @return selected item
     */
    public int getSelectedItem() {
        return mSelectedItem;
    }

    public int getCount() {
        return mSomeData.size();
    }

    public Object getItem(int i) {
        return mSomeData.get(i);
    }

    public long getItemId(int i) {
        return i;
    }

    public View getView(final int index, View recycledView, ViewGroup viewGroup) {

        ViewHolder viewHolder;

        if (recycledView == null) {
            /* inflate the list item */
            recycledView = mInflater.inflate(R.layout.listview_item_with_edit_text, viewGroup, false);
            /* get link to the view holder views */
            viewHolder = new ViewHolder();
            viewHolder.note = (EditText) recycledView.findViewById(R.id.first_times_note);
            recycledView.setTag(viewHolder);
        } else {
            /* reuse the same views we load the first time */
            viewHolder = (ViewHolder) recycledView.getTag();
        }

        /* display some notes */
        viewHolder.note.setText(mSomeData.getNotes());

        /* if the last id is set, the edit text from this list item was pressed */
        if (mNoteId == index) { 

            /* make the edit text recive focus */
            viewHolder.note.requestFocusFromTouch();
            /* make the edit text's cursor to appear at the end of the text */
            viewHolder.note.setSelection(viewHolder.note.getText().length());

            /* reset the last id to default value */
            mNoteId = DEFAULT_ID_VALUE;
        }

        /* set a touch listener on the edit text just to record the index of the edit text that was pressed */
        viewHolder.note.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                    /* get the index of the touched list item */
                    mNoteId = index;
                }
                return false;
            }
        });

        return recycledView;
    }

    static class ViewHolder {        
        /* note input */
        EditText note;
    }

}
...