简体   繁体   English

国家、州和城市微调器无法正常工作

[英]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:表格代码:

fragment_register.xml fragment_register.xml

<?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.我没有将它们包含在上面的代码中,因为它会变得太长。

RegisterFragement.java注册片段.java

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数据, OkHttpGSONapache-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.此代码使用三个数据模型类CountryStateCity ,它们都实现了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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM