1

I have a listview with edittext in each row using a textwatcher to show a toast of content input. The textwatcher works fine for all the rows except the first row. The toast after input of text fires up consistently after you input text instead of showing only once.

The other rows respond well to the desired behaviour by displaying the toast once every time you change input. The default values for the inputs is 0.

Here is my code inside getView() of my adapter:

//tvItems is my edittext variable reference

TextWatcher tt = new TextWatcher() {

public void afterTextChanged(Editable s) {

                //tvItems.setSelection(s.length());
            }

            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            public void onTextChanged(CharSequence s, int start, int before, int count) {
                tvItems.removeTextChangedListener(tt);

                if (tvItems.getText().toString().trim().length() == 1) {

                  //to check if input is greater than 0 so we can proceed

                    if (Integer.valueOf(tvItems.getText().toString().trim()) > 0) {
                      //displays toast
                         Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();


                        tvItems.removeTextChangedListener(tt);
                    }
                }
                tvItems.addTextChangedListener(tt);
            }
        };
        tvItems.addTextChangedListener(tt);

Any suggestions will be welcomed.

As requested, my full adapter code:

public class ProductListAdapter extends BaseAdapter implements Filterable {
    List<ProductModel> mStringFilterList;
    ValueFilter valueFilter;
    int item_number = 0;
    TextWatcher tt = null;
    private Activity activity;
    private LayoutInflater inflater;
    private List<ProductModel> modelItems;
    private OnAddRemoveListener myaddInterface;
    TextView tvTitle;
    Button minusIcon, addIcon;

    public ProductListAdapter(Activity activity, List<ProductModel> modelItems, OnAddRemoveListener myaddInterface) {
        this.activity = activity;
        this.modelItems = modelItems;
        mStringFilterList = modelItems;
        this.myaddInterface = myaddInterface;
    }

    @Override
    public int getCount() {
        return modelItems.size();
    }

    @Override
    public Object getItem(int location) {
        return modelItems.get(location);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }/*
    @Override
    public boolean isEnabled(int position) {
        return false;
    }*/

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        if (inflater == null)
            inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null)
            convertView = inflater.inflate(R.layout.product_item_row, null);

        final ProductModel m = modelItems.get(position);

        tvTitle = (TextView) convertView.findViewById(R.id.tv2);
        TextView tprice = (TextView) convertView.findViewById(R.id.tv3);
        boolean ignoreNextTextChange = true;
        final EditText tvItems = (EditText) convertView.findViewById(R.id.num);
        tvItems.setText("0");
        minusIcon = (Button) convertView.findViewById(R.id.minus);
        addIcon = (Button) convertView.findViewById(R.id.add);

        //add items
        addIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("add button", "clicked");
                int new_item_number = 1 + Integer.parseInt(tvItems.getText().toString());
                tvItems.setText("" + new_item_number);
                (myaddInterface).onItemadded(String.valueOf(m.getPrice()), new_item_number, position);
            }
        });

        minusIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("minus button", "clicked");

                int new_item_number = Integer.parseInt(tvItems.getText().toString());
                if (new_item_number > 0) {
                    (myaddInterface).onItemremoved(String.valueOf(m.getPrice()), position);
                    tvItems.setText("" + (new_item_number - 1));
                } else if (tvItems.getText().toString().equals("0")) {

                    tvItems.setText("0");
                }

            }
        });

        tvTitle.setText(m.getname());
        tprice.setText("(" + m.getPrice() + ")");

    public void afterTextChanged(Editable s) {
        if (tvItems.getText().toString().trim().length() == 1) { 
 
            //to check if input is greater than 0 so we can proceed 
            if (Integer.valueOf(tvItems.getText().toString().trim()) > 0) {
               //displays toast 
               Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();    
            } 
         } 
    } 
 
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    } 
 
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    } 
}; 
        tvItems.addTextChangedListener(tt);
        return convertView;
    }

    //code for search filter, not associated with the question
    
    @Override
    public Filter getFilter() {
        if (valueFilter == null) {
            valueFilter = new ValueFilter();
        }
        return valueFilter;
    }

    private class ValueFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            if (constraint != null && constraint.length() > 0) {
                ArrayList<ProductModel> filterList = new ArrayList<>();
                for (int i = 0; i < mStringFilterList.size(); i++)
                    if ((mStringFilterList.get(i).getname().toUpperCase())
                            .contains(constraint.toString().toUpperCase()) || (mStringFilterList.get(i).getproductDesc().toUpperCase())
                            .contains(constraint.toString().toUpperCase())) {


                        ProductModel m = new ProductModel(mStringFilterList.get(i)
                                .getProduct_id(), mStringFilterList.get(i)
                                .getname(), mStringFilterList.get(i)
                                .getPrice(), mStringFilterList.get(i)
                                .getimage_url(), mStringFilterList.get(i)
                                .getproductDesc());

                        filterList.add(m);
                    }
                results.count = filterList.size();
                results.values = filterList;
            } else {
                results.count = mStringFilterList.size();
                results.values = mStringFilterList;
                //show no results
            }

           /* }else if((mStringFilterList.get(i).getproductDesc().toUpperCase())
                    .contains(constraint.toString().toUpperCase())){}*/

            return results;

        }

        @Override
        protected void publishResults(CharSequence constraint,
                                      FilterResults results) {
            modelItems = (List<ProductModel>) results.values;
            notifyDataSetChanged();
        }

    }

}
Steve Kamau
  • 2,755
  • 10
  • 42
  • 73

2 Answers2

2

set the listener object to edittext,(i.e) tt ,like this

editText.addTextChangedListener(tt);

adhi
  • 326
  • 4
  • 6
1

Can you try this instead:

TextWatcher tt = new TextWatcher() {

    public void afterTextChanged(Editable s) {
        if (tvItems.getText().toString().trim().length() == 1) {

            //to check if input is greater than 0 so we can proceed
            if (Integer.valueOf(tvItems.getText().toString().trim()) > 0) {
               //displays toast
               Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();    
            }
         }
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }
};
user3623735
  • 345
  • 2
  • 9
  • Thanks for the reply, but may i ask how are you attaching the textwatcher to your edittext? – Steve Kamau Feb 18 '16 at 10:07
  • `Either editText.addTextChangedListener(new TextWatcher {...})` or `editText.addTextChangedListener(tt);` assuming `tt` is accesible to the editText. – user3623735 Feb 18 '16 at 10:12
  • Still the same result. it's frustrating, but alteast now i have found out that the toast loops through all edittextviews in all the rows before showing the first row value.Like this ==shows first row input,loops through all the rows values, then again first input. – Steve Kamau Feb 18 '16 at 10:21
  • No problem, let me have a look. – user3623735 Feb 18 '16 at 10:33
  • Sure, let me know if you come up with anything – Steve Kamau Feb 18 '16 at 10:40
  • Btw you should really use ViewHolder pattern. – user3623735 Feb 18 '16 at 10:40
  • To avoid frequent call of findViewById() during ListView scrolling? I will definately do that once i solve this. – Steve Kamau Feb 18 '16 at 10:44
  • NO you can't solve this without having a ViewHolder. Please implement ViewHolder and post your code. – user3623735 Feb 18 '16 at 20:51
  • After using ViewHolder on my adapter i attached a custom textwatcherlistener as an inner class which solved the issue. Thank you so much for leading me into the right direction. – Steve Kamau Feb 19 '16 at 07:25