【问题标题】:Country, state and city spinner not working correctly国家、州和城市微调器无法正常工作
【发布时间】:2016-08-04 20:26:10
【问题描述】:

我一直在开发一个注册表单应用程序,其中使用了一些微调器小部件。微调器用于选择 Country、State 和 City。因此,这些微调器需要以某种方式相互连接(下面的代码将显示我是如何尝试实现的)。

表格代码:

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>

上面的代码有更多的小部件,您可以在 java 文件中找到它们;我没有将它们包含在上面的代码中,因为它会太长。

RegisterFragement.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));
    }


}
}

有一个 PHP API 可以根据 url 返回 Country、State 或 City 的 json。例如: 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

在 onItemSelected 中,我正在尝试相对于前一个微调器动态设置微调器。对于EX。,我在选择国家/地区旋转器项时设置状态旋转器。我正在通过 if-else 块检查这一点; if 条件检查是否选择了 Austria(列表中的国家之一;随机选择)然后设置 state 微调器 else 还设置 状态微调。这样我最终会根据国家微调器元素设置状态微调器。

为了向 API 指定选择哪个 country,我使用了 itemId,其中包含国家微调器中所选项目的 Id。 long itemId = country_spinner.getSelectedItemId();

然后,当我有 ID 时,我调用设置 result ArraryList 的 getData 方法并将其分配给微调器 state。

getData("getStates","countryId",itemId); state_spinner.setAdapter(new ArrayAdapter<String>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, results));

上面的代码使应用程序在运行时崩溃并出现以下错误(我认为只有一部分可能有用,完整的 Logcat 文件在这里:Link):

--------- 崩溃开始 04-13 21:05:09.782 9288-9600/com.gouravchawla.loginregistration E/AndroidRuntime: FATAL 例外:线程 503 进程:com.gouravchawla.loginregistration,PID:9288 java.lang.NegativeArraySizeException:-110 在 com.android.volley.toolbox.DiskBasedCache.streamToBytes(DiskBasedCache.java:316) 在 com.android.volley.toolbox.DiskBasedCache.get(DiskBasedCache.java:117) 在 com.android.volley.CacheDispatcher.run(CacheDispatcher.java:101)

抛出 OutOfMemoryError "未能分配 1667853436 字节 分配 777786 个空闲字节和 381MB 直到 OOM"

【问题讨论】:

    标签: java android android-studio android-volley android-spinner


    【解决方案1】:

    在您的代码中,您必须更改例如依赖于其他微调器的微调器的适配器。

    城市spinner 适配器根据州spinner 适配器变化

    Statespinner 适配器根据 Countryspinner 适配器变化,

    我编写了一个示例代码来演示如何实现这一点,我编写了一个通用代码,其他人在阅读答案时可以理解,请随意提出建议并根据您的要求进行更改。

    代码也可在Github 上找到,另一个示例可帮助您从其使用的网络下载JSON 数据,OkHttp、GSON 和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
            }
        }
    }
    

    此代码使用三个数据模型类Country、State 和City,它们都实现了Comparable&lt;T&gt;,以便可以根据List 中的ID 对它们的实例进行排序,您可能想要在此处使用Comprator&lt;T&gt; 按字母顺序排序。

    我已经使用AdapterView.OnItemSelectedListener 来跟踪Spinner 小部件中的更改,以便可以更改后续微调器适配器。

    我添加了一些测试数据来演示代码的工作原理

    Country              Country1                   Country2  
                      ______|_____                 _____|_________
                      |           |               |               |
    State          state1       state2         state3          state4
                   __|___       ___|___        __|___          __|____
                   |    |       |     |        |    |          |     |
    City        city1 city2   city3 city4   city5 city6      city7 city8 
    

    【讨论】:

    • 首先,感谢@pankaj-nimgade。其次,我尝试了它并没有得到我希望得到的结果。在这里,您正在使用我不需要的数据模型类。如果您使用它们只是为了对事物进行分类,那么我可以取消它。此外,这是我的第一个应用程序,我的 java/android 经验很少,所以希望尽可能简单。另外,您能否告诉我如何使用 volley 获取数据并使用该数据动态填充微调器,因为我认为这是导致问题的原因。 API
    • github.com/pankajnimgade/Tutorial/blob/master/app/src/main/java/… .. 在此示例中查看代码,此示例使用 OkHttp 和 GSON 填充 Spinner 中的数据,我还包含了您可以使用基本 AsyncTask 的代码。抱歉,我不使用 Volley,@GouravChawla
    • 我认为我的问题在我上面的评论中消失了。我的意思是问题是从 api 获取州和城市微调器中的数据(用法如下)。当用户选择印度时,它应该调用 api 并填充状态微调器,然后在选择状态后,例如德里,然后它应该再次调用 api 并填充城市微调器。 http://leansigmaway.com/api/ca_api/api.php?type=getCountries http://leansigmaway.com/api/ca_api/api.php?type=getStates&amp;countryId=101 http://leansigmaway.com/api/ca_api/api.php?type=getCities&amp;stateId=10
    • @GouravChawla,整个代码都在那里,你正在寻找什么,这两个链接包含从服务器中提取数据并填充微调器的信息,以及更改微调器状态的信息父微调器改变它的状态
    • 非常感谢!你是个救世主。我自己是想不通的。
    【解决方案2】:

    试试这个方法就行了

    字符串.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) {
    
         }
    
        }
    

    【讨论】:

    • 我遇到过这种方法;我唯一不明白的是我有 20 多个国家。并且为每个国家/地区编写 if else 条件是没有意义的。正如我提到的,我的数据来自数据库,所以不能在 string.xml 文件中对其进行硬编码,可以吗?
    • 更好地创建网络服务
    【解决方案3】:

    我遇到了类似的问题,原因是 onItemSelected 在创建微调器时被调用,而没有用户选择。解决方法是通过微调器的 post 事件上的可运行对象添加侦听器。这是一个例子:-

            // 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) {
                        }
                    });
                }
            });
    

    巧合的是,来自 3 个微调器(商店、过道和产品)。这将是相似的。请注意,这只是三者之一。我使用的逻辑是如果商店更改(即onItemSelected)然后更改过道(无需更改商店列表,因为所有商店都在列表中),这将导致产品发生变化。如果过道发生变化,则更改产品。

    【讨论】:

    • 我是安卓编程新手;你能告诉我我应该把可运行文件放在我发布的代码中吗?上面代码的唯一区别是现在我有三个监听器;一个用于country_spinner、state_spinner 和city_spinner。 @MikeT
    • 代码 (yourview.post ........) 进入您当前拥有onItemSelected 的活动中。请注意,代码还包含setOnItemSelectedListener,因此您将删除当前设置侦听器的相应代码。
    • 非常感谢,迈克!在构建应用程序时,您对 runnable 的评论和建议非常有用。
    【解决方案4】:

    在您的 MainActivity.java 文件中,您需要在 onItemSelected 方法下进行更改,On Country Selection 需要获取 country_id 以检索国家/地区的州名。在 Sate 更改获取 state_id 以检索该州的城市名称,因为我认为所有这些详细信息都存储在 MySQL 中的三个表中,并使用它们的 id 关联。[我使用 volley android 库从远程或本地数据库中检索数据并存储到数组中正如您在代码中使用的那样]

    我开发了一个简单的程序来帮助您解决问题,我编写了一个简单的代码,使用 ArrayAdapter 和 ArrayList 来存储 Country、State 和 City。您在代码中也使用相同的地方。您可以根据需要更改提供的解决方案。

    完整的代码和部署指南可以在Github找到

    You can view this Output Screen that depicts how Country , State and City will appear

    //检查下面的代码

    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));
    
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-20
      • 2011-01-14
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 2017-11-11
      • 2019-02-15
      • 1970-01-01
      • 2011-01-07
      相关资源
      最近更新 更多