I have an application with a ListView that displays different transactions made by the user. My code doesn't seem to work.
The problem I have now is that I want to add a Spinner above this ListView to let the user choose whether the transactions should be ordered by date, amount or an own choice of an interval between two dates.
Heres my code for just the spinner onSelectedItem:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_income, container, false);
initializeComponents(view);
registerListeners();
spinnerOrderIncome = (Spinner) view.findViewById(R.id.spinnerOrderIncome);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this.getActivity(), R.array.spinnerSortIncome, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerOrderIncome.setAdapter(adapter);
spinnerOrderIncome.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (spinnerOrderIncome.getSelectedItem().toString()) {
case "date":
lvIncome.setAdapter(new CustomIncomeListAdapter(activity, dbController.getDataFromIncomeTable()));
break;
case "amount":
lvIncome.setAdapter(new CustomIncomeListAdapter(activity, dbController.getSortedAmountFromIncomeTable()));
break;
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
The ListView is already populated with this method that gets the list from the DatabaseController:
public void populateListView() {
lvIncome.setAdapter(new CustomIncomeListAdapter(activity, dbController.getDataFromIncomeTable()));
}
The methods are seen in the switch-statement where thought to change the order of the ListView, but nothing happens when I select the different spinner items (date, amount) Am I on the right track? Help!
Instead of assigning a new adapter to the listView each time you change its data, I would just update the list it contains, then call notifyDataSetChanged to inform the adapter that its datased has changed (so the view will be redrawn).
Something like that, I guess (not tested) :
spinnerOrderIncome.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
CustomIncomeListAdapter myAdapter = (CustomIncomeListAdapter)lvIncome.getAdapter();
myAdapter.getDataSet().clear();
switch (spinnerOrderIncome.getSelectedItem().toString()) {
case "date":
myAdapter.getDataSet().addAll(dbController.getDataFromIncomeTable());
break;
case "amount":
myAdapter.getDataSet().addAll(dbController.getSortedAmountFromIncomeTable());
break;
}
myAdapter.notifyDataSetChanged();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
Related
I am using spinners which are dependent on one another. So when i choose one value in a spinner A the arraylist of other spinners B,C,D change accordingly.
when I select item at position 1 on spinner B and then choose any other value in spinner A The data on spinner B gets updated. So I again choose item at position 1 on spinner B the view doesn't changes while selecting item at any other position changes the view. So the same index doesn't get updated value in this piece of code.
ArrayAdapter<String> myAdapterEmployer = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,employerlist);
myAdapterEmployer.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
employer.setAdapter(myAdapterEmployer);
employer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id)
{
if(position > 0) {
employer1 = employer.getSelectedItem().toString();
employeridname = employdetail.get(employer1);
Sectorlist(employeridname);
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
This changes data of Sectorlist everytime a item is selected in employer.
And then any item is choosen in sectorlist.
ArrayAdapter<String> myAdaptersector = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,sectorlist);
myAdaptersector.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sector.setAdapter(myAdaptersector);
sector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id)
{
sector1=sector.getSelectedItem().toString();
String selectedsectortext = (String) parent.getItemAtPosition(position);
if(position > 0){
sectoridd=sectordetail.get(selectedsectortext);
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Here when i choose item at same index as before it doesn't update in the spinner view.
Inside your onItemSelected of the spinner A you can set Adapter to other spinners to be update and this will work as you want.
employer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id)
{
if(position > 0) {
employer1 = employer.getSelectedItem().toString();
employeridname = employdetail.get(employer1);
Sectorlist(employeridname);
// Update other spinners here
myAdaptersector = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,sectorlist);
myAdaptersector.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sector.setAdapter(myAdaptersector);
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
i have two spiners, the first spinner is an Integer array and second is an array of 2D strings.
ArrayAdapter adapter1,adapter3;
String selectedsection;
Integer selectedsem;
Integer[] semester= new Integer[] {1, 2, 3, 4, 5};
String[][] subject=new String[][]{{"m1"},{"m2"},{"m3"},{"m4"},{"m5"},{"m6"},{"m7"},{"m8"}};
adapter1 = new ArrayAdapter<Integer>(this, android.R.layout.simple_spinner_item, semester);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_item);
sp1.setAdapter(adapter1);
sp1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedsem = (Integer)parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(),String.valueOf(selectedsem),Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
adapter3 = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, subject[selectedsem]);
adapter3.setDropDownViewResource(android.R.layout.simple_spinner_item);
sp3.setAdapter(adapter3);
sp3.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedsubject = parent.getItemAtPosition(position).toString();
Toast.makeText(getApplicationContext(),String.valueOf(selectedsem),Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), selectedsubject, Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
the app crashes because it cannot find the value of selectedsem. SO, how to get the value of selectedsem from first spinner use it in second spinner.
Hope the question is understood!
The reason is since it's Integer it can be null and you are trying to use it while initializing it and nothing is yet selected you may get nullpointerexception so better give it a default value of 0 or something at initialization
and then just create adapter for second spinner after the user selects the item.
You can place your second adapter creation just under onItemSelected
sp1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedsem = semester[parent.getSelectedItemPosition()];
//second adapter code goes here
ArrayAdapter<String> adapterNew = new ArrayAdapter<String>(YourActivity.this, android.R.layout.simple_spinner_item, subject[selectedsem]);
sp3.setAdapter(adapterNew);
Toast.makeText(getApplicationContext(),String.valueOf(selectedsem),Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
we are just updating the second spinner just after the user selects some value in(OnItemSelected) the first spinner.
Try to make the second adapter in another function and call it right after the first adapter made, I mean try to schedule the two task not asynchronous not asynchronous
This is happening because the method onItemSelected of your first spinner's OnItemSelectedListener is only called when the spinner actually gets selected by user. So, when you try to instantiate your adapter3, selectedsem is still null. To fix this, you have to put all the code where you expect selectedsem to have a value, right after it actually gets a value, that is: inside onItemSelected method. Like this:
sp1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedsem = (Integer)parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(),String.valueOf(selectedsem),Toast.LENGTH_SHORT).show();
if (selectedsem != null) {
adapter3 = new ArrayAdapter<String>(YourActivity.this, android.R.layout.simple_spinner_item, subject[selectedsem]);
adapter3.setDropDownViewResource(android.R.layout.simple_spinner_item);
sp3.setAdapter(adapter3);
sp3.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedsubject = parent.getItemAtPosition(position).toString();
Toast.makeText(getApplicationContext(),String.valueOf(selectedsem),Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), selectedsubject, Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
i create in a two way data binding spinner in Android, and added value into with a result of a REST GET.
I need now to add the first value of the spinner as an empty string that when it will be selected from the spinner, the value will be null.
In the fragment class i wrote this code:
//spinner
appCompatSpinner = binding.spinner;
spinnerAdapter = new SpinnerAdapter(getActivity(), viewModel.usersDetailsList );
appCompatSpinner.setAdapter(spinnerActorAdapter);
appCompatSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
viewModel.onSelected(position);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mAdapter.notifyDataSetChanged();
Can someone please help me to achieve that?
I'm new to Android development, I having some problem which unable to resolve.
I tried to implement a Spinner inside Fragment, now it having problems with the spinner.setOnItemClickListener() method,
It showing an error message:
"setOnItemClickListener
(android.widget.AdapterView.OnItemClickListener) in Spinner cannot be
applied to (anonymous
android.widget.AdapterView.OnItemSelectedListener)
Here is my code:
public class CheckAvailabilityFragment extends Fragment {
Spinner spinner;
ArrayAdapter<CharSequence> adapter;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_check_availability, container,false);
spinner = (Spinner)getView().findViewById(R.id.spinner);
adapter = ArrayAdapter.createFromResource(getActivity().getBaseContext(),R.array.venue,android.R.layout.simple_list_item_1);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemClickListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getBaseContext(), parent.getItemAtPosition(position) + " selected", Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
return rootView;
}
}
The error message tells you that setOnItemClickListener() takes a parameter of type OnItemClickListener. However, you are giving it a OnItemSelectedListener. Since Spinner doesn't support OnItemClickListener, you probably mean to call onItemSelectedListener() which takes a OnItemSelectedListener as its parameter.
setOnItemClickListener will not works with spinner as been said at Spinner SetOnItemClickListener:
A spinner does not support item click events. Calling this method will
raise an exception.
Instead use
setOnItemSelectedListener(AdapterView.OnItemSelectedListener).
Try using the following:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getBaseContext(), parent.getItemAtPosition(position) + " selected", Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
use getActivity() instead of getBaseContext()
Is there a reason you want getBaseContext()? You should be able to just pass getActivity() as the first parameter of createFromResource()
Long version I have two spinners on my screen and when I select the one, I do certain operations, and the other spinner should display the original selection, because of design patterns. In this situation, I let the user select the elements on a list by year, and by state. You would agree with me that when the user choose to select by year, the spinner regarding the state should display the default selection (the one that displays all of the item) and not the last selected one.
I am trying to do this from this morning, but when I found this solution I really though I was done.
Short version I want to setSelection(0) on the spinner which is not clicked, without triggering its listener (which by the way, will setSelection(0) on the first spinner, if triggered)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
// irrelevant code...
mYearSpinner.setOnItemSelectedListener(onYearSelected);
mStateSpinner.setOnItemSelectedListener(onStateSelected);
// irrelevant code...
}
private AdapterView.OnItemSelectedListener onYearSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mStateSpinner.setOnItemSelectedListener(null);
mStateSpinner.setSelection(0);
mStateSpinner.setOnItemSelectedListener(onStateSelected);
// Do something...
}
#Override
public void onNothingSelected(AdapterView<?> parent) { }
};
private AdapterView.OnItemSelectedListener onStateSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mYearSpinner.setOnItemSelectedListener(null);
mYearSpinner.setSelection(0);
mYearSpinner.setOnItemSelectedListener(onYearSelected);
// Do something...
}
#Override
public void onNothingSelected(AdapterView<?> parent) { }
};
But no! The listeners will just fire, indiscriminately.
Is there someone who knows how to handle this problem?
Why this solution wouldn't work?
As requested, here is the full code of my onCreateView(...) method
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
Log.d(TAG, "onCreateView");
View view = inflater.inflate(R.layout.fragment_career, container, false);
mExamListView = (ListView) view.findViewById(R.id.exam_list_view);
mYearSpinner = (Spinner) view.findViewById(R.id.select_by_year_spinner);
mStateSpinner = (Spinner) view.findViewById(R.id.select_by_state_spinner);
mLoadingView = view.findViewById(R.id.fragment_career_loading_spinner);
mExamListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Exam exam = (Exam) parent.getItemAtPosition(position);
if (exam.isBookable()) {
FragmentManager fm = getActivity().getSupportFragmentManager();
SessionsDialogFragment.newInstance(exam).show(fm, null);
}
}
});
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> yearAdapter = ArrayAdapter.createFromResource(getActivity(),
R.array.spinner_year, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
yearAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> stateAdapter = ArrayAdapter.createFromResource(getActivity(),
R.array.spinner_state, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
stateAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mYearSpinner.setAdapter(yearAdapter);
mStateSpinner.setAdapter(stateAdapter);
mYearSpinner.setOnItemSelectedListener(onYearSelected);
mStateSpinner.setOnItemSelectedListener(onStateSelected);
return view;
}
I tried implementing what --- suggested and I want to report here what happens.
When the application starts all the two listeners are executed only once.
Then, if I select an item on the first spinner (let's say the year spinner), the expected listener is executed only once (as it should be), and so it is, if I keep selecting items on it.
Ultimately, if I select and item on the state spinner, the listeners are executed in this way
1. onStateListener
2. onYearListener
3. onStateListener
From reading your comments it sounds like you want to set the selection of a second spinner to 0 from your first spinners onItemClick method without triggering its listener.
If you keep a record of the old position the spinners are at in integer variables we can check if the position has changed and only run the code if it has.
That way if we set the old position variable to 0 before changing the spinners current position to 0 it will think its position hasn't changed and so won't run the code in the listener.
private AdapterView.OnItemSelectedListener onYearSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (lastYearPosition != position) {
//Do you code here
lastStatePosition = 0;
mStateSpinner.setSelection(0);
}
lastYearPosition = position;
}
#Override
public void onNothingSelected(AdapterView<?> parent) { }
};
private AdapterView.OnItemSelectedListener onStateSelected = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (lastStatePosition != position) {
//Do your code here
lastYearPosition = 0;
mYearSpinner.setSelection(0);
}
lastStatePosition = position;
}