2

I am currently working on an Activity which requires a ListView with custom NumberPickers. I created the number picker as suggested here.

The problem which I am facing is quite frustrating; when I click on the + button of the number picker, the text view keeps displaying 0. I have tried all these suggestions but nothing has been changed.

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

    View vi = convertView;

    //ViewHolder holder = new ViewHolder();

    if(vi == null)
    {
        holder = new ViewHolder();

        vi = inflater.inflate(R.layout.materialdialogcontent, null);

        //Initialize Buttons and TextViews.

        holder.num.setText("0");

        holder.add.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v) 
            {
                counter++;
                holder.num.setText("" + counter);
            }
        });

        holder.sub.setOnClickListener(new View.OnClickListener()
        {   
            @Override
            public void onClick(View v) 
            {
                counter--;
                holder.num.setText("" + counter);
            }
        });


        //holder.pk = (NumberPicker)vi.findViewById(R.id.npMaterialAmount);

        vi.setTag(holder);
    }
    else
    {
    holder = (ViewHolder)vi.getTag();
    }

    holder.txt.setText(data.get(position).getName());
    //holder.pk.setMaxValue(20);
    //holder.pk.setMinValue(0);

    return vi;
}

public static class ViewHolder
{
    TextView txt;
    Button add;
    Button sub;
    TextView num;
    //NumberPicker pk;
}

The above code is found in my ListView Adapter.

The following is what I have already tried:

When I debug the above code, the counter increments, and the debugger variable shows that the TextView's text is actually being set to the number present in the counter, however the number displayed is still 0.

I have also tried setting an OnItemClickListener() to the ListView, and nothing happens still. I then removed the Button click listeners from the ListView Adapter class and placed them inside the ListView's onItemClickListener(). When debugging however, the Button click listeners are skipped by the debugger.

Do you have any other suggestions?

I would gratefully appreciate all help possible.

Updated:

holder.add.setTag(position);
    holder.add.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v) 
        {
            int position = (Integer)v.getTag();
            int temp = numPickerValues.get(position);
            temp += 1;
            numPickerValues.set(position, temp);
            notifyDataSetChanged();
        }
    });
    holder.num.setText(String.valueOf(numPickerValues.get(position)));
    return convertView;
Community
  • 1
  • 1
ClaireG
  • 1,244
  • 2
  • 11
  • 23
  • 1
    You probably update wrong views, as holder seems to be a variable outside of `getView()`?(also the use of that counter variable isn't right either). Anyway that's not the way to do what you want, you need to somehow hold the value of the number picker from each row and update that. Have a look at this small gist https://gist.github.com/luksprog/6208731 – user Aug 12 '13 at 07:03
  • @Luksprog It is a nice idea. I tried it, however the value did not change. I had to use an ArrayList instead because the number of rows in my ListView are random. It still didn't work however, please take a look. I inserted the code in the above post. – ClaireG Aug 12 '13 at 07:43
  • holder is a class which holds all the components inside one listview row. – ClaireG Aug 12 '13 at 07:46
  • Strange, I saw the `ViewHolder` class, I was referring to the holder variable where is declared. Did you tried my exact example, the one where you set the text from the `numPickerValues` **in the `getView()`** method(not the `onClick`), in the `onClick` method you would just set the new value in `numPickerValues` and call `notifyDataSetChanged()`? – user Aug 12 '13 at 07:49
  • @Luksprog I fixed the edit again because I was setting num text inside button listener. It worked perfectly! Thank you SO much! Please post it as an answer so I can mark it as correct. I am so grateful;I would give you a thousand upvotes if I could! – ClaireG Aug 12 '13 at 07:50

4 Answers4

2

Right now you're probably updating other views, also the counter variable use it's not ok. The right way of handling those row number pickers would be to save their current values in some data structure and set/update the current value from that list:

View vi = convertView;
ViewHolder holder;
if(vi == null) {
    holder = new ViewHolder();
    vi = inflater.inflate(R.layout.materialdialogcontent, null);
    //Initialize Buttons and TextViews.
    vi.setTag(holder);
} else {
    holder = (ViewHolder)vi.getTag();
}
holder.txt.setText(data.get(position).getName());
holder.add.setTag(position); // so we have the proper position in the onClick method
holder.add.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
       // there's no need for counter
      int position = v.getTag();
      // numberpickervalues is the array/list of int values representing the values from all the row
      // update the proper value  
      int temp = numPickerValues.get(position);
      temp += 1; // incremment the value
      numPickerValues.set(position, temp);
      notifyDataSetChanged(); // let the list know about this change
}
});
holder.num.setText(String.valueOf(numberPickerValues.get(position)));
user
  • 86,916
  • 18
  • 197
  • 190
0

As I already suggested days ago: the ViewHolder needs to be a static class.

private static class ViewHolder {
    TextView txt;
    Button add;
    Button sub;
    TextView num;
    //NumberPicker pk;
}

One benefit of using static inner class, is that the inner class can be accessed from static methods, without having an instance of the outer class.

Also I cannot see the reason why u are setting the text for the button when decrementing:

 holder.sub.setText("" + counter);

shouldn't it be?

 holder.num.setText("" + counter);

I suppose when you increment with your Buttons, nothing happens, but when you scroll to another position in the ListView and then back to the position where you incremented, the incremented value will be displayed. This is because the ListView is refreshen upon scrolling. Simply call

notifyDataSetChanged()

to refresh the ListViews Views.

Philipp Jahoda
  • 50,880
  • 24
  • 180
  • 187
0

You need call notifyDataSetChanged ().

This from Android API

public void notifyDataSetChanged ()

Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

blay
  • 464
  • 9
  • 23
0

Once you have incremented i suppose you need to refresh the listview. And to do so follow the link below:

Update ListView

Community
  • 1
  • 1
Zax
  • 2,870
  • 7
  • 52
  • 76
  • 1
    Then tryout the other options in the link. like: myListView.invalidateViews(); this redraws the view. – Zax Aug 12 '13 at 06:31
  • Tried. Not working either. I am literally running out of options – ClaireG Aug 12 '13 at 06:35
  • Actually adapter.notifyDataSetChanged(); should have worked as i have tried a lots of time.. – Zax Aug 12 '13 at 06:39
  • Unfortunately it didn't. I have tried everything possible so far, googled every possible solution, or so I think and nothing is working for my situration – ClaireG Aug 12 '13 at 06:59
  • Try saving your incremented numbers in an array and add elements of this array to the list view. In this case adater.notifyDataSetChanged(); will work. Using this you can even overwrite existing values in the array, so that the old values are no longer displayed. – Zax Aug 12 '13 at 07:10