如何从 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 中的位置?