I have created a custom Array Adapter to bind a custom row that contains some static text and an editable EditText. I am trying to register to be notified when the user changes the text within the edit text and when notified to determine which ArrayList row the modified EditText corresponds to.
In the past with other types of views such as a Spinner I could simply put a reference to the parent view and the row number into the tag for the Spinner view. And then when I was notified that the value changed I read the tag to determine how to correlate it back to the master ArrayList.
The problem with registering to be notifed with an EditText change is that you do not get back a view but instead get a TextWatcher and I have no way to correlate back to the parent view or ArrayList row.
What is the technique that you need to use in this circumstance?
You can use onEditorAction on your EditText in your ArrayAdapter:
mEditText.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
// Parse parent tree to find position of view
int position = 0;
View v = null;
while (view != v && position < mListView.getChildCount())
v = mListView.getChildAt(position++);
// do something
something(position);
// do not consume the action
return false;
}
});
Note that using this method, you are going to trigger an event only when user press "ok", "enter", "done", etc. on the keyboard.
Related
I am trying to get the index of a spinner that is inside my inflated view.
Although I'm successful in retrieving the index of my child view when it's inflated on a button click like this:
itineraryDetailLL = (LinearLayout) findViewById(R.id.itineraryDetailLinearlayout);
childView = getLayoutInflater().inflate(R.layout.cardview, null);
itineraryDetailLL.addView(childView);
int posValue = itineraryDetailLL.indexOfChild(childView);
Toast.makeText ( PlanItineraryDetailView.this, Integer.toString(posValue), Toast.LENGTH_SHORT ).show();
This bit of code returns me 0 for 1st inflated view, 1 for 2nd inflated view and so on...
Problem
But when I'm trying to get the index position of the spinner (by calling the setOnTouchListener event) in each of my child view it returns me the last index position for each spinner
spinnerPlanItinerary.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
int indexValueTown = itineraryDetailLL.indexOfChild(childView);
Toast.makeText ( PlanItineraryDetailView.this, Integer.toString(indexValueTown), Toast.LENGTH_SHORT ).show();
return true;
}
});
This returns me 1 for spinner in my 1st inflated view, 1 for spinner my 2nd inflated view (It should return 0 for spinner in my 1st inflated view, 1 for spinner in my 2nd inflated view).
I hope I'm clear with my problem.
Note I'm inflating only two views only for testing right now.
Posting as answer so someone who stumble here might get solution.
The problem in your case was your itineraryDetailLL & childView were global variables. That means whenever you add new item via button click, there value was updating to the last inflated view. now whenever you touch on Spinner, you were getting the last index as expected.
So making them local & final variable made sure that you refer to the same view when you touch the spinner.
I didn't understood your requirement or what you were trying to do fully though. There might be better way of achieving this.
I am new to android and having some trouble with this method and wondering if someone can assist with this.
Question: I have an array adapter with EditText box that the user can modify in the ListView. But, I only want user modifications and not the program's in my fragment. How do I do this?(read on for full context) The issue here is that when the user modifies this EditText in the listView, the adapter will make a call to the fragment and the fragment will manipulate the numbers. Then it will modify the other EditText in the list view.
The problem for me is, when the user modifies or clicks on the EditText in the list view, it's value using afterTextChanged() will be passed to the fragment, but since i do some modification and modify the same EditText in different positions in the list view programmatically, the afterTextChanged events gets called for other EditText views in the list view as well. I just want user changed.
To tackle this, I tried using this onTouchListener(). Just want to know if this is correct.
Class myArrayAdapter extends ArrayAdapter<Obj>{
//private defines and static viewHolder class
public myArrayAdapter (Context c, ArrayList<Obj> obj, MyFragment myFrag
{
//this....
}
#Override
public View get View (int position, View convertView, ViewGroup parent){
obj posObj = getItem(position);
if (convertView == NULL){
//inflate (ObjlistView)
viewHolder.userInputValue = (EditText) covertView.findViewById(R.id.view_userInput);
//user onTouch
final int pos= position;
viewHolder.userInputValue.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View view, MotionEvent event){
EditText UserInput= (EditText)view;
//this is a custom Text watcher for passing editText Value to Fragment. SO I want this to be only called when user modifies it. Not when the Fragment modifies it and calling notifyDataSetChanged
UserInput.addTextChangedListener(new CustomTextWatcher(pos, myFrag));
return false;
}
});
convertView.setTag(viewHolder)
}else {//...}
viewHolder.userInputValue.setText(posObj.getValue());
}
}
XML for the ListVie
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="number" // another annoying issue when i user clicks the editText it will show the number pad then will go to the keyboard and every time there is a delete or a new entry this keyboard change will happen. But that is not for this question.
android:id="#+id/view_userInput"
In the fragment this is how I am modifying the edittext again
Obj myTempUserobj ;
for (int i = 0; i< userObj.size(); i++){
myTempUserobj = userObj.get(i);
//modify the field in the object
userObj.set(i,myTempUserobj)
myAdapter.notifyDataSetChanged();
}
Thanks for your Help!
Maybe there is a simple solution to my problem, but i´m not able to find it.
I have a ListView with a list of users. Each row has an EditText to enter the username. I want to set hint text for each user like: "user1, user2, user3, etc", used as default name. The user can click on the EditText and change this name, so the hint text dissapears and the user can enter his name, or leave this default name if he wants.
When the ListView is too long, I have the problem of the view recycling, that duplicates the names. I solved it by using a setOnFocusChangeListener for the EditText, and storing the name for each row, and it´s working fine, but I´d like that when I have a long list, keep the hint text or text introduced by the user for each EditText when scrolling the list.
I don´t know how to modify my adapter to set the name/hint for each EditText.
Any idea?
Thanks a lot.
Create one list in your activity
List<String> yourlist = new ArrayList();
yourlist.add("user1");
yourlist.add("user2");
yourlist.add("user3");....
pass this list to adapter then in adapter,
holder.youredittext.setHint(yourlist.get(position));
if your passing number of items to adapter then create one model class then pass to adapter.
I have an adapter like this:
public View getView(final int position, View convertView, ViewGroup parent)
{
View item = convertView;
if(item == null)
{
LayoutInflater inflater = context.getLayoutInflater();
item = inflater.inflate(R.layout.setup_jugador, null);
holder = new ViewHolder();
holder.nombre = (EditText) item.findViewById(R.id.nombre);
// Establecemos el tag
item.setTag(holder);
}
else
{
holder = (ViewHolder)item.getTag();
}
holder.nombre.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
EditText et = (EditText) v.findViewById(R.id.nombre);
// Here I store the name
jugadores.get(position).setNombre(et.getText().toString());
}
}
});
// Update EditText
holder.nombre.setText(jugadores.get(position).getNombre());
// Another option is
holder.nombre.setHint(jugadores.get(position).getNombre());
return(item);
}
jugadores is a list that stores the names. Initially it has user1, user2, etc.
I could setHint when Item==null, but I have to update the text at the end of the adapter, and when scrolling, the view recycling changes the items that are invisible.
I only see 8 items, and when scrolling, if I change first item, item number 9 also change. If I use setText, it becomes black, and if I use setHint, first item becomes grey.
I can´t put hint value in layout because I´d like to add the row number to the name. I tried using a boolean value in the class used as model in the adapter to show that the name has been modified, check this value using position index in the list, and use setText or setHint according to that, but doesn´t work.
I have the listview in my activity. In the list view I have an edit text box with a filled value. I am filling the value using a hashmap. If the user can change the edit text value in list view, I need to update the hashmap and refresh the list view with update values
Can anybody tell me how to do this?
Without code, making a bunch of assumptions here...
Inside your custom adapter (in your getView method), use setOnFocusChangeListener on the EditText and have it fire your code to update the hashmap.
yourEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) { // run when focus is lost
String value = v.getText().toString(); // get the value from the EditText
// Your code to update hashmap
}
}
});
I have EditText inside ListView for inline editing. The user can modify its value & the values are then stored in the SQLite database.
I am using Custom DataAdapter for populating ListView.
There are 15 rows in the listview. at a time 4 rows are visible, to see other rows scrollbar is used (Up / Down)
Issue:
ListView is loaded for the first time. User writes into the EditText 1,2,3,4 in each EditText.
The Scrollbar is moved down & one by one the user enters data into all the rows.
When the user moves the Scroll bar UP to see the first 4 rows... the 4th row shows wrong data instead of 4 it shows 14, which is the last value entered by the user (OR my have some other random value forexample 10/13/11 etc)
In my Custom DataAdapter class i am storing the user input into the datasource when the EditText loses Focus as shown below:
public View getView(int position, View convertView, ViewGroup parent) {
//txtComments is an EditText
holder.txtComments.setId(position);
holder.txtComments.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
final int position = v.getId();
final EditText tempComments = (EditText) v;
// items: the DataSource for the listView
items.get(position).Comments = tempComments.getText().toString();
}
}
});
}
EDIT:
I have also tried the TEXTWATCHER but it doest not work for me.
After extensive testing; we found that this issue occures randomly for example sometimes ExitText11 will show wrong value another time ExitText4 will show wrong value OR both of them will show wrong values & this behaviour changes while moving scrollbar up down.