如何从 BaseAdapter 中的 NumberPicker 设置 OnValueChangedListener

Posted

技术标签:

【中文标题】如何从 BaseAdapter 中的 NumberPicker 设置 OnValueChangedListener【英文标题】:How to setOnValueChangedListener from NumberPicker inside a BaseAdapter 【发布时间】:2014-08-04 12:27:27 【问题描述】:

我正在尝试创建一个 BaseAdapter,其中每个元素都有一个 NumberPicker 和一个 Button。按钮的动作参数取决于 NumberPicker 中选取的值。我认为的一种解决方案是在 NumberPicker 的 onValueChange 内创建一个 setOnClickListener(按钮的),问题是当我更改数字时 onValueChange 永远不会被触发。

我把代码留给你,让它更清楚:

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);
                    
                );
            
        );

我该如何解决这个问题?谢谢!

【问题讨论】:

【参考方案1】:

由于适配器将重用布局,因此您需要在创建布局时设置监听器。将按钮侦听器移出。否则,它将在每次值更改时设置。这是修改后的代码:

// 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]);


在标签字段中保存数据将确保您在单击按钮时获得正确的行数据。我不知道你的数据是如何表示的,所以我引入了一个 int 数组来存储这些值。否则,选择器在被重用时将失去价值。

【讨论】:

首先感谢您的回答。我不明白几件事。首先什么是标签?我可以使用 getView 中的位置而不是 button.tag (我不知道如何从最后一个中提取位置)。如果 theNumberPicker 是最终变量,那么我无法在 if 情况之外访问。再次感谢! tag 字段是一个 View 对象字段,android 不使用。你可以用它来存储任何东西。 getView() 中的位置变量包含控件请求显示内容的位置信息。当用户与一行上的控件交互时,不会调用 getView()。因此,我将位置存储在标签字段中。这可确保显示的每一行上的控件都知道其位置。抱歉,我应该在 if 块之外定义另一个 var。我已经更新了代码。 既然我问了这个问题,我也有类似的问题。如果每次更改数字选择器中的值时都必须更改文本怎么办?我无法更新文本,因为我没有监听器(就像它有一个按钮一样)。你知道怎么做吗?谢谢! 在数字选择监听器的onValueChange()方法中,可以调用notifyDataSetChanged()方法来强制重绘控件。然后,在 TextView 中显示当前值 numValues[positon]。在 if 块之后设置 NumberPicker 的值后立即调用 setText()。

以上是关于如何从 BaseAdapter 中的 NumberPicker 设置 OnValueChangedListener的主要内容,如果未能解决你的问题,请参考以下文章

Android ListView重写BaseAdapter如何改变指定item中的TextView的颜色?

ListFragment(或 Fragment)中的 BaseAdapter 不起作用

使用 BaseAdapter 时片段 TabLayout 中的 NullPointerException

为啥我的 BaseAdapter 类不增加 getView 中的位置?

如何将数据添加到 listView 的自定义 BaseAdapter - Android

如何在 Baseadapter 中获得位置