Reputation: 233
I have a custom ArrayAdapter implementation as follows:
private final LayoutInflater inflater;
private final Context mContext;
private final int resource;
private ListObject item;
public CheckListAdapter(Context cx, int res, List<ListObject> list){
super(cx,res,list);
resource=res;
mContext=cx;
inflater=LayoutInflater.from(cx);
}
@Override
public View getView(int position, View convertView, ViewGroup container) {
convertView = (LinearLayout) inflater.inflate(resource, null);
item = getItem(position);
TextView slotNoView = (TextView)convertView.findViewById(R.id.itemSlotNo);
TextView itemNameView = (TextView)convertView.findViewById(R.id.itemnameview);
TextView itemIdView = (TextView)convertView.findViewById(R.id.itemIdView);
String slotNo = item.getSlotNo();
String itemName = item.getItemName();
slotNoView.setText(slotNo+".");
itemNameView.setText(itemName);
itemIdView.setText(item.getId());
EditText value = (EditText)convertView.findViewById(R.id.value);
value.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
String new6amVal = value.getText().toString();
Log.d("ListView Position",Integer.toString(position));
Log.d("Item ID: ",item.getId());
Log.d("Item value: ",value.getText().tostring());
}
});
return convertView;
}
All the TextViews get correctly populated when the adapter is created and sent to the list view. But when I make change in the EditText of any of the list item, the change is reflected only in the first list item EditText. When I log the position variable obtained in the getView method from inside the TextChangeListener, I can see that the value of position is always 0. How can I obtain the correct value of position of each list item from inside the getView method?
I also tried to check the value of position by using the OnFocusChangeListener but the value returned is always of the first position.
Upvotes: 1
Views: 610
Reputation: 1113
You should use the recommended ViewHolder
pattern for your adapter, and set your position as final
. If that doesn't work then I suggest you create a custom TextWatcher
class which keeps track of the position itself. Here's some sample code.
For ViewHolder pattern, create a class that extends RecyclerView.ViewHolder and find all your views there
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView slotNoView;
TextView itemNameView;
TextView itemIdView;
EditText value;
public MyViewHolder(View itemView) {
super(itemView);
slotNoView = (TextView) itemView.findViewById(R.id.itemSlotNo);
itemNameView = (TextView)itemView.findViewById(R.id.itemnameview);
itemIdView = (TextView) itemView.findViewById(R.id.itemIdView);
value = (EditText) itemView.findViewById(R.id.value);
}
}
Then in your getView
adapter method, create a new instance of the ViewHolder only if your convertview is null. Like this (remember to make position
final
)
@Override
public View getView(final int position, View convertView, ViewGroup container) {
MyViewHolder viewHolder;
if(convertView == null){
convertView = inflater.inflate(resource, container, false);
}
viewHolder = new MyViewHolder(convertView);
item = getItem(position);
String slotNo = item.getSlotNo();
String itemName = item.getItemName();
viewHolder.slotNoView.setText(slotNo+".");
viewHolder.itemNameView.setText(itemName);
viewHolder.itemIdView.setText(item.getId());
viewHolder.value.addTextChangedListener(new TextWatcher() {
//implement your stuff
...
}
}
If that doesn't work, create a custom abstract class that implements TextWatcher
which would be aware of the position and then just implement a method getPosition()
in it to give you the position when you need it. You can pass the position in constructor. Example:
private abstract class PositionAwareTextWatcher implements TextWatcher{
private int position;
public PositionAwareTextWatcher(int position){
this.position = position;
}
public int getPosition(){
return this.position;
}
}
Then in your getView
where your setting the TextWatcher, use it like this then
viewHolder.value.addTextChangedListener(new PositionAwareTextWatcher(position) {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String new6amVal = value.getText().toString();
Log.d("ListView Position",Integer.toString(getPosition()));
Log.d("Item ID: ",item.getId());
Log.d("Item value: ",value.getText().tostring());
}
};
Upvotes: 2