Autore Topic: 3 spinner collegati tra loro popolati da database Sqlite  (Letto 1362 volte)

Offline guidocx84

  • Utente junior
  • **
  • Post: 68
  • Respect: 0
    • Mostra profilo
3 spinner collegati tra loro popolati da database Sqlite
« il: 05 Giugno 2013, 13:00:29 CEST »
0
Ciao a tutti ragazzi!
Avrei bisogno del vostro aiuto perché non so da dove rifarmi. Ho lavorato in passato con gli Spinner ne avevo due, non connessi tra loro, e con 10 righe ciascuno... quindi niente di troppo complicato...
Adesso invece ho un database sqlite con dentro le tre tipiche tabelle regioni/province/comuni e devo creare 3 spinner che peschino da queste tabelle tutti i valori in relazione alla scelta precedente dell'utente.
Quindi l'utente inizia selezionando la regione e nello spinner sottostante devono essere inserire soltanto le province della regione selezionata. Analogamente per i comuni. Dovranno essere mostrati solo quelli della provincia selezionata.
Inoltre, una volta popolati, devo prevedere una prima voce di default (es. "Scegli la regione" oppure "Scegli la provincia" oppure "Scegli il comune") e un button che, a seconda di cosa sceglie l'utente, lo porti in una Activity ListView successiva in cui esso possa vedere tutte le strutture afferenti alle scelte fatte nello spinner. La scelta di province e comuni deve essere opzionale. La scelta della regione obbligatoria. Ogni struttura che deve essere mostrata nella ListView ovviamente ha una tabella posizioni associata in cui sono riportati gli id di regione, provincia e città.
Come posso fare?? Potete darmi qualche spunto per favore? Grazie mille!  ;-)

Offline NanoAndroide

  • Utente junior
  • **
  • Post: 63
  • Respect: +3
    • Google+
    • Mostra profilo
    • MeToo
  • Dispositivo Android:
    GT-S5570
  • Play Store ID:
    MeToo
  • Sistema operativo:
    Windows 7
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #1 il: 05 Giugno 2013, 18:46:03 CEST »
0
Prova a dare un'occhiata a questo esempio:

Android Populating Spinner data from SQLite Database

In particolare, il metodo loadSpinnerData() dovrebbe essere più o meno quel che cerchi...  ;-)

Offline guidocx84

  • Utente junior
  • **
  • Post: 68
  • Respect: 0
    • Mostra profilo
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #2 il: 05 Giugno 2013, 19:14:40 CEST »
0
Ciao,
grazie per la risposta!
In realtà sono già in grado di popolare gli spinner dal Sqlite. Quello che non riesco a fare è catturare dinamicamente la selezione dell'utente nello spinner in modo da ottimizzare il popolamento degli spinner successivi.
Esempio: se l'utente seleziona la regione Toscana vorrei che il secondo spinner mostrasse le province di questa regione e, selezionata, nel terzo spinner si vedessero i comuni di questa provincia. Per fare questo devo mettere delle WHERE nelle query sql basate sugli ID (non come è implementato attualmente che seleziona tutto). Ma per prendere l'ID ho bisogno di un qualcosa di dinamico che non so come implementare. Di seguito il mio codice attuale.

Codice: [Seleziona]
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

public class myClass extends Activity {

        SQLiteDatabase mydb;
        private static String DBNAME = "miodb";
        private static String REGIONI_TABLE = Regioni.TABLE_NAME;
        private static String PROVINCE_TABLE = Province.TABLE_NAME;
        private static String COMUNI_TABLE = Comuni.TABLE_NAME;
       
        int id_regione_selezionata;
        int id_provincia_selezionata;
        int id_comune_selezionato;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_myclass);

                ArrayList<String> arrayRegioni = new ArrayList<String>();
                arrayRegioni = getTableRegioniValues();

                Spinner spinnerRegioni = (Spinner) findViewById(R.id.spinnerRegioni);
                ArrayAdapter adapterRegioni = new ArrayAdapter(this,
                                R.layout.spinner_row, arrayRegioni);
                spinnerRegioni.setAdapter(adapterRegioni);
               
                ArrayList<String> arrayProvince = new ArrayList<String>();
                arrayProvince = getTableProvinceValues();

                Spinner spinnerProvince = (Spinner) findViewById(R.id.spinnerProvince);
                ArrayAdapter adapterProvince = new ArrayAdapter(this,
                                R.layout.spinner_row, arrayProvince);
                spinnerProvince.setAdapter(adapterProvince);

        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.myclass, menu);
                return true;
        }

        // Questa funzione mostra i dati prelevati dalla tabella regioni

        public ArrayList<String> getTableRegioniValues() {

                ArrayList<String> my_array = new ArrayList<String>();

                try {
                        mydb = openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE, null);
                        Cursor allrows = mydb.rawQuery("SELECT * FROM " + REGIONI_TABLE,
                                        null);
                        System.out.println("COUNT : " + allrows.getCount());

                        if (allrows.moveToFirst()) {
                                do {
                                        String ID_REGIONE = allrows.getString(0);
                                        String NOME_REGIONE = allrows.getString(1);
                                        my_array.add(NOME_REGIONE);

                                } while (allrows.moveToNext());
                        }
                        allrows.close();
                        mydb.close();
                } catch (Exception e) {
                        Log.i("ERRORE", "Errore nel popolare lo spinner");
                }
                return my_array;
        }

        // Questa funzione mostra i dati prelevati dalla tabella province

        public ArrayList<String> getTableProvinceValues() {

                ArrayList<String> my_array = new ArrayList<String>();
                try {
                        mydb = openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE, null);
                        Cursor allrows = mydb.rawQuery("SELECT * FROM " + PROVINCE_TABLE,
                                        null);
                        System.out.println("COUNT : " + allrows.getCount());

                        if (allrows.moveToFirst()) {
                                do {
                                        String ID_PROVINCIA = allrows.getString(0);
                                        String NOME_PROVINCIA = allrows.getString(1);
                                        String ID_REGIONE = allrows.getString(2);
                                        my_array.add(NOME_PROVINCIA);

                                } while (allrows.moveToNext());
                        }
                        allrows.close();
                        mydb.close();
                } catch (Exception e) {
                        Log.i("ERRORE", "Errore nel popolare lo spinner");
                }
                return my_array;
        }

        // Questa funzione mostra i dati prelevati dalla tabella comuni

        public ArrayList<String> getTableComuniValues() {

                ArrayList<String> my_array = new ArrayList<String>();
                try {
                        mydb = openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE, null);
                        Cursor allrows = mydb.rawQuery("SELECT * FROM " + COMUNI_TABLE,
                                        null);
                        System.out.println("COUNT : " + allrows.getCount());

                        if (allrows.moveToFirst()) {
                                do {
                                        String ID_COMUNE = allrows.getString(0);
                                        String ID_PROVINCIA = allrows.getString(1);
                                        String NOME_COMUNE = allrows.getString(2);
                                        my_array.add(NOME_COMUNE);

                                } while (allrows.moveToNext());
                        }
                        allrows.close();
                        mydb.close();
                } catch (Exception e) {
                        Log.i("ERRORE", "Errore nel popolare lo spinner");
                }
                return my_array;
        }
       

}


Probabilmente devo utilizzare un Listener a quanto ho capito ma non saprei come integrarlo nella mia soluzione... e soprattutto non so se quello che ho scritto fino ad ora va bene o esiste un modo migliore per ottenere il solito risultato...

GRAZIE!  ;-)

Offline NanoAndroide

  • Utente junior
  • **
  • Post: 63
  • Respect: +3
    • Google+
    • Mostra profilo
    • MeToo
  • Dispositivo Android:
    GT-S5570
  • Play Store ID:
    MeToo
  • Sistema operativo:
    Windows 7
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #3 il: 05 Giugno 2013, 20:28:43 CEST »
0

Probabilmente devo utilizzare un Listener a quanto ho capito ma non saprei come integrarlo nella mia soluzione... e soprattutto non so se quello che ho scritto fino ad ora va bene o esiste un modo migliore per ottenere il solito risultato...

GRAZIE!  ;-)

Esattamente. Quello che ti serve è un OnItemSelectedListener(). Trovi la documentazione ufficiale qui:

AdapterView.OnItemSelectedListener | Android Developers

Qualche esempio:
android - How to get Spinner value? - Stack Overflow
android - Adding OnItemSelectedListener to Spinner - Stack Overflow
Android: two Spinner onItemSelected() - Stack Overflow

 ;-)

Offline guidocx84

  • Utente junior
  • **
  • Post: 68
  • Respect: 0
    • Mostra profilo
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #4 il: 05 Giugno 2013, 21:20:13 CEST »
0
Ok. Allora sembrerei essere sulla strada giusta... Domani allora darò un'occhiata a questi link che mi hai passato! Grazie!  ;-)
C'è una cosa però che non riesco a capire: guardando la mia implementazione, e considerato che negli spinner ovviamente metto i nomi di regione/provincia/città e non il suo id per ovvie ragioni, una volta implementato il listener come mi consigli di agire per fare in modo di modificare il contenuto degli spinner sulla base dell'id univoco e non del nome che li identifica nel database? Perché fondamentalmente è quello che mi devo portare dietro per fare poi la selezione delle strutture per posizione geografica.
Suppongo che il Listener catturi la posizione dell'elemento nello spinner che l'utente ha selezionato ma questo non coinciderà mai con l'id univoco che identifica la regione/provincia/città nel database.
Come faccio secondo te a legare gli spinner tra loro tramite gli id di regione/provincia/città pur mostrandone il loro nome?
Grazie mille per il tuo aiuto!!!  ;-)

Offline NanoAndroide

  • Utente junior
  • **
  • Post: 63
  • Respect: +3
    • Google+
    • Mostra profilo
    • MeToo
  • Dispositivo Android:
    GT-S5570
  • Play Store ID:
    MeToo
  • Sistema operativo:
    Windows 7
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #5 il: 05 Giugno 2013, 22:18:29 CEST »
0
In linea di massima, il primo spinner (diciamo regione, giusto per intenderci...  ;-) ) va popolato come già fai.

Quando l'utente seleziona una voce, entra in gioco OnItemSelectedListener(), che ti restituisce l'id della risorsa visualizzata. Dato che questa, nel tuo caso, dovrebbe corrispondere al contenuto di un array, che se ho capito bene contiene i nomi delle regioni, ripeti la query con questo nome per ottenere la lista delle province nella regione, che userai per popolare il secondo spinner.

Poi ripeti il procedimento (su selezione della provincia, ottieni la lista dei comuni) e popoli il terzo.

Scusa se sono molto sintetico, ma continua a cadermi la connessione e di solito succede mentre invio il messaggio, con conseguente riscrittura del medesimo...  :-P

Offline guidocx84

  • Utente junior
  • **
  • Post: 68
  • Respect: 0
    • Mostra profilo
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #6 il: 05 Giugno 2013, 23:22:36 CEST »
0
Vediamo se ho capito...

Citazione
Quando l'utente seleziona una voce, entra in gioco OnItemSelectedListener(), che ti restituisce l'id della risorsa visualizzata.

Per id in questo caso intendi la posizione della voce selezionata nello spinner? Cioè 0 se ha selezionato la prima voce, 1 per la seconda, ecc. giusto?

A questo punto dovrei usare questo intero per andare a prendermi la stringa dell'array corrispondente alla regione selezionata (es. array[id]) ed utilizzare il nome della regione come where per la select delle province giusto?

Quindi te diresti di eseguire le select sul database non in base agli id di regioni/province/città ma in base ai loro nomi...

Potrebbe succedere che dei comuni abbiano lo stesso nome ma comuni con lo stesso nome nella stessa provincia la vedo buia... quindi direi che si può fare... nell'ottica poi di mostrare tutte le strutture di quel comune poi però dovrò farmi qualche nuova query per immagazzinare i veri id del database.

Questo perché per ogni struttura ho un identificativo univoco. Inoltro ho una tabella posizioni in cui ho inserito identificativo della struttura e identificativi di regioni/province/città. Non i nomi. Quindi, alla fine, dovrò recuperare questi id sicuramente.

Citazione
Scusa se sono molto sintetico, ma continua a cadermi la connessione e di solito succede mentre invio il messaggio, con conseguente riscrittura del medesimo...

 :D :D :D :D Non ti preoccupare! Anzi, grazie per il tuo aiuto! Davvero! Domani provo a scrivere qualcosa e poi ti faccio sapere!

Offline NanoAndroide

  • Utente junior
  • **
  • Post: 63
  • Respect: +3
    • Google+
    • Mostra profilo
    • MeToo
  • Dispositivo Android:
    GT-S5570
  • Play Store ID:
    MeToo
  • Sistema operativo:
    Windows 7
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #7 il: 06 Giugno 2013, 01:02:13 CEST »
0
Per id in questo caso intendi la posizione della voce selezionata nello spinner? Cioè 0 se ha selezionato la prima voce, 1 per la seconda, ecc. giusto?

A questo punto dovrei usare questo intero per andare a prendermi la stringa dell'array corrispondente alla regione selezionata (es. array[id]) ed utilizzare il nome della regione come where per la select delle province giusto?

Si, ora non ricordo se è id o position ( credo la seconda...  :-P ), ma una delle due è quella che ti serve...  ;-)

Quindi te diresti di eseguire le select sul database non in base agli id di regioni/province/città ma in base ai loro nomi...

Esattamente.  :D


Offline guidocx84

  • Utente junior
  • **
  • Post: 68
  • Respect: 0
    • Mostra profilo
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #8 il: 06 Giugno 2013, 12:26:50 CEST »
0
Ciao!!! Allora... qualche aggiornamento...  :D

Grazie ai link che mi hai passato ho implementato il Listener delle regioni e funziona!!

Codice: [Seleziona]
// Spinner delle regioni

                ArrayList<String> arrayRegioni = new ArrayList<String>();
                arrayRegioni = getTableRegioniValues();

                Spinner spinnerRegioni = (Spinner) findViewById(R.id.spinnerRegioni);
                ArrayAdapter adapterRegioni = new ArrayAdapter(this,
                                R.layout.spinner_row, arrayRegioni);
                spinnerRegioni.setAdapter(adapterRegioni);
               
                // Listener delle regioni
               
                spinnerRegioni.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                        Object item = parent.getItemAtPosition(pos);
                        regione_selezionata = item.toString();
                        Log.i("REGIONE", "Hai selezionato " + regione_selezionata);
                       
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    }
                });

Dentro il Log.i che ho inserito nel listener vedo che viene riportato tutte le volte il nome della regione che ho selezionato.

Per popolare lo spinner delle province chiamo il metodo (modificato rispetto a ieri)

Codice: [Seleziona]
public ArrayList<String> getTableProvinceValues(String regioneSelezionata)
Come vedi, il metodo prende in ingresso il nome della regione selezionata. Con questo nome io cerco l'id relativo nella tabella regioni e poi catturo la lista di province che hanno come id della regione quello preso al passo precedente (questo ho dovuto farlo perché nella tabella province non ho la colonna contenente il nome della loro regione ma ho soltanto la colonna che definisce l'id della regione a cui appartiene quella provincia).

PROBLEMA: inizialmente ho impostato la stringa regioneSelezionata a null perché fino a quando l'utente non seleziona la regione non deve poter selezionare alcuna provincia.
Ma come faccio a far sì che lo spinner delle province sia "rigenerato" tutte le volte che il listener delle regioni rileva una nuova selezione? Grazie!!!  ;-)

Post unito: 06 Giugno 2013, 15:57:22 CEST
OK! CE L'HO FATTA!
Praticamente ho inserito le definizioni delle ArrayList e degli ArrayAdapter all'interno dei Listener!
Esempio:

Codice: [Seleziona]
spinnerRegioni
                                .setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                                        @Override
                                        public void onItemSelected(AdapterView<?> parent,
                                                        View view, int pos, long id) {
                                                Object item = parent.getItemAtPosition(pos);
                                                regione_selezionata = item.toString();
                                                Log.i("REGIONE", "Hai selezionato "
                                                                + regione_selezionata);
                                               
                                                ArrayList<String> arrayProvince = new ArrayList<String>();
                                                arrayProvince = getTableProvinceValues(regione_selezionata);
                                                ArrayAdapter<String> adapterProvince = new ArrayAdapter<String>(getApplicationContext(),R.layout.spinner_row, arrayProvince);
                                                adapterProvince.setDropDownViewResource(R.layout.spinner_row);
                                                spinnerProvince.setAdapter(adapterProvince);

                                        }

                                        @Override
                                        public void onNothingSelected(AdapterView<?> parent) {
                                        }
                                });

Analogamente ho fatto per le province, inserendoci dentro la definizione di Array e Adapter dei comuni. E così sono comparse tutte le voci e se ne cambio una cambiano le altre in relazione ad essa!!

A questo punto vorrei fare le ultime due cose su questa Activity:

1) Vorrei inserire negli spinner le tipiche voci di default ("Seleziona la regione", "Seleziona la provincia", "Seleziona il comune")... mi sa che sarà un problema visto l'automatismo che ora si è creato...

2) Infine creerò un button che prende i valori scelti dall'utente e li passa ad un'altra activity. E su questo sono ragionevolmente tranquillo  :D :D

Consigli? Grazieeee!!!  :-) :-) :-)
« Ultima modifica: 06 Giugno 2013, 15:57:22 CEST da guidocx84, Reason: Merged DoublePost »

Offline NanoAndroide

  • Utente junior
  • **
  • Post: 63
  • Respect: +3
    • Google+
    • Mostra profilo
    • MeToo
  • Dispositivo Android:
    GT-S5570
  • Play Store ID:
    MeToo
  • Sistema operativo:
    Windows 7
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #9 il: 06 Giugno 2013, 22:42:24 CEST »
0
Sono tornato tardi, ma vedo che te la sei cavata egregiamente...  :D

A questo punto vorrei fare le ultime due cose su questa Activity:

1) Vorrei inserire negli spinner le tipiche voci di default ("Seleziona la regione", "Seleziona la provincia", "Seleziona il comune")... mi sa che sarà un problema visto l'automatismo che ora si è creato...

2) Infine creerò un button che prende i valori scelti dall'utente e li passa ad un'altra activity. E su questo sono ragionevolmente tranquillo  :D :D

Consigli? Grazieeee!!!  :-) :-) :-)

Per quel che riguarda il primo punto, ti suggerisco di dare un'occhiata qui:

android - How to set Spinner Default by its Value instead of Postion? - Stack Overflow

L'esempio va un po adattato, ma rende l'idea...  ;-)

Sul secondo punto, ti dico soltanto intent e bundle... Mi piace buttare li il concetto e lasciarti lavorare, a mio avviso è più formativo. Se poi non riesci ti do qualche elemento in più...  :-P



Offline guidocx84

  • Utente junior
  • **
  • Post: 68
  • Respect: 0
    • Mostra profilo
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #10 il: 07 Giugno 2013, 11:21:40 CEST »
0
Ciao!!!! Ho finito!!!
Ho visto su internet dai vari link su come settare le cose di default che le prendeva comunque dall'ArrayAdapter che costruisco a partire dall'ArrayList. Allora sono andato alla sorgente e ho inserito un myarray.add apposito prima di tutto il resto!

Codice: [Seleziona]
ublic ArrayList<String> getTableRegioniValues() {

                ArrayList<String> my_array = new ArrayList<String>();

                try {
                        mydb = openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE, null);
               
                        Cursor allrows = mydb.query(TABLE_REGIONI,
                                        new String[] { C_REGIONE }, null, null, null, null, null);

                        if (allrows.moveToFirst()) {
                                my_array.add("Seleziona la regione");
                                do {
                                        String NOME_REGIONE = allrows.getString(0);
                                        my_array.add(NOME_REGIONE);

                                } while (allrows.moveToNext());
                        }
                        allrows.close();
                        mydb.close();
                } catch (Exception e) {
                        Log.i("ERRORE", "Errore nel popolare lo spinner delle regioni");
                }
                return my_array;
        }

Grazie mille per il supporto!!!

p.s. il button l'avevo fatto in 5 min.. già sapevo come fare!  ;-)

GRAZIE!

Post unito: 07 Giugno 2013, 16:19:12 CEST
Dimenticavo una cosa fondamentale: oltre a quanto detto sopra, è necessario anche aggiungere nella tabella regione una regione con id 0 che si chiama "Seleziona la regione", idem per le province ("Seleziona la provincia") con id 0 e id regione di appartenenza 0 ed infine nella tabella dei comuni un comune chiamato "Seleziona il comune" con id 0 afferente alla provincia 0.  ;-)
« Ultima modifica: 07 Giugno 2013, 16:19:12 CEST da guidocx84, Reason: Merged DoublePost »

Offline leo87

  • Nuovo arrivato
  • *
  • Post: 33
  • Respect: +1
    • Mostra profilo
  • Sistema operativo:
    windows 8
Re:3 spinner collegati tra loro popolati da database Sqlite
« Risposta #11 il: 08 Giugno 2013, 12:27:07 CEST »
0
Ciao...
Io dovrei fare una cosa simile, solo che il mio database è su un server remoto (ma questo non è un problema perchè sò come gestirlo). Volevo chiederti se tu ti crei 3 Spinner e popoli dinamicamente (a cascata) le spinner?