views:

70

answers:

2

Hi,

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.

A: 

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
}
Pentium10
Hej,Thanks! Just for clarification though, do you mean to implement one single listener for all three Spinners, only testing inside the listener to see which Spinner it came from?
Adrian Cachinero Vasiljević
I'm terribly sorry, would you greatly mind explaining in a shade more detail how you would implement this? I'm quite lost.Thanks once again!
Adrian Cachinero Vasiljević
Yeah you need one listener for all three spinners.
Pentium10
Thanks, I would just appreciate a further pointer on how exactly to use the view parameter to pull which Spinner sent the event, if you don't mind!Cheers.
Adrian Cachinero Vasiljević
See my edit to the question.
Pentium10
Ahaa I understand what you mean now, thanks a lot, I'll give it a shot!
Adrian Cachinero Vasiljević
hmm, although just a quick conceptual question: surely if I create spinners 1, 2 and 3 in the Activity class, they still won't be encapsulated within the OnMyItemSelectedListener class? so 'this' won't resolve to anything?Have yet to get back home to try.
Adrian Cachinero Vasiljević
if that is a private class, it will allow access to the parent class's fields. Eventually try the longer naming form `MyActivityName.this.spinner1`
Pentium10
Brilliant, thanks!You've also cleared up an encapsulation question I had nagging at the back of my head.
Adrian Cachinero Vasiljević
A: 

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 !

sami boussacsou