[英]Country, state and city spinner not working correctly
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;上面的代码有更多的小部件,您可能会在 java 文件中找到它们; 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.有一个 PHP API,它根据 url 返回 Country、State 或 City 的 json。 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
例如:
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.在onItemSelected 中,我试图相对于前一个微调器动态设置微调器。 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-else块进行检查; 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.
if 条件检查是否选择了奥地利(列表中的国家之一;随机选择)然后设置状态微调器否则也设置状态微调器。 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.为了向 API 指定正在选择哪个国家/地区,我使用了 itemId,其中包含国家/地区微调器中所选项目的 Id。
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 .然后,当我拥有 Id 时,我调用getData方法,该方法设置结果ArraryList 并将其分配给微调器状态。
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 ):上面的代码使应用程序在运行时崩溃并出现以下错误(我认为只有其中一部分可能有用,完整的 Logcat 文件在这里:链接):
--------- 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)
--------- 崩溃开始 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"
抛出 OutOfMemoryError“无法分配 1667853436 字节的分配,其中有 777786 个可用字节和 381MB,直到 OOM”
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城市
spinner
适配器根据州spinner
适配器的不同而变化
State spinner
adapter change depending on Country spinner
adapter,状态
spinner
适配器根据国家/地区spinner
适配器而变化,
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代码也可以在Github 上找到,另一个例子可以帮助你从它使用的网络下载
JSON
数据, OkHttp
, GSON
和apache-common-io
, 代码
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.此代码使用三个数据模型类
Country
、 State
和City
,它们都实现了Comparable<T>
以便它们的实例可以根据它们在List
的 id 进行排序,您可能希望在此处使用Comprator<T>
进行排序按字母顺序。
I have used AdapterView.OnItemSelectedListener
to track the changes in the Spinner
widget that subsequent spinner adapter can be changed.我已经使用
AdapterView.OnItemSelectedListener
来跟踪可以更改后续微调适配器的Spinner
小部件中的更改。
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字符串.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活动_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主活动.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) {
}
}
I had what might be a similar issue, the cause, was that onItemSelected, is called when the spinner is created without it being user selected.我遇到了可能类似的问题,原因是 onItemSelected 在创建微调器时被调用,而没有被用户选择。 The cure was to add the listener via a runnable on the spinner's post event.
解决方法是通过 Spinner 的 post 事件上的 runnable 添加侦听器。 Here's an example :-
这是一个例子:-
// Set Spinner's onItemSelectedListener ie to act when a shop is selected.
// Note!!! run on post, as a runnable, so that initial onItemSelected event
// (at initialisation) is not captured
current_shoplistspinner.post(new Runnable() {
@Override
public void run() {
current_shoplistspinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
currentshoplistcursor.moveToPosition(position);
currentshopid = currentshoplistcursor.getLong(ShopperDBHelper.SHOPS_COLUMNN_ID_INDEX);
Log.d(Constants.LOG,"ACTIVITY: " + THIS_ACTIVITY + " SECTION: Running - SHOPLIST OnItemSelectedLIstener" +
"- SHOPID Extracted=" + currentshopid);
currentaislelistcursor = shopperdb.getAislesPerShopAsCursor(currentshopid);
current_aislelistspinneradapter.swapCursor(currentaislelistcursor);
// if no aisles for this shop then don't show any products
// TODO dialog to allow Aisle Add
Log.d(Constants.LOG,"ACTIVITY: " + THIS_ACTIVITY + " SECTION: Running - SHOPLIST OnItemSelectedListener" +
"- NEW AISLE COUNT=" + currentaislelistcursor.getCount());
if(currentaislelistcursor.getCount() < 1) {
currentproductlistcursor = shopperdb.getNoProductsAsCursor();
current_productlistspinneradapter.swapCursor(currentproductlistcursor);
// Also need to clear products per aisle as no ailse so no products
// So use -1 as the aisleid when getting new cursor
currentproductsperaisleecursor = shopperdb.getProductsperAisle(-1);
current_productsperaislecursoradapter.swapCursor(currentproductsperaisleecursor);
// Disable the ADD button as cannot add if no aisle or prodcuts
findViewById(R.id.productusageedit_add).setVisibility(View.INVISIBLE);
} else {
currentproductlistcursor = shopperdb.getProductsAsCursor();
current_productlistspinneradapter.swapCursor(currentproductlistcursor);
findViewById(R.id.productusageedit_add).setVisibility(View.VISIBLE);
//Note!! as aislelist spinner has a new selecteditem it's listener will
//handle products per aisle refresh (unlike if no aisle)
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
});
By coincidence that came from a 3 spinner (Shops, Aisle and products).巧合的是来自 3 纺纱厂(商店、过道和产品)。 Which would be similar.
这将是相似的。 Note this is just one of the three.
请注意,这只是三者之一。 The logic I used is if shop changes (ie onItemSelected) then change the aisle (no need to change shop list as all shops are in the list), which will then cause the products to be changed.
我使用的逻辑是,如果商店发生变化(即onItemSelected),则更改过道(无需更改商店列表,因为所有商店都在列表中),这将导致产品发生变化。 If aisle changes then changed the products.
如果过道发生变化,则更改产品。
In your MainActivity.java file, You need to make changes under onItemSelected method, On Country Selection need to get country_id to retrieve state name of the country.在 MainActivity.java 文件中,您需要在 onItemSelected 方法下进行更改,On Country Selection 需要获取 country_id 以检索国家/地区的州名。 On Sate change get state_id to retrieve city names of the state as i considered all these details are stored in MySQL in three tables and related using their ids.[I have used volley android library to retrieve data from Remote or local database and store into Array as you have used in your code]
在 Sate 更改获取 state_id 以检索州的城市名称,因为我认为所有这些详细信息都存储在 MySQL 中的三个表中并使用它们的 id 相关。[我使用 volley android 库从远程或本地数据库中检索数据并存储到数组中正如您在代码中使用的那样]
I have developed a simple program that would help you to solve your problem, I have written a simple code using ArrayAdapter and ArrayList to store Country, State, and City.我开发了一个简单的程序来帮助您解决问题,我编写了一个简单的代码,使用 ArrayAdapter 和 ArrayList 来存储 Country、State 和 City。 where you are also using same in your code.
您也在代码中使用相同的地方。 you can change provided solution as it fits your needs.
您可以根据需要更改提供的解决方案。
The Full Fledged Code along with deployment Guideline can be found on Github可以在Github上找到完整的代码和部署指南
You can view this Output Screen that depicts how Country , State and City will appear您可以查看此输出屏幕,其中描述了 Country 、 State 和 City 的显示方式
//Checkout Below code //结帐下面的代码
public class MainActivity extends AppCompatActivity{
//Spinner to hold Country, State/Province, City
private Spinner mSpinCountry,mSpinState,mSpinCity;
// To hold country response from getCountry.php API
private JSONArray countryResult;
// To hold state response from getState.php API
private JSONArray stateResult;
// To hold city response from getCity.php API
private JSONArray cityResult;
//To hold all country
private ArrayList<String> countryArrayList;
//To hold all state of the country
private ArrayList<String> stateArrayList;
//To hold all scity of the state
private ArrayList<String> cityArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initialize country, state and city spinner
mSpinCountry=(Spinner)findViewById(R.id.spinCountry);
mSpinState=(Spinner)findViewById(R.id.spinState);
mSpinCity=(Spinner)findViewById(R.id.spinCity);
//Initialize Country Array List
countryArrayList = new ArrayList<String>();
//Fetch all Country
getCountry();
//On Country Change, Change List of State of the country
mSpinCountry.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
//fetch Country_ID of the selected country to fetch list of states
getCountryId(position);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
mSpinState.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
//fetch State_ID of the selected country to fetch list of states
getStateId(position);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
private void getCountry() {
StringRequest stringRequest = new StringRequest(BASE_URL+"getCountry.php",
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject j = null;
try {
j = new JSONObject(response);
countryResult = j.getJSONArray("result");
//Fetch Country List
countryDetails(countryResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplication(), ""+error,Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void countryDetails(JSONArray result) {
for (int i = 0; i < result.length(); i++) {
try {
JSONObject json = result.getJSONObject(i);
countryArrayList.add(json.getString(countryArray));
} catch (JSONException e) {
e.printStackTrace();
}
}
mSpinCountry.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, countryArrayList));
}
private void getCountryId(int position) {
String country_id="";
try {
//Getting object of given index
JSONObject json = countryResult.getJSONObject(position);
//Fetching name from that object
country_id= json.getString("country_id");
getState(country_id);
} catch (JSONException e) {
e.printStackTrace();
}
}
private void getState(String country_id) {
StringRequest stringRequest = new StringRequest(BASE_URL+"getState.php/?country_id="+country_id,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject j = null;
try {
j = new JSONObject(response);
stateResult = j.getJSONArray("result");
stateDetails(stateResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplication(), ""+error,Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void stateDetails(JSONArray result) {
//Create stateArrayList object here, because after each change of country state must be added (NOT Appended)
stateArrayList=new ArrayList<String>();
for (int i = 0; i < result.length(); i++) {
try {
JSONObject json = result.getJSONObject(i);
stateArrayList.add(json.getString(stateArray));
} catch (JSONException e) {
e.printStackTrace();
}
}
// stateArrayList.add(0,"Select State");
mSpinState.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, stateArrayList));
}
private void getStateId(int position) {
String state_id="";
try {
//Getting object of given index
JSONObject json = stateResult.getJSONObject(position);
//Fetching name from that object
state_id= json.getString("state_id");
getCity(state_id);
} catch (JSONException e) {
e.printStackTrace();
}
}
private void getCity(String state_id) {
StringRequest stringRequest = new StringRequest(BASE_URL+"getCity.php/?state_id="+state_id,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject j = null;
try {
j = new JSONObject(response);
cityResult = j.getJSONArray("result");
cityDetails(cityResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplication(), ""+error,Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void cityDetails(JSONArray cityResult) {
//Create cityArrayList object here, because after each change of state city must be added (NOT Appended)
cityArrayList=new ArrayList<String>();
for (int i = 0; i < cityResult.length(); i++) {
try {
JSONObject json = cityResult.getJSONObject(i);
cityArrayList.add(json.getString(cityArray));
} catch (JSONException e) {
e.printStackTrace();
}
}
mSpinCity.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, cityArrayList));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.