I have an Android application with an customized adapter that extends Cursor Adapter.
I overrided bindView and newview methods of CursorAdapter. Each of my ListView row contains an EditText. When I enter some text in EditText and scrolldown the ListView the content of the EditText text is moved to another EditText.
Can anyone help me in sorting out this issue to how to prevent EditText from reused its content when ListView is scrolled down.
Thanks in Advance,
Here is the code:
private class AddScreenArrayAdapter extends ArrayAdapter<AddScreenItems>{
ViewHolder viewHolder = null;
public String[] holder_values;
public AddScreenArrayAdapter(Context context, int textViewResourceId,
List<AddScreenItems> objects) {
super(context, textViewResourceId, objects);
holder_values = new String[objects.size()];
// TODO Auto-generated constructor stub
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.additem_row, null);
viewHolder = new ViewHolder();
viewHolder.label = (TextView) v.findViewById(R.id.label_add_item);
viewHolder.dbName=(TextView)v.findViewById(R.id.dbtable_name);
viewHolder.value = (EditText) v.findViewById(R.id.value_add_item);
viewHolder.value.addTextChangedListener(new TextWatcher()
{
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
holder_values[viewHolder.ref]= arg0.toString();
}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// TODO Auto-generated method stub
}
});
v.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) v.getTag();
}
AddScreenItems addScreenItems = addScreenItemsList.get(position);
if(addScreenItems!=null)
{
viewHolder.label.setText(addScreenItems.labelname);
viewHolder.dbName.setText(addScreenItems.databaseTableName);
// viewHolder.ref = position;
if (holder_values[position] != null)
{
viewHolder.value.setText(holder_values[position]);
}
else {
viewHolder.value.setText("");
}
}
return v;
}
}
static class ViewHolder {
public TextView label;
public EditText value;
public TextView dbName;
int ref;
}
If you're having problem after scrolling it's the view recycling that's messing you up. You basically need to set up an array to hold the contents of the EditTexts so when you scroll they don't get messed up.
Here's a link to another answer I gave on a similar topic. It ought to point the way for you. SO Answer
EDIT
I use setOnFocusChangeListener to run code when the user finishes an entry in the EditText box.
qty.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
LinearLayout parent = (LinearLayout) v.getParent();
EditText qtyTemp = (EditText) parent.findViewById(R.id.qty);
quantity[pos] = qtyTemp.getText().toString();
}
}
});
Related
//Filling the ArrayList From the Fragment
gridmodel = new TypeTruckPogo("Truck 14 wheel",-1,false);
list.add(gridmodel);
gridmodel = new TypeTruckPogo("Truck 16 wheel",-1,false);
list.add(gridmodel);
final TypeOfTruckAdapter truckAdapter=new TypeOfTruckAdapter(context, list);
truckListView.setAdapter(truckAdapter);
//My POGO CLASS
public class TypeTruckPogo{
String typeOfTruckName;
int nmbrOfTruck;
boolean isEditTextVisiable;
public TypeTruckPogo(String typeOfTruckName,int nmbrOfTruck,boolean isEditTextVisiable){
this.typeOfTruckName=typeOfTruckName;
this.nmbrOfTruck=nmbrOfTruck;
this.isEditTextVisiable=isEditTextVisiable;
}
public String getTypeOfTruckName() {
return typeOfTruckName;
}
public String setTypeOfTruckName(String typeOfTruckName) {
this.typeOfTruckName = typeOfTruckName;
return typeOfTruckName;
}
public int getNmbrOfTruck() {
return nmbrOfTruck;
}
public Integer setNmbrOfTruck(int nmbrOfTruck) {
this.nmbrOfTruck = nmbrOfTruck;
return nmbrOfTruck;
}
public boolean isEditTextVisiable() {
return isEditTextVisiable;
}
public Boolean setIsEditTextVisiable(boolean isEditTextVisiable) {
this.isEditTextVisiable = isEditTextVisiable;
return isEditTextVisiable;
}
}
// My Adapter Class,this class have 20 item in the list,at first time it's showing 8 item , when user press on single row then editText become visible and if user press the same position twice the editText become inviable,But the problem is that when user tap on any position(let say he tapped on position 0) then editText is visible but when i scroll down then other editText is also becoming visible sometime position 8 sometime 15.ANY HELP APPRECIATED !!!! Single row contain textView and editText
public class TypeOfTruckAdapter extends BaseAdapter{
List<TypeTruckPogo> list;
Context context;
LayoutInflater inflater;
public String[] Current;
TypeTruckPogo typeTruckPogo;
public static HashMap<Integer,String> truckHashMap=new HashMap<Integer,String>();
public TypeOfTruckAdapter( Context context,List<TypeTruckPogo> list) {
this.list = list;
this.context = context;
for(int i=0;i<list.size();i++)
{
truckHashMap.put(i,"");
}
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
class Viewholder{
TextView name;
EditText nmbrOfTruck;
int ref;
Viewholder(View view) {
name = (TextView) view.findViewById(R.id.textView1);
nmbrOfTruck = (EditText) view.findViewById(R.id.et_nmbr_of_truck_id);
}
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final Viewholder holder;
typeTruckPogo = list.get(position);
if(convertView==null){
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.single_row_for_type_of_truck, parent, false);
holder = new Viewholder(convertView);
convertView.setTag(holder);
}else{
holder = (Viewholder)convertView.getTag();
}
// For position zero i have to set the text color to blue color,else dark gray color
if(position==0){
holder.name.setTextColor(context.getResources().getColor(R.color.blue_color));
}else{
holder.name.setTextColor(context.getResources().getColor(R.color.darkgray));
}
// setting the name on the textview
holder.name.setText(list.get(position).getTypeOfTruckName());
//setting the tag on edittext
holder.nmbrOfTruck.setTag(position);
//setting the viewholder position
holder.ref = position;
// clicking on listview making edittext to appear (initially edittext is invisiable)
// if edittext is visiable make it invisiable and if it is invisiable make it visiable
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (v.findViewById(R.id.et_nmbr_of_truck_id).getVisibility() == View.VISIBLE) {
v.findViewById(R.id.et_nmbr_of_truck_id).setVisibility(View.INVISIBLE);
} else {
v.findViewById(R.id.et_nmbr_of_truck_id).setVisibility(View.VISIBLE);
}
}
});
// if user write on editText save the input by the user in specified position
//truckHashMap is hashmap where I saving the position as a key and value as the user Input
holder.nmbrOfTruck.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
// TODO Auto-generated method stub
}
public void afterTextChanged(Editable s) {
Current = new String[holder.ref];
truckHashMap.put(position, s.toString().trim());
}
});
// Setting the User Input at specified Position
holder.nmbrOfTruck.setText(truckHashMap.get(position));
Config.colorFont(context, null, holder.name, null);
return convertView;
}
You have to use else statement which set your default text color in your adapter:
...
if(position==0){
holder.name.setTextColor(context.getResources().getColor(R.color.blue_color));
} else {
// here set your default text color black for example
holder.name.setTextColor(context.getResources().getColor(R.color.black_color));
}
...
Hope it helps!
Where your else condition ?
if(position==0)
{
holder.name.setTextColor(context.getResources().getColor(R.color.blue_color));
} else {
// Calling when if Condition not Satisfied .
holder.name.setTextColor(context.getResources().getColor("Your_Color"));
}
I have a ListView that contains two TextViews and one EditText in each row. I have searched and searched and cannot figure out how to get the text that the user enters into the EditText. My most recent attempt implements a TextWatcher.
public void addIngredientToMeal(String ingredientName) {
ingredient_list = (ListView) findViewById(R.id.ingredients_in_meal_listView);
int numberOfIngredients = ingredient_list.getChildCount();
ListAdapter adapter = new ListAdapter();
adapter.name_array = new String[numberOfIngredients+1];
for (int i = 0; i < numberOfIngredients; i++)
adapter.name_array[i] = (String) ingredient_list.getItemAtPosition(i);
adapter.name_array[numberOfIngredients] = ingredientName;
ingredient_list.setItemsCanFocus(true);
ingredient_list.setAdapter(adapter);
}
private class ListAdapter extends BaseAdapter{
public String[] name_array, qty_array;
#Override
public int getCount() {
// TODO Auto-generated method stub
if(name_array != null && name_array.length != 0){
return name_array.length;
}
return 0;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return name_array[position];
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//ViewHolder holder = null;
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = NewMeal.this.getLayoutInflater();
convertView = inflater.inflate(R.layout.ingredients_in_meal_layout, null);
holder.textView1 = (TextView) convertView.findViewById(R.id.ingredient_name_in_new_meal_textView);
holder.editText1 = (EditText) convertView.findViewById(R.id.ingredient_qty_in_new_meal_editText);
holder.textView2 = (TextView) convertView.findViewById(R.id.ingredient_unit_in_new_meal_textView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.ref = position;
holder.textView1.setText(name_array[position]);
holder.textView2.setText(databaseAdapter.dbQuery(name_array[position]));
holder.editText1.setText(qty_array[position]);
holder.editText1.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
qty_array[holder.ref] = arg0.toString();
}
});
return convertView;
}
private class ViewHolder {
TextView textView1, textView2;
EditText editText1;
int ref;
}
}
}
For those who may have a similar issue, I solved the problem I was having.
The problem:
Need to get values entered in multiple editTexts that are contained within a listView. Using listviewname.getItemAtPosition(integer) only gets the value of the first editText. Moreover, I had multiple views contained in each row of the listview, so getItemAtPosition only returned the value of the first view in the first row of the listView.
The solution:
Define a listView object that identifies the listview that we care
about
Define a View object that can get the listview
Define whatever field(s) you are trying to get from the listview (EditTexts, TextViews Etc.)
Get the number of rows that the listview currently contains
Set the view object using listviewname.getChildAt(position)
Assign the field (say, an editText) using something like (EditText) viewObject.findViewById(R.id.edittextid)
Get the value from the field using editTextObject.getText().toString()
Here's some sample code that could be implemented on a button press:
ListView lvName = (ListView) findViewById(R.id.listview1);
View v;
EditText et;
int listLength = lv.getChildCount();
String[] valueOfEditText = new String(listLength);
for (int i = 0; i < listLength; i++)
{
v = lvName.getChildAt(i);
et = (EditText) v.findViewById(R.id.edittext1);
valueOfEditText[i] = et.getText().toString();
}
getFocusedChild(position) it will return a View, or findFocus()
View row = ingredient_list.getFocusedChild();
EditText et = (EditText)row.findViewById(R.id.ingredient_qty_in_new_meal_editText);
Edit
Sorry i misunderstood create a gist will toast with the input
https://gist.github.com/imjarp/9313c687ccbe339d052f
I have a listview with 2 textviews and an Edit text. I have used a custom adapter to populate the listview (as I used the same for avoiding refreshing of checkboxes a month ago), my question is how to avoid the refereshing of the edit texts when the list view is scrolled, as I want to save the data on each edittext. Will the textwatcher help in any way to avoid the refreshing and saving ? If yes please help.I have included my the model and custom adapter class here:
Model class:
public class InternalListModel {
String no;
String name;
String value;
public InternalListModel(String internNo, String internName) {
// TODO Auto-generated constructor stub
this.no=internNo;
this.name=internName;
value="";
}
public String getNo(){
return no;
}
public String getName(){
return name;
}
public String getValue(){
return value;
}
public void setValue(String value){
this.value=value;
}
}
custom adapter class:
public class InternCustomAdapter extends ArrayAdapter<InternalListModel>
{
private final List<InternalListModel> internnoname;
private final Internal6 context;
public InternCustomAdapter(Internal context,
List<InternalListModel> internnoname) {
super(context,R.layout.internlistdecor,internnoname);
// TODO Auto-generated constructor stub
this.context=context;
this.internnoname=internnoname;
}
static class ViewHolder{
protected TextView textview,textview1;
protected EditText edittext;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder viewHolder;
if(convertView ==null){
LayoutInflater inflator = context.getLayoutInflater();
convertView = inflator.inflate(R.layout.internlistdecor,null);
viewHolder = new ViewHolder();
viewHolder.textview=(TextView)convertView.findViewById(R.id.tvintNO);
viewHolder.textview1=(TextView)convertView.findViewById(R.id.tvintName);
viewHolder.edittext = (EditText)convertView.findViewById(R.id.etintValue);
viewHolder.edittext.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
convertView.setTag(viewHolder);
convertView.setTag(R.id.tvintNO, viewHolder.textview);
convertView.setTag(R.id.tvintName, viewHolder.textview1);
convertView.setTag(R.id.etintValue, viewHolder.edittext);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textview.setText(internnoname.get(position).getNo());
viewHolder.textview1.setText(internnoname.get(position).getName());
viewHolder.edittext.setText(internnoname.get(position).getValue());
return convertView;
}
}
You can set the entered text, in the value field for that position(index)
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
internnoname.get(position).setValue(s.toString());
}
That way even when the Views are recycled, depending on the position, the value will be set properly to the EditTexView, because of the below code:
viewHolder.edittext.setText(internnoname.get(position).getValue());
I have a stock check application wherein the materials are displayed in a grid and each grid element has an image of the material, edittext of quantity , check button and an image which turns red or green depending on whether stock is available or not.
There is also a textview which be set to "Available" if image is green else to "Not Available" if image is red.
I am using a custom adapter which is extending a base adapter.
Everything is working fine until i press the check button
I used edittext textwatcher to get the text changed at which position but when i m pressing the check button the image is set to green at the 9th element of the 3*3 Grid.
I am using viewHolder but still its not working.
Can anyone please help.
Please see the below codes
private class CustomAdapter extends ArrayAdapter<HashMap<String, Object>> {
private Context context;
boolean[] checkboxstate;
ViewHolder viewHolder;
ArrayList<HashMap<String, Object>> testdata;
public CustomAdapter(Context context, int textViewResourceId,
ArrayList<HashMap<String, Object>> testdata) {
super(context, textViewResourceId, testdata);
this.context=context;
this.testdata=testdata;
checkboxstate = new boolean[testdata.size()];
}
private class ViewHolder {
TextView txt_product;
ImageView image_available;
ImageView image_product;
TextView txt_available;
EditText quantity;
Button check;
}
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View gridView;
if (convertView == null) {
gridView=new View(context);
convertView = inflater.inflate(R.layout.salesdummy, null);
viewHolder = new ViewHolder();
// cache the views
viewHolder.quantity=(EditText)convertView.findViewById(R.id.quantity);
viewHolder.image_product=(ImageView)convertView.findViewById(R.id.image1);
viewHolder.image_available=(ImageView)convertView.findViewById(R.id.imagecheck);
viewHolder.txt_available=(TextView)convertView.findViewById(R.id.txt_available);
viewHolder.check=(Button)convertView.findViewById(R.id.btncheck);
viewHolder.txt_product=(TextView)convertView.findViewById(R.id.product);
// link the cached views to the convertview
convertView.setTag(viewHolder);
} else
viewHolder = (ViewHolder) convertView.getTag();
// set the data to be displayed
viewHolder.txt_product.setText(testdata.get(position).get("MATERIAL").toString());
int photoId=(Integer) testdata.get(position).get("IMAGE");
viewHolder.image_product.setImageDrawable(getResources().getDrawable(photoId));
/* viewHolder.quantity.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
quant=s.toString();
}
});
*/
viewHolder.check.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.d("VAlue of string",quant);
int i_quant;
i_quant=Integer.parseInt(quant);
String material=testdata.get(position).get("MATERIAL").toString();
Log.d("Check material",material);
Cursor c=db.GetMaterial(material);
rec_quantity=c.getString(2);
System.out.println("Value of received quantity is" + rec_quantity);
i_rec_quantity=Integer.parseInt(rec_quantity);
if(i_quant>i_rec_quantity)
{
System.out.println("===============Value is greater than stock");
viewHolder.image_available.setBackgroundDrawable(getResources().getDrawable(R.drawable.red));
viewHolder.txt_available.setText("Not Available");
}
else
{
viewHolder.image_available.setBackgroundDrawable(getResources().getDrawable(R.drawable.green));
viewHolder.txt_available.setText("Available");
}
}
});
viewHolder.quantity.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
quant=s.toString();
}
});
/*
viewHolder.txt_name.setText(testdata.get(position)
.get("NAME").toString());
viewHolder.txt_salesvolume.setText(testdata.get(position)
.get("SALESVOLUME").toString());
viewHolder.txt_overdue.setText(testdata.get(position)
.get("OVERDUE").toString());
viewHolder.txt_outstanding.setText(testdata.get(position)
.get("OUTSTANDING").toString());
viewHolder.txt_creditlimit.setText(testdata.get(position)
.get("CREDIT_LIMIT").toString());
viewHolder.txt_creditutilization.setText(testdata.get(position)
.get("CREDIT_UTILIZATION").toString());
String creditlimit=testdata.get(position).get("CREDIT_LIMIT").toString();
String creditutilized=testdata.get(position).get("CREDIT_UTILIZATION").toString();
*/
/*
String remcom=testdata.get(position).get("CREDIT_UTILIZATION").toString();
Log.d("Remcom value",remcom);
String remcom1=remcom.replace(",","");
int inint=Integer.parseInt(remcom1);
if(inint>150000)
{
viewHolder.txt_creditutilization.setTextColor(Color.RED);
}
*/
// VITAL PART!!! Set the state of the
// CheckBox using the boolean array
// //HAVE OPENED THE BELOW COMMENT AND HAVE DONE THIS TO CHECK
// WHETHER DUPLICATE CHECKS ARE NOT IMPLEMENTED
// return the view to be displayed
return convertView;
}
}
I would like to enable search functionality to EditText. My requirement is like this:
when someone types with some letter, suppose the user types 'a', then it should show all the words which starts with 'a' should be shown as a drop down list. For example, if I first typed "copy" in the EditText, if again, I cleared the EditText and tried to type "co", then it should show the drop-down list "copy","come","cow"....
I want to enable this feature to my EditText view. It worked when I had a ListView with only a textview inside, but now that I have two textview in my ListView it doesn't work.
This is my activity:
public class sedactivity extends Activity {
ListView lview;
ListViewAdapter lviewAdapter;
EditText ed;
private static final String first[] = {
"America",
"Busta",
"Cactus",
"Fire",
"Garden",
"Hollywood",
"King",};
private static final String second[] = {
"Uniti",
"Chiusa",
"Verde",
"Fiamme",
"Aperto",
"Boulevard",
"Kong",};
private ArrayList<String> arr_sort= new ArrayList<String>();
int textlength=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ed = (EditText)findViewById(R.id.EditText1);
lview = (ListView) findViewById(R.id.listView2);
lviewAdapter = new ListViewAdapter(this, first, second);
System.out.println("adapter => "+lviewAdapter.getCount());
lview.setAdapter(lviewAdapter);
lview.setTextFilterEnabled(true);
ed.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
textlength=ed.getText().length();
arr_sort.clear();
for(int i=0;i<first.length;i++)
{
if(textlength<=first[i].length())
{
if(ed.getText().toString().equalsIgnoreCase((String) first[i].subSequence(0, textlength)))
{
arr_sort.add(first[i]);
}
}
}
}});}
}
And this is my ListView Adapter
public class ListViewAdapter extends BaseAdapter{
Activity context;
String title[];
String description[];
public ListViewAdapter(Activity context, String[] title, String[] description) {
super();
this.context = context;
this.title = title;
this.description = description;
}
public int getCount() {
// TODO Auto-generated method stub
return title.length;
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
private class ViewHolder {
TextView txtViewTitle;
TextView txtViewDescription;
}
public View getView(int position, View convertView, ViewGroup parent)
{
// TODO Auto-generated method stub
ViewHolder holder;
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null)
{
convertView = inflater.inflate(R.layout.listitem_row, null);
holder = new ViewHolder();
holder.txtViewTitle = (TextView) convertView.findViewById(R.id.textView1);
holder.txtViewDescription = (TextView) convertView.findViewById(R.id.textView2);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.txtViewTitle.setText(title[position]);
holder.txtViewDescription.setText(description[position]);
return convertView;
}
}
I think an AutoCompleteTextView might be more suitable to implement this feature.
Check out this example to create your own Listener to check the values inside Edittext on key press event - How to implement your own Listener
Instead of extending BaseAdapter you extend ArrayAdapter. It implements the Filterable interface for you. In TextWatcher call getFilter().filter(text); method.
public void afterTextChanged(Editable s) {
listview.getAdapter().getFilter().filter(s);
}