How to setOnValueChangedListener from NumberPicker inside a BaseAdapter

牧云@^-^@ 提交于 2020-01-11 07:52:08

问题


I am trying to create a BaseAdapter which each element has a NumberPicker and a Button. The button's action parameters depends on the value picked in NumberPicker. One solution I thought was creating a setOnClickListener (of the button) inside the onValueChange of the NumberPicker, the problem is onValueChange never gets fired when I change the number.

I leave you the code to make it clearer:

public class Adapter extends BaseAdapter{
...

  public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        if (v == null)
        {
            LayoutInflater vi = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.row, null);
        }
        button = (Button) v.findViewById(R.id.button);
        numPick = (NumberPicker) v.findViewById(R.id.numPick);
        numPick.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                val = newVal;
                button.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View arg0) {
                        actionToPerform(val);
                    }
                });
            }
        });

How can I solve this problem? Thank you!


回答1:


Since the adapter will reuse the layout, you will need to set your listener when you create the layout. Move the button listener out. Otherwise, it will get set on every value change. Here is the revised code:

// Put the array as a member of your activity or fragment's class
// Remember to save it between life cycle event
// Initialize it to same size as your adapter data
int[] numValues;

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null)
    {
        LayoutInflater vi = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.row, null);

        final Button button = (Button) v.findViewById(R.id.button);
        final NumberPicker numPick = (NumberPicker) v.findViewById(R.id.numPick);

        button.setOnClickListener(new View.OnClickListener() {
                public void onClick(View arg0) {
                    // Get the position value from the tag field
                    int pos = (int)button.tag;
                    actionToPerform(numValues[pos]);
                }
            });

        numPick.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
        public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
              // Save the value in the number picker
              numPick.tag = newVal;
          }
        });
    }

    // Save the position in the button's tag field
    button.tag = position;
    // Restore picker value
    final NumberPicker numPick1 = (NumberPicker) v.findViewById(R.id.numPick);
    numPicker1.setValue(numValues[position]);

}

Saving the data in the tag field will ensure you get the right row's data when the button is clicked. I don't know how your data is represented so I introduce a int array to store the values. Otherwise, the picker will lose the value when it gets reused.



来源:https://stackoverflow.com/questions/24213890/how-to-setonvaluechangedlistener-from-numberpicker-inside-a-baseadapter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!