Edit: My issue seems like BaseAdapter
just wont post more than 1 Spinner. If I change the array's size to 0, it wont put anything, but anything more than 1 is truncating it. It never passes position 0 from getView()
and it never shwows anymore than 1. I have been at it for hours. Is there a reason for this?
I am having an issue with adding Spinners
dynamically in a ListView
using a BaseAdapter
. I tried it before as a test to make sure it could be done correctly in a test class, and it iterates the positions correctly. But now I am doing it again and its failing. What I mean by failing is instead of getView()
creating the new Spinner
, it never leaves position 0. It still runs. Just never adds more Spinner
s.
This is my code:
Main Adapter code
public class RemindersAdapter extends BaseAdapter{
Spinner[] shownReminders = new Spinner[1];
TextView[] removeReminders = new TextView[1];
String[] reminders = new String[1]; //this hlds the values of the coresponding spinner
RemindersAdapter mAdapter;
@Override
public int getCount() {
return shownReminders.length;
}
@Override
public Object getItem(int position) {
return shownReminders[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
Log.d("TAG", "A NEW SPINNER AND TEXTVIEW IS CREATED HERE WITH POSITION"+position);
if(view == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
view = inflater.inflate(R.layout.reminder_spinner, parent, false);
}
Spinner reminderSpinner = (Spinner)view.findViewById(R.id.reminder_spinner);
reminderSpinner.setTag(String.valueOf(position));
ArrayAdapter<CharSequence> reminderAdapter = ArrayAdapter.createFromResource(
parent.getContext(), R.array.reminders_array, android.R.layout.simple_spinner_item);
reminderAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
reminderSpinner.setAdapter(reminderAdapter);
reminderSpinner.setOnItemSelectedListener(new MyOnReminderSelectedListener());
shownReminders[position] = reminderSpinner;
TextView remove = (TextView)view.findViewById(R.id.remove_reminder);
remove.setTag(String.valueOf(position));
removeReminders[position] = remove;
remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("The Array positioning of this remove view is: ", ""+v.getTag());
}
});
return view;
}
public void addReminder() {
Log.d("addReminder METHOD", "The Add Reminder method is running");
Spinner[] temp = new Spinner[shownReminders.length+1];
TextView[] temp2 = new TextView[removeReminders.length+1];
String [] temp3 = new String[reminders.length+1];
for(int i = 0; i < shownReminders.length; i++) {
temp[i] = shownReminders[i];
temp2[i] = removeReminders[i];
temp3[i] = reminders[i];
}
shownReminders = temp;
removeReminders = temp2;
reminders = temp3;
mAdapter.notifyDataSetChanged();//this just makes the adapter refresh itself
}
public void giveYourself(RemindersAdapter adapter) {
mAdapter = adapter;
}
public class MyOnReminderSelectedListener implements OnItemSelectedListener{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos,
long id) {
int position = Integer.parseInt(parent.getTag().toString()); //gets the position of the Spinner and puts it in the same index in the reminders array
reminders[position] = parent.getItemAtPosition(pos).toString();
for(int i =0; i < reminders.length; i++) Toast.makeText(parent.getContext(), i+": "+reminders[i], Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// Do nothing for now
}
}//end of MyOnReminderSelectedListener innerclass
}//end of Class
What runs in the Activity
reminderList = (ListView)findViewById(R.id.reminders_list);
reminderAdapter = new RemindersAdapter();
reminderAdapter.giveYourself(reminderAdapter);
reminderList.setAdapter(reminderAdapter);
TextView addReminder = (TextView)findViewById(R.id.add_reminder);
addReminder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "The onClick is running !");
reminderAdapter.addReminder();
}
});
I am at a loss because my code looks exactly like my test code, with some modifications in order for it to work with my app. But the information used by the Adapter
is pretty much the same. I am going to post the test code as well so you guys can see the code that works.
Test Code
public class RemindersAdapter extends BaseAdapter{
Spinner[] shownReminders = new Spinner[1];
ArrayList<TextView> removeSpinner = new ArrayList<TextView>();
Context mContext;
public RemindersAdapter(Context context) {
mContext = context;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return shownReminders.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return shownReminders[position];
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
Log.d("TAG", "Number of times this is running"+position);
Log.d("TAG", "Address of the Spinner Object"+shownReminders[position]);
if(view == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
view = inflater.inflate(R.layout.reminder_spinner, parent, false);
}
Spinner reminderSpinner = (Spinner)view.findViewById(R.id.reminders_spinner);
reminderSpinner.setTag("1");
ArrayAdapter<CharSequence> reminderAdapter = ArrayAdapter.createFromResource(
parent.getContext(), R.array.reminders_array, android.R.layout.simple_spinner_item);
reminderAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
reminderSpinner.setAdapter(reminderAdapter);
reminderSpinner.setOnItemSelectedListener(new MyOnReminderSelectedListener());
shownReminders[position] = reminderSpinner;
TextView remove = (TextView)view.findViewById(R.id.remove_reminder);
remove.setTag(position);
removeSpinner.add(remove);
remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = Integer.parseInt(v.getTag().toString());
removeSpinner.remove(pos);
Spinner[] temp = new Spinner[shownReminders.length-1];
for(int i =0; i < shownReminders.length; i++) {
if(i == pos || i > pos) {
temp[i-1] = shownReminders[i];
} else {
temp[i] = shownReminders[i];
}
}
//Here i should refresh somewhow
}
});
return view;
}
public void addReminder() {
Spinner[] temp = new Spinner[shownReminders.length+1];
for(int i = 0; i < shownReminders.length; i++) {
temp[i] = shownReminders[i];
}
shownReminders = temp;
}
/*
* Listener for when the reminder spinner gets a value the user entered
* */
public class MyOnReminderSelectedListener implements OnItemSelectedListener{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos,
long id) {
//does nothing for now
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// Do nothing for now
}
}//end of MyOnReminderSelectedListener innerclass
I also have a question as to why the Adapter runs itself so much. For examples, using the Log, I noticed it calls getView()
twice for no apparent reason. Its weird that it has this behavior. I guess I don't understand BaseAdapter
so well.
This error will happen if you put a ListView inside a ScrollView. ListView itself does vertical scroll so it must not be put into a ScrollView.
An adapter will call getView when listView needs a new item to show. So, if your listView has no scroll, no new item will be created, and no call to getView will be made.
But you should not store all spinner objects, or create new objects in getView. That`s because it will be slow and maybe waste of memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With