问题
I am working on app in which I am using a Custom ArrayAdaptor to populate my listView.The customoized row includes a number Picker along with some text boxes in its activity. Now the Problem Part--> The funny part is that when i am changing the number of number picker in a particular row other number pickers of other rows get changed automatically.I have been staring at my code almost 2 days now .Please help
Custom_row.java
public class Custom_row extends ArrayAdapter {
static Button ProPay;
Context context;
int newValcount=0;
public Custom_row(Context context, int resourceId,
List<DataItem> items) {
super(context, resourceId, items);
this.context = context;
}
private class ViewHolder {
TextView Items,Cost;
NumberPicker number;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
DataItem dataItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.activity_custom_row, null);
holder = new ViewHolder();
holder.Items = (TextView) convertView.findViewById(R.id.tvItem);
holder.Cost = (TextView) convertView.findViewById(R.id.tvCost);
holder.number=(NumberPicker)convertView.findViewById(R.id.numberPicker);
holder.number.setMaxValue(10);
holder.number.setMinValue(0);
holder.number.setValue(0);
holder.number.setFocusable(false);
ItemList.picker = holder.number;
holder.number.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
if(newVal!=0){
newValcount++;
if(newValcount > 0)
ProPay.setVisibility(View.VISIBLE);
}
else{
newValcount--;
if(newValcount==0)
ProPay.setVisibility(View.INVISIBLE);
}
}
});
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.Items.setText(dataItem.getItem());
holder.Cost.setText(dataItem.getCost());
return convertView;
}
}
ItemList.java `public class ItemList extends Activity { public ListView listView; public static List dataItems; Button PayPro; static NumberPicker picker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
listView = (ListView)findViewById(R.id.itemList);
Custom_row.ProPay=(Button)findViewById(R.id.bProPay);
Custom_row adapter = new Custom_row(this,
R.layout.activity_custom_row, dataItems);
listView.setAdapter(adapter);
}
}
`
回答1:
You need to set your listener everytime so you are not reusing the same listener on multiple rows.
Also newValCount
seems to be shared amoungst all number pickers - so if it changes for one it'll change for them all.
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
DataItem dataItem = getItem(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.activity_custom_row, null);
holder = new ViewHolder();
holder.Items = (TextView) convertView.findViewById(R.id.tvItem);
holder.Cost = (TextView) convertView.findViewById(R.id.tvCost);
holder.number =(NumberPicker)convertView.findViewById(R.id.numberPicker);
holder.number.setMaxValue(10);
holder.number.setMinValue(0);
holder.number.setFocusable(false);
ItemList.picker = holder.number;
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.Items.setText(dataItem.getItem());
holder.Cost.setText(dataItem.getCost());
holder.number.setValue(0);
holder.number.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
if(newVal!=0){
newValcount++; // THIS IS SHARED AMOUNGST ALL NUMBER PICKERS
if(newValcount > 0)
ProPay.setVisibility(View.VISIBLE);
}
else{
newValcount--;
if(newValcount==0)
ProPay.setVisibility(View.INVISIBLE);
}
}
});
return convertView;
}
inside if (convertView == null)
you should only be creating references to views. Not adding a value change listener. (This needs to be done for every item every time, not recycled.
Separately don't do this LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
inside your getView
it's bad for performance to get it everytime
Also static Button ProPay;
will lead to a memory leak, as a Button
is a View
a View
has Context
and the Context
is your Activity
making it static means you will hold a reference to an Activity
even after that Activity
is no longer on the screen i.e. memory leak
回答2:
Custom_row.java
:
holder.numberPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
View parentRow = (View)picker.getParent();
ListView mListView =(ListView)parentRow.getParent();
final int position = mListView.getPositionForView(parentRow);
setPickerNumber(position,newVal);
if(newVal > oldVal){
newValcount = newValcount + newVal - oldVal;
}
if(oldVal > newVal){
newValcount = newValcount + newVal - oldVal;
}
if(newValcount>0)
{
ProPay.setVisibility(View.VISIBLE);
}
else{
ProPay.setVisibility(View.INVISIBLE);
}
}
});
来源:https://stackoverflow.com/questions/33843389/number-picker-in-custom-listview-changing-number-by-itself