Enable a currently disabled Spinner in Android - java

I was fooling around with Android and my Java knowledge is limited at best (for instance, I'm perplexed by the fact that it allows inline classes!?).
My question is as follows:
I have a layout where there are three dropdown menus. I initialise all three of them inside onCreate().
The first one takes its values from a string-array. The second one, however, depends on the choice of the first one and the third one depends on the choice of the second one in turn!
I have a few string-arrays for the second Spinner but I was wondering what would be the correct way to implement a list of successively enabled Spinners. I'm tempted to just hack into it and make it work but I don't want to run the risk of it being malformed and unstable.
So for example's sakes, my case is as if I had the Google Spinner tutorial with an extra Spinner for the moons of each planet (and then maybe for craters on each of the moons).
In my resources, I have an arrays.xml such as:
<resources>
<string-array name="planets">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
<item>Jupiter</item>
<item>Saturn</item>
<item>Uranus</item>
<item>Neptune</item>
</string-array>
<string-array name="earth">
<item>The Moon</item>
</string-array>
<string-array name="mars">
<item>Deimos</item>
<item>Phobos</item>
</string-array>
<string-array name="jupiter">
<item>Metis</item>
<item>Adrasthea</item>
<item>Amalthea</item>
<item>Thebe</item>
<item>Io</item>
<item>Europa</item>
<item>Ganymede</item>
<item>Callisto</item>
[...] etc. etc.
</resources>
In the onCreate method I initialise all three:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner spinner1 = (Spinner) findViewById(R.id.planetSpinner);
Spinner spinner2 = (Spinner) findViewById(R.id.moonSpinner);
Spinner spinner3 = (Spinner) findViewById(R.id.craterSpinner);
spinner2.setEnabled(false);
spinner3.setEnabled(false);
ArrayAdapter adapter1 = ArrayAdapter.createFromResource(
this, R.array.planets, android.R.layout.simple_spinner_item);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(adapter1);
spinner1.setOnItemSelectedListener(new MyOnPlanetSelectedListener());
}
My listener class is
public class MyOnPlanetSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
Toast.makeText(parent.getContext()), "The planet is " +
parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
So there it is. My question is where and how to implement the listeners for the successive Spinners so that they're enabled once the first one is selected. My first guess is:
public class MyOnPlanetSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
Toast.makeText(parent.getContext()), "The planet is " +
parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
spinner2.setEnabled(true);
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
But obviously this is wrong since spinner2 is not encapsulated here.
Then, the successive spinners should pick a string-array for their adapters depending on what the choice of the Spinners before it are. I tried encapsulating the spinners in the activity class, in the constructor, but the application crashes before running.
Thank you very much in advance for your help.

Use the view parameter of onItemSelected to decide which Spinner sent the onItemSelected event. From this doing the logic is simple.
Make spinner1 2 and 3 member of the class (activity)
private Spinner spinner1;
Then simply compare the view param against
if (view==this.spinner1) {
// event came from spinner 1
// create a new adapter, assign the new adapter to spinner 2
} else if (view==this.spinner2) {
// event came from spinner 2
}

Try to use this :
switch(parent.getId())
{
case R.id.spinner1:
Log.d(TAG,"spinner1");
break;
case R.id.spinner2:
Log.d(TAG,"spinner2");
break;
}
good luck !

Related

Android, spinner item disappeared after clicking on other spinner

Scenario: Let's say there are 2 spinner in the fragment called spinner a and b:
Spinner a contain: dog cat elephant
Spinner b contain: micky, minny, moe
My question is: Is it possible that when user using apps, and clicked Spinner a, and choose elephant, the micky and minny option in Spinner b option be gone and only leaving moe as an option?
And what is the best way to do it? (not using any database)
xml:
<Spinner
android:id="#+id/spinner_a"
android:entries="#array/value_a"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Spinner
android:id="#+id/spinner_b"
android:entries="#array/value_b"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
string value:
<resources>
<string-array name="value_a">
<item>dog</item>
<item>cat</item>
<item>Elephant</item>
</string-array>
<string-array name="value_b">
<item>micky</item>
<item>minny</item>
<item>moe</item>
</string-array>
java:
package...
import....
public class testing123 extends Fragment{
final Spinner a123 = (Spinner) getView().findViewById(R.id.spinner_a);
final Spinner b123 = (Spinner) getView().findViewById(R.id.spinner_b);
final String ax = a123.getSelectedItem().toString();
final String bx = b123.getSelectedItem().toString();
if (ax.equals("elephant")) {
//what is the best way to do it?
}else{}
}
Yes you can but not with your way.
For spinner a it's ok, but for b you should manage it dinamically from Java code.
Add to spinner A a listener and modify string-array of spinner b based on item a selected.
Listener:
Spinner spinner_a = (Spinner) findViewById(R.id.spinner_a);
spinner_a.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// retrieve selected item
String spinner_a_choice = parent.getItemAtPosition(position).toString();
// elaborate and set here your spinner b with its own adapter
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// Something else
}
});
How to add an adapter to spinner (you have to manipulate it):
Spinner spinner_b = (Spinner) findViewById(R.id.spinner_b);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.value_b, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_b.setAdapter(adapter);

Java If Statements/Spinner

I'm working on an Activity where I need to start a new Activity at the click of a button based on the selected item in a spinner. I can't quite figure it out. This is what I have after clearing failed attempts.
spinner = (Spinner)findViewById(R.id.spinner);
adapter = ArrayAdapter.createFromResource(this, R.array.user_type, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(spinner.equals("My String Here")){
startActivity(new Intent(Register.this, *****.class));
}else{
startActivity(new Intent(Register.this, *****.class));
}}
Am I better off just installing two buttons with their own proper syntax starting new activities separately?
If spinner.equals does not make any sense at all.
You should use position integer value to check your array data and then make a decision based on that value
First things first.
spinner.equals("My String Here")
spinner is of type Spinner whereas "My String Here" is a String. You are always sure that they will never be equated the same.
Next, try to make use of your position and adapter to be able to properly construct your condition.

Android Studio gridView

Is it possible to have methods and actual coding inside each item for a GridView?
The app that I am attempting to create is a currency converter, and I am currently displaying 3 images in the gridView: Euros, Pesos, and Rupees.
Once the user clicks on one, I want the open to open up a new XML which displays a textView. The user enters the value of US dollars in the textView and clicks the compute button. The app then displays the converted amount in the bottom of the screen.
The problem is that I am unable to figure out how to open up a new XML every time a picture is clicked on in the gridView. Assuming that I am able to do this, I am also unsure of where to place the code that goes behind the conversions. Would I make a new .java or just place is all in MainActivity.java?
Thanks.
What you might be best doing is when the user clicks on a currency it takes them to another activity where you would then load another xml for whatever you want to show.
In order to detect which item had been clicked you can implement an onItemClickListener for example
gridView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//this assumes you give the gridview a list of currency which it then displays. Here we get the currency selected to then pass to our new activity
String selectedCurrency = myArrayOfCurrencies.get(position);
//then start new activity and give it the currency. This means we won't have to create an activity for each currency. You just need to create 1 and then based on what currency you give it will change the functionality
Intent intent = new Intent(this, Converter.class);
Intent.putExtra("currency", selectedCurrency);
startActivity(intent);
}
First you should be able to detect the clicks on each item of the GridView by calling the setOnItemClickListener() method.
If you set the clicklistener and you still can't detect the clicks, then most probably you need to add those attribtutes to your imageView in the xml
android:focusable="false"
android:focusableInTouchMode="false"
Second, once you are able to detect the clicks you can start new activity or add fragment that contains that edit text that will promote the user to enter the value.
Third, I would suggest to put the code responsible for the currency conversion in a class separately and create static methods that takes a value and convert it to the other curreny such as:
public class CurrencyConverter {
public static double convertToRupees (String currencyType, double currencyValue){
....
return currencyInRupees;
}
}
and by the way I would suggest you to use RecyclerView with grid layout manager instead of GridView.
I would create more classes.
You asked how to open a different XML file for each gridView item.
Create a custom adapter that extends BaseAdapter.
Override getView and for each view attach the right Xml file, according to the position.
For example:
YourActivity.java:
GridView gridView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
gridView = (GridView) findViewById(R.id.gridView);
gridView.setAdapter(new MyAdapter(getApplicationContext());
}
MyAdapter.java:
...
#Override
public int getCount() {
return XmlArr.length;
}
#Override
public Object getItem(int position) {
return XmlArr[position];
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Xml myXml = (Xml) getItem(position);
Holder holder;
if (convertView == null) {
// Set your view's layout. Consider using LayoutInflater.
// Use a static holder to prevent re-initialization:
holder = new Holder();
// holder.textView = ...
// holder.Xml = ...
// Or whatever you decided to have in each gridView item.
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.Xml = myXml;
...
return convertView;
}
static class Holder() {
TextView tv;
Xml xml;
...
}
I assumed you would used an Xml array (xmlArr).
Now you have option to play with each gridView item as you wish. You can set each view/button/textView an onItemClickListener, or you can also set the whole gridView an onItemClickListener (from YourActivity.java).
Hope this helps.

'Proper' Android Development Syntax

I am not entirely sure this is the right SE to ask this on but I am wondering if this is expected when developing for android. I am ending up with a larger containing class and then a significant amount of nested/newed anonymous classes for callbacks within callbacks. I am wondering if this is expected or if there is a better way of doing this as the amount of nested classes is starting to lead to very convoluted code.
This is just a dialog fragment that has some settings on it. When you click on a setting it populates a list view with the appropriate options and when you select an option it updates the value that you clicked on. It is a DialogFragment with a nested anonymous OnClickListener() that then assigns a nested anonymous OnItemClickListener() to a ListView type of object. This allows me to use the ListView object for multiple settings with having to duplicate the ListView for each one of them (I just bind a new adapter and OnItemClickListener to it).
class MyDialogFragment extends DialogFragment
{
protected View _root;
protected ListView _listViewSomeSettingOptions;
protected TextView _textViewSomeSetting;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
_root = inflater.inflate(R.layout.layout_for_dialog, container, false);
_listViewSomeSettingOptions = (ListView)_root.FindViewById(R.id.listViewSettingOptions);
_textViewSomeSetting.setOnClickListener(new OnClickListener()
{
protected ArrayList<String> _someSettingOptions = new ArrayList<String>();
// Fill _someSettingOptions with a list of options
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, _someSettingOptions);
_listViewSomeSettingOptions.setAdapter(adapter);
_listViewSomeSettingOptions.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
_textViewSomeSetting.setText(_someSettingOptions.get(position));
}
}
}
}
}
Is this just how it goes? Should I be making custom controls that implement the listeners instead of using the anonymous ones? This DialogFragment is approaching 1000 lines all in onCreateView now handling the different options and display updates of a user tweaking the setting options and its just tingling my "Maybe this is not the best design" sense. I guess besides Upkeep I am wondering if there is a drawback to this form of development.

How to make a spinner populate another spinner?

How would you go about making a spinner populate another spinner based on the first spinners selection?
So for example:
Spinner1 items are vegetarian or meat eater.
<string-array name="spinnerarray_veg_meat">
<item >Vegetarian</item>
<item >Meat eater</item>
</string-array>
Spinner2 would then need to display either vegetarian meal names or meat eater ones depending on spinner1's selection.
To do this you'll have to set a OnItemSelectedListener on your first Spinner to populate the second Spinner programmatically.
spinner1.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
if(position == 0) {
// Populate the Spinner2 with different values
} else {
// Populate the Spinner2 with different values
}
}
public void onNothingSelected(AdapterView<?> parent) {
return;
}
});
There are a number of ways to do it. One being, create an Array of meat items and one of vegetable items. In onItemSelected() of spinner1 set the adapter for spinner2 according to the position
Spinner Docs
This link has many useful functions and properties available to Spinners

Categories