【问题标题】:How to setOnValueChangedListener from NumberPicker inside a BaseAdapter如何从 BaseAdapter 中的 NumberPicker 设置 OnValueChangedListener
【发布时间】: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);
                    }
                });
            }
        });

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

【问题讨论】:

    标签: android button baseadapter numberpicker


    【解决方案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()。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2015-08-08
    相关资源
    最近更新 更多