I've been working on a registration form app with few spinner widgets being used in it. The spinners are to be used to select Country, State and City. Hence, these spinners need to be interconnected somehow (The code below would show how I have tried to achieve that).
Form code:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true">
<TextView
android:text="Student Registration Form"
android:textSize="22sp"
android:textAlignment="center"
android:layout_marginBottom="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/country_spinner"
android:foregroundTint="#222"
android:background="#001c47"
android:layout_marginBottom="20dp" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/state_spinner"
android:foregroundTint="#222"
android:background="#001c47"
android:layout_marginBottom="20dp" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/city_spinner"
android:foregroundTint="#222"
android:background="#001c47"
android:layout_marginBottom="20dp" />
</LinearLayout>
</ScrollView>
The code above has more widgets which you might find in the java file; I haven't included them in above code as it would make it too long.
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.SharedPreferences;
import android.nfc.Tag;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.AppCompatButton;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class RegisterFragment extends Fragment implements View.OnClickListener, Spinner.OnItemSelectedListener{
private AppCompatButton btn_register;
private EditText et_email,et_password,et_name;
private TextView tv_login;
private ProgressBar progress;
//Declaring the Spinners
private Spinner country_spinner;
private Spinner state_spinner;
private Spinner city_spinner;
//An ArrayList for Spinner Items
private ArrayList<String> results;
// countGetData: It will keep a count of how many times get data has been run and for 0 times
// it would set the spinners to default state
private int countGetData;
ArrayList student1 = new ArrayList();
//JSON Array
private JSONArray resultArray;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_register,container,false);
initViews(view);
return view;
}
private void initViews(View view){
btn_register = (AppCompatButton)view.findViewById(R.id.btn_register);
tv_login = (TextView)view.findViewById(R.id.tv_login);
et_name = (EditText)view.findViewById(R.id.et_name);
et_email = (EditText)view.findViewById(R.id.et_email);
et_password = (EditText)view.findViewById(R.id.et_password);
progress = (ProgressBar)view.findViewById(R.id.progress);
btn_register.setOnClickListener(this);
tv_login.setOnClickListener(this);
//Initializing the ArrayList
results = new ArrayList<String>();
// Initializing countGetData
countGetData = 0;
//Initializing Spinner
country_spinner = (Spinner) view.findViewById(R.id.country_spinner);
state_spinner = (Spinner) view.findViewById(R.id.state_spinner);
city_spinner = (Spinner) view.findViewById(R.id.city_spinner);
//Adding an Item Selected Listener to our Spinner
//As we have implemented the class Spinner.OnItemSelectedListener to this class iteself we are passing this to setOnItemSelectedListener
country_spinner.setOnItemSelectedListener(this);
state_spinner.setOnItemSelectedListener(this);
city_spinner.setOnItemSelectedListener(this);
university_spinner.setOnItemSelectedListener(this);
college_spinner.setOnItemSelectedListener(this);
ca_spinner.setOnItemSelectedListener(this);
getData("getCountries", "", 0);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.tv_login:
goToLogin();
break;
case R.id.btn_register:
String name = et_name.getText().toString();
String email = et_email.getText().toString();
String password = et_password.getText().toString();
if(!name.isEmpty() && !email.isEmpty() && !password.isEmpty()) {
progress.setVisibility(View.VISIBLE);
registerProcess(name,email,password);
} else {
Snackbar.make(getView(), "Fields are empty !", Snackbar.LENGTH_LONG).show();
}
break;
}
}
private void getData(String urlPart1,String urlPart2, long itemId) {
//Creating a string request
StringRequest stringRequest = new StringRequest(Config.DATA_URL+urlPart1+"&"+urlPart2+"="+itemId,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject j = null;
try {
//Parsing the fetched Json String to JSON Object
j = new JSONObject(response);
//Storing the Array of JSON String to our JSON Array
resultArray = j.getJSONArray(Config.JSON_ARRAY);
//Calling method getStudents to get the students from the JSON Array
getResults(resultArray);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating a request queue
RequestQueue requestQueue = Volley.newRequestQueue(getActivity().getApplicationContext());
//Adding request to the queue
requestQueue.add(stringRequest);
}
private void getResults(JSONArray j) {
//Traversing through all the items in the json array
for (int i = 0; i < j.length(); i++) {
try {
//Getting json object
JSONObject json = j.getJSONObject(i);
//Adding the name of the student to array list
results.add(json.getString(Config.TAG_NAME));
} catch (JSONException e) {
e.printStackTrace();
}
}
if(countGetData == 0) {
student1.add("Select This");
//Setting adapter to show the items in the spinner
country_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));
state_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, student1));
city_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, student1));
countGetData += 1;
}
}
//this method will execute when we pic an item from the spinner
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(country_spinner.getSelectedItem().toString().equals("Austria")){
long itemId = country_spinner.getSelectedItemId();
getData("getStates","countryId",itemId);
state_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));
}
else{
long itemId = country_spinner.getSelectedItemId();
getData("getStates","countryId",itemId);
state_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));
}
}
}
There is a PHP API which returns the json for Country, State or City based on the url. For ex.:
http://www.example.com/location_api/api.php?type=getCountries
http://www.example.com/location_api/api.php?type=getStates&countryId=12
http://www.example.com/location_api/api.php?type=getCities&stateId=1
In onItemSelected I'm trying to dynamically set spinners with respect to the previous spinner. For ex., I'm setting the state spinner whenever a country spinner item is selected. I'm checking this through a if-else block; if condition checks if Austria(one of the countries in the list; random choice) is selected then set the state spinner else also set the state spinner. This way I end up setting the state spinner according to the country spinner element.
To specify to the API which country is being chosen I'm using the itemId which contains the Id of the selected item in country spinner.
long itemId = country_spinner.getSelectedItemId();
Then when I have the Id I call the getData method which sets the result ArraryList and I assign it to the spinner state.
getData("getStates","countryId",itemId);
state_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));
The above code is making the app crash at run time with following error(only part of it which I think might be useful, full Logcat file here: Link):
--------- beginning of crash 04-13 21:05:09.782 9288-9600/com.gouravchawla.loginregistration E/AndroidRuntime: FATAL EXCEPTION: Thread-503 Process: com.gouravchawla.loginregistration, PID: 9288 java.lang.NegativeArraySizeException: -110 at com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316) at com.android.volley.toolbox.DiskBasedCache.get(DiskBasedCache.java:117) at com.android.volley.CacheDispatcher.run(CacheDispatcher.java:101)
Throwing OutOfMemoryError "Failed to allocate a 1667853436 byte allocation with 777786 free bytes and 381MB until OOM"
You can add a dropdown menu to your Android application in a few simple steps. For starters, you need to edit the XML files. Integrate the dropdown menu into them using Android Studio's drag-and-drop feature. Next, you have to create a string array to add all the relevant items to your dropdown menu.
Spinner is a widget similar to a drop-down list for selecting items. In this tutorial, we show you how to do the following tasks : Render a Spinner in XML, and load the selection items via XML file also. Render another Spinner in XML, and load the selection items via code dynamically.
in your code you would have to change the adapter of the spinner which is dependent on the other spinners for example.
City spinner
adapter change depending on State spinner
adapter
so does the
Statespinner
adapter change depending on Countryspinner
adapter,
I have written a sample code that would demonstrate how this can be achieved, I have written a generic code that others can understand while reading the answer feel free to suggest and change it as it fits your requirement.
Code is also available on Github, and another example that would help you download JSON
data from network it uses, OkHttp
, GSON
and apache-common-io
, code
public class SpinnerCountryActivity extends AppCompatActivity {
private Spinner country_Spinner;
private Spinner state_Spinner;
private Spinner city_Spinner;
private ArrayAdapter<Country> countryArrayAdapter;
private ArrayAdapter<State> stateArrayAdapter;
private ArrayAdapter<City> cityArrayAdapter;
private ArrayList<Country> countries;
private ArrayList<State> states;
private ArrayList<City> cities;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner_country);
initializeUI();
}
private void initializeUI() {
country_Spinner = (Spinner) findViewById(R.id.SpinnerCountryActivity_country_spinner);
state_Spinner = (Spinner) findViewById(R.id.SpinnerCountryActivity_state_spinner);
city_Spinner = (Spinner) findViewById(R.id.SpinnerCountryActivity_city_spinner);
countries = new ArrayList<>();
states = new ArrayList<>();
cities = new ArrayList<>();
createLists();
countryArrayAdapter = new ArrayAdapter<Country>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, countries);
countryArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
country_Spinner.setAdapter(countryArrayAdapter);
stateArrayAdapter = new ArrayAdapter<State>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, states);
stateArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
state_Spinner.setAdapter(stateArrayAdapter);
cityArrayAdapter = new ArrayAdapter<City>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, cities);
cityArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
city_Spinner.setAdapter(cityArrayAdapter);
country_Spinner.setOnItemSelectedListener(country_listener);
state_Spinner.setOnItemSelectedListener(state_listener);
city_Spinner.setOnItemSelectedListener(city_listener);
}
private AdapterView.OnItemSelectedListener country_listener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position > 0) {
final Country country = (Country) country_Spinner.getItemAtPosition(position);
Log.d("SpinnerCountry", "onItemSelected: country: "+country.getCountryID());
ArrayList<State> tempStates = new ArrayList<>();
tempStates.add(new State(0, new Country(0, "Choose a Country"), "Choose a State"));
for (State singleState : states) {
if (singleState.getCountry().getCountryID() == country.getCountryID()) {
tempStates.add(singleState);
}
}
stateArrayAdapter = new ArrayAdapter<State>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, tempStates);
stateArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
state_Spinner.setAdapter(stateArrayAdapter);
}
cityArrayAdapter = new ArrayAdapter<City>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, new ArrayList<City>());
cityArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
city_Spinner.setAdapter(cityArrayAdapter);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
private AdapterView.OnItemSelectedListener state_listener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position > 0) {
final State state = (State) state_Spinner.getItemAtPosition(position);
Log.d("SpinnerCountry", "onItemSelected: state: "+state.getStateID());
ArrayList<City> tempCities = new ArrayList<>();
Country country = new Country(0, "Choose a Country");
State firstState = new State(0, country, "Choose a State");
tempCities.add(new City(0, country, firstState, "Choose a City"));
for (City singleCity : cities) {
if (singleCity.getState().getStateID() == state.getStateID()) {
tempCities.add(singleCity);
}
}
cityArrayAdapter = new ArrayAdapter<City>(getApplicationContext(), R.layout.simple_spinner_dropdown_item, tempCities);
cityArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
city_Spinner.setAdapter(cityArrayAdapter);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
private AdapterView.OnItemSelectedListener city_listener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
};
private void createLists() {
Country country0 = new Country(0, "Choose a Country");
Country country1 = new Country(1, "Country1");
Country country2 = new Country(2, "Country2");
countries.add(new Country(0, "Choose a Country"));
countries.add(new Country(1, "Country1"));
countries.add(new Country(2, "Country2"));
State state0 = new State(0, country0, "Choose a Country");
State state1 = new State(1, country1, "state1");
State state2 = new State(2, country1, "state2");
State state3 = new State(3, country2, "state3");
State state4 = new State(4, country2, "state4");
states.add(state0);
states.add(state1);
states.add(state2);
states.add(state3);
states.add(state4);
cities.add(new City(0, country0, state0, "Choose a City"));
cities.add(new City(1, country1, state1, "City1"));
cities.add(new City(2, country1, state1, "City2"));
cities.add(new City(3, country1, state2, "City3"));
cities.add(new City(4, country2, state2, "City4"));
cities.add(new City(5, country2, state3, "City5"));
cities.add(new City(6, country2, state3, "City6"));
cities.add(new City(7, country2, state4, "City7"));
cities.add(new City(8, country1, state4, "City8"));
}
private class Country implements Comparable<Country> {
private int countryID;
private String countryName;
public Country(int countryID, String countryName) {
this.countryID = countryID;
this.countryName = countryName;
}
public int getCountryID() {
return countryID;
}
public String getCountryName() {
return countryName;
}
@Override
public String toString() {
return countryName;
}
@Override
public int compareTo(Country another) {
return this.getCountryID() - another.getCountryID();//ascending order
// return another.getCountryID()-this.getCountryID();//descending order
}
}
private class State implements Comparable<State> {
private int stateID;
private Country country;
private String stateName;
public State(int stateID, Country country, String stateName) {
this.stateID = stateID;
this.country = country;
this.stateName = stateName;
}
public int getStateID() {
return stateID;
}
public Country getCountry() {
return country;
}
public String getStateName() {
return stateName;
}
@Override
public String toString() {
return stateName;
}
@Override
public int compareTo(State another) {
return this.getStateID() - another.getStateID();//ascending order
// return another.getStateID()-this.getStateID();//descending order
}
}
private class City implements Comparable<City> {
private int cityID;
private Country country;
private State state;
private String cityName;
public City(int cityID, Country country, State state, String cityName) {
this.cityID = cityID;
this.country = country;
this.state = state;
this.cityName = cityName;
}
public int getCityID() {
return cityID;
}
public Country getCountry() {
return country;
}
public State getState() {
return state;
}
public String getCityName() {
return cityName;
}
@Override
public String toString() {
return cityName;
}
@Override
public int compareTo(City another) {
return this.cityID - another.getCityID();//ascending order
// return another.getCityID() - this.cityID;//descending order
}
}
}
This code uses three Data Model classes Country
, State
and City
all of them implement Comparable<T>
so that their instance can be sorted with respect to their ids in a List
, You may want to use Comprator<T>
here to sort by the alphabetical order.
I have used AdapterView.OnItemSelectedListener
to track the changes in the Spinner
widget that subsequent spinner adapter can be changed.
I have added some test data to demonstrate how code works
Country Country1 Country2
______|_____ _____|_________
| | | |
State state1 state2 state3 state4
__|___ ___|___ __|___ __|____
| | | | | | | |
City city1 city2 city3 city4 city5 city6 city7 city8
Try this way it will work
string.xml
<resources>
<string name="app_name">Spinner</string>
<string name="hello_world">Hello world!</string>
<string name="title_activity_main">MainActivity</string>
<string-array name="country_array">
<item>India</item>
<item>Pakisthan</item>
<item>Sri Lanka</item>
</string-array>
<string-array name="city_india">
<item>Mumbai</item>
<item>Chennai</item>
<item>Kolkata</item>
<item>Bangalore</item>
</string-array>
<string-array name="city_pakisthan">
<item>Karachi</item>
<item>Lahore</item>
<item>Faisalabad</item>
<item>Rawalpindi</item>
</string-array>
<string-array name="city_srilanka">
<item>Colombo</item>
<item>Dehiwala-Mount Lavinia</item>
<item>Moratuwa</item>
<item>Kotte</item>
</string-array>
</resources>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="left" >
<TextView
android:id="@+id/textView"
android:layout_width="130dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:gravity="center"
android:text="Select County and City"
android:textSize="15dp"
/>
<Spinner
android:id="@+id/spinnerCountry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="28dp"
android:entries="@array/country_array" />
<Spinner
android:id="@+id/spinnerCity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/spinnerCountry"
android:layout_below="@+id/spinnerCountry"
android:layout_marginTop="42dp"
android:entries="@array/city_india" />
</RelativeLayout>
MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
public class MainActivity extends Activity implements OnItemSelectedListener {
Spinner spinnerCountry, spinnerCity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinnerCountry = (Spinner) findViewById(R.id.spinnerCountry);
spinnerCity = (Spinner) findViewById(R.id.spinnerCity);
spinnerCountry.setOnItemSelectedListener(this);
}
@Override
public void onItemSelected(AdapterView<?> parent, View arg1, int pos,
long arg3) {
parent.getItemAtPosition(pos);
if (pos == 0) {
ArrayAdapter<CharSequence> adapter = ArrayAdapter
.createFromResource(this, R.array.city_india,
android.R.layout.simple_spinner_item);
spinnerCity.setAdapter(adapter);
} else if (pos == 1) {
ArrayAdapter<CharSequence> adapter = ArrayAdapter
.createFromResource(this, R.array.city_pakisthan,
android.R.layout.simple_spinner_item);
spinnerCity.setAdapter(adapter);
} else if (pos == 2) {
ArrayAdapter<CharSequence> adapter = ArrayAdapter
.createFromResource(this, R.array.city_srilanka,
android.R.layout.simple_spinner_item);
spinnerCity.setAdapter(adapter);
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
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