Android Handling Many EditText Fields in ListView

Just the main question: if I have dozens of EditText fields that are part of the ListAdapter, how can individual EditText fields know which row they belong to?

I am currently using TextWatcher to listen for text input. I tried expanding TextWatcher so that I could go to the position of the EditText constructor in TextWatcher.

However, when a soft keyboard appears, the positions that correspond to the various EditText fields are shuffled.

How can I track EditText fields in the correct position?

I use GridView to pave things. The layout of each element is an ImageView with a TextView field and an EditText under it.

The text for each EditText is stored in a global array of String called strings. It is initially empty and updated by my TextWatcher class.

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; } } 

When I click on the first EditText (see the picture), the EditText goes to that under the emoticon.

Shows how the EditText fields are layed out

+6
source share
5 answers

Not considering that this is a good user interface design, here's how you do it:

 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' is a placeholder. You need to use any class that you created to store the data that is placed and edited in the editing text. TextWatcher will reference the data object that is being referenced. When scrolling, edit text fields should be updated with current data, and text changes should be saved. You can track which objects have been modified by the user to increase the efficiency of data / network updates.

* Change *

To use an int position instead of a direct reference to an object:

 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; } }; 

* Change again *

I feel compelled to say for posterity that in fact I would not call it that. I suppose you want more structured data than a String array, and you support the String array outside, just like an ArrayAdapter, so this is kind of a weird parallel situation. However, this will work fine.

I have my data in one String array, and not in a multidimensional array. The reason is that the data model that supports the GridView is a simple list. It may not be logical, but it is. GridView should do the layout itself, and if it is left on its own devices, it will fill the string with variable numbers of cells, depending on how much data you have and how wide your screen is displayed (AFAIK).

Enough chat. The code:

 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 } } 
+5
source

To keep track of the line number, each listener in EditText must contain a link to an item in the list and use getPosition(item) to get the position in the ListView . My example uses Button , but I think it can be applied to 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; } } 
+3
source

Perhaps you should consider whether editing texts are needed for storage in list cells? It seems a little unnecessary when the user will only edit one at a time.

While I don’t know how your application was developed, I would recommend rethinking your user interface a bit, so that when you click on a list item for editing, one text edit is edited. Thus, you can simply get a link to the list items, as usual, using the list adapter, save it while the user edits and update it when they are finished.

+1
source

I'm not sure you have a good design, as the contents of the EditText will have a good chance of problems (shuffling the content, missing text) after scrolling through the list. consider trying the idea of ​​m6tt.

but if you really want to go your own way, can you post some code, in particular, your TextWatcher?

+1
source

I tried to solve this problem, and as you can see, there is a simple method - I am posting the answer here, as it may be useful to someone.

It is not possible to get a position when the list view β†’ edit text has a text observer.

This is the solution that worked for me:

In view mode -

when I add a text observer listener to edit text, I also added the line below

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

in your afterTextChanged -

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

Gives the correct position number, and you can make changes depending on the position number.

0
source

Source: https://habr.com/ru/post/901404/


All Articles