当我关注EditText时getView()出错

时间:2014-05-10 08:40:22

标签: android listview android-edittext runtime-error visibility

在我的ListView中,我有很多行,每行都有一个TextView和一个Button。如果我单击TextView,这两个视图将变为不可见(GONE),并显示EditText和另一个Button。最后一个Button允许返回TextView和前一个Button,隐藏Edittext和他自己。换句话说,我在这两个视图之间切换。 在ListView的页脚中,我有一个允许添加新行的按钮。当我单击最后一行的TextView时,一如既往地显示EditText和Button。问题是,当我单击EditText时,即Edittext获得焦点时,大多数情况下此EditText和相关按钮都被隐藏,并且显示TextView与另一个Button。

当我调试代码时,程序永远不会切换任何元素的可见性(或者更好,在它的UiI中,但程序不符合我为此目的编写的行)。

我找不到错误,我在这里留下代码:

包含ListView的类

    package fragments;

import [...]


/**
 * La classe FragmentModificaLinea è un Fragment che permette di prendere
 * una linea già presente nel database, e modificare le fermate che essa
 * percorre.
 */
public class FragmentModificaLinea extends Fragment {

    private Context context = null;


private Button btnConfermaModifica = null;
    private Button btnAggiungi = null;
    private Button btnCambiaLinea = null;
    private EditText edtCambiaNome = null;
private EditText edtCambiaCodice = null;
private ListView listViewModifica = null;
private ListView listViewMostra = null;

// Lista di tutte le linee.
private ArrayList<String> contenitoreLinee = null;

// Lista con le linee appartenenti alla fermata e relativo adapter.
private ArrayList<String> fermateDellaLinea = null;
private AdapterModificaLinea adapterFermateDellaLinea = null;

// Inflater per il footer della lista
private LayoutInflater li = null;

// Oggetto che contiene query al db locale.
private Query richiediAlDatabase = null;

// Tag usato nei log.
@SuppressWarnings("unused")
private static final String TAG = FragmentModificaLinea.class.getSimpleName();

// Salva il codice originale, serve per eliminare la linea.
private String codiceLinea = null;

// La posizione nella listviewmostra dell'elemento da modificare.
private int posizione = 0;

/**
 * Primo metodo che viene chiamato quando creo il fragment. Qui associo
 * il layout al fragment.
 * @param inflater Il layout da utilizzare in questo fragment.
 * @param container Il layout che contiene il fragment.
 * @param savedInstanceState Se si creasse un punto di ripristino dell'activity quando si chiude.
 * @return View
 */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inserisco il layout di questo fragment.
    // Inflate the layout for this fragment.
    return inflater.inflate(R.layout.fragment_modifica_linea, container, false);
}

/**
 * Metodo chiamato appena dopo che è stato istanziato il layout. Ottengo gli oggetti in esso presenti.
 * @param view Tutte le view nel layout.
 * @param savedInstanceState Se si creasse un punto di ripristino dell'activity quando si chiude.
 */
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    context = getActivity();        
    richiediAlDatabase = new Query(context);
    li = LayoutInflater.from(context);
    // Carico tutte le linee dal database locale.
    contenitoreLinee = richiediAlDatabase.caricaLinee();        
    // Imposto la listView che mostra le linee.
    listViewMostra = (ListView) getView().findViewById(R.id.listViewModificaLineaMostraLinee);
    listViewMostra.setAdapter(new ArrayAdapter<String>(context,android.R.layout.simple_list_item_1, contenitoreLinee));
    listViewMostra.setEmptyView(getView().findViewById(R.id.empty_list_item));
    // Imposto la ListView; ci aggiungo come footer i bottoni al fondo del layout:
    // aggiungi una fermata e conferma linea.
    listViewModifica = (ListView) getView().findViewById(R.id.listViewModificaLinea);
    LinearLayout footer = (LinearLayout) li.inflate(R.layout.footer_list_view, null);
    btnConfermaModifica = (Button) footer.findViewById(R.id.btnConfermaModifica);
    btnAggiungi = (Button) footer.findViewById(R.id.btnAggiungi);
    listViewModifica.addFooterView(footer);
    // Aggiungo come header ciò che mi permette di modifica nome, codice linea
    // e di cambiare linea che si sta modificando.
    LinearLayout header = (LinearLayout) li.inflate(R.layout.header_list_view, null);
    btnCambiaLinea = (Button) header.findViewById(R.id.btnCambiaLinea);
    edtCambiaCodice = (EditText) header.findViewById(R.id.edtCambiaCodice);
    edtCambiaNome = (EditText) header.findViewById(R.id.edtCambiaNome);
    listViewModifica.addHeaderView(header);

    listViewMostra.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            posizione = position;

            // Setto l'adapter alla ListView.
            fermateDellaLinea = richiediAlDatabase.caricaFermateDellaLinea(((String) listViewMostra.getItemAtPosition(posizione)).split(" Cod: ")[1]);
            adapterFermateDellaLinea = new AdapterModificaLinea(context, R.layout.elemento_modifica_linea, fermateDellaLinea);
            listViewModifica.setAdapter(adapterFermateDellaLinea);
            // Rendo visibile la ListView.
            listViewModifica.setVisibility(ListView.VISIBLE);
            // Inizializzo i valori nell'header: nome e codice.
            edtCambiaNome.setText(((String) listViewMostra.getItemAtPosition(posizione)).split(" - Cod: ")[0]);
            edtCambiaCodice.setText(((String) listViewMostra.getItemAtPosition(posizione)).split(" - Cod: ")[1]);
            // Salvo il codice della linea così posso poi eliminarla.
            codiceLinea = ((String) listViewMostra.getItemAtPosition(posizione)).split(" Cod: ")[1];
            // Disabiliti gli oggetti per la ricerca della linea.
            listViewMostra.setVisibility(ListView.GONE);

        }
    });


    // Aggiunge una fermata alla ListView.
    btnAggiungi.setOnClickListener(new OnClickListener() {          
        @Override
        public void onClick(View v) {

            // Controllo che non stia modificando già un'altra linea.
            if(!adapterFermateDellaLinea.isStoModificandoUnaFermata())
                // Se fermateDellaLinea fosse vuoto andrebbe in errore la prossima if,
                // quindi si aggiunge senza ulteriori controlli.
                if(!fermateDellaLinea.isEmpty())
                    // Se l'ultima riga è ancora da inserire.
                    if(!fermateDellaLinea.get(fermateDellaLinea.size() - 1).equals("Nuova fermata")){
                        // Codice uguale all'else sottostante.
                        fermateDellaLinea.add("Nuova fermata");
                        adapterFermateDellaLinea.notifyDataSetChanged();
                    }else Toast.makeText(context, "Inserire prima la fermata appena aggiunta.", Toast.LENGTH_LONG).show();
                else{
                    fermateDellaLinea.add("Nuova fermata");
                    adapterFermateDellaLinea.notifyDataSetChanged();                    
                }
            else Toast.makeText(context, "Confermare la fermata che si sta tentando di modificare.", Toast.LENGTH_LONG).show();
        }
    });


    // Bottone che permette di caricare la linea aggiornata.
    btnConfermaModifica.setOnClickListener(new OnClickListener() {          
        @Override
        public void onClick(View v) {

            // Se l'ultima fermata è già stata inserita.
            if(!fermateDellaLinea.get(fermateDellaLinea.size() - 1).equals("Nuova fermata")){
                // Se non si sta tentando di modificare una fermata.
                if(!adapterFermateDellaLinea.isStoModificandoUnaFermata())
                    // Permette di caricare la linea.
                    new UpdateLinea().execute();
                else Toast.makeText(context, "Confermare la fermata che si sta tentando di modificare.", Toast.LENGTH_LONG).show();
            }else Toast.makeText(context, "Inserire l'ultima fermata con un suggerimento.", Toast.LENGTH_LONG).show();

        }
    });


    // Questo bottone nasconde la listView e abilita la ricerca di una nuova linea da modificare.
    btnCambiaLinea.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            // Rendo visibigli gli elementi per la ricerca.
            listViewMostra.setVisibility(ListView.VISIBLE);

            // Nascondo la ListView.
            listViewModifica.setVisibility(ListView.GONE);

            // Ripulisco le EditText.
            edtCambiaCodice.setText("");
            edtCambiaNome.setText("");
        }
    });
}


/**
 * Il compito di questa classe è quello di aggiornare la linea. Per far
 * ciò prima la cancella dai database e poi la ricarica con i nuovi dati.
 * Non si usano due AsyncTask diversi per evitare il caso in cui, non essendo
 * sincronizzati, si inseriscano dei record prima che vengano eliminati.
 */
class UpdateLinea extends AsyncTask<Void, Void, Void>{

    private ProgressDialog pDialog;

    // Tag usato nei log.
    private final String TAG = UpdateLinea.class.getSimpleName();

    private String ELIMINA_LINEA = GlobalClass.getDominio() + "Upload/eliminaLinea.php";
    private String CARICA_LINEA = GlobalClass.getDominio() + "Upload/caricaLinea.php";

    private String nomeLineaScelta = edtCambiaNome.getText().toString();
    private String codiceLineaScelta = edtCambiaCodice.getText().toString();

    JSONObject jsonElimina = null;
    JSONObject jsonCarica = null;
    List<NameValuePair> paramsCarica = null;

    /**
     * Metodo che viene eseguito prima di doInBackground.
     * Avvio il ProgressDialog.
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        // Creo e mostro il ProgressDialog.
        pDialog = new ProgressDialog(context);
        pDialog.setMessage("Aggiornamento Fermata...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    /**
     * Questo metodo esegue il download.
     * @param voids
     * @return
     */
    @Override
    protected Void doInBackground(Void... params) {

        JSONParser jsonParser = new JSONParser();
        String codLinea = codiceLinea;
        // Creazione dei parametri.
        List<NameValuePair> paramsElimina = new ArrayList<NameValuePair>();
        paramsElimina.add(new BasicNameValuePair("CodLinea", codLinea));

        // Richiesta della pagina .php.
        jsonElimina = jsonParser.makeHttpRequest(
                ELIMINA_LINEA, "POST", paramsElimina);


        jsonParser = new JSONParser();
        // Creazione dei parametri.
        // A differenza della classe FragmentAggiungiLinea, i parametri
        // li creo dentro all'AsyncTask perchè i controlli li faccio
        // già durante l'inserimento, e non quando si conferma l'invio
        // dei dati.
        paramsCarica = new ArrayList<NameValuePair>();
        paramsCarica.add(new BasicNameValuePair("NomeLinea", nomeLineaScelta));
        paramsCarica.add(new BasicNameValuePair("CodLinea", codiceLineaScelta));
        for (String fermata : fermateDellaLinea) {
            paramsCarica.add(new BasicNameValuePair("Fermate[]", fermata.split(" - Cod: ")[1]));
        }

        // Richiesta della pagina .php.
        jsonCarica = jsonParser.makeHttpRequest(
                CARICA_LINEA, "POST", paramsCarica);

        return null;
    }

    /**
     * Metodo eseguito dopo doInBackground. Chiudo il ProgressDialog.
     * @param risultato E' il risultato del .php.
     */
    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);

        // Chiudo il ProgressDialog.
        pDialog.dismiss();

        // Aggiorno il database locale.
        try {

            // Se la linea è sia stata eliminata che aggiunta con successo.
            if(jsonElimina.getInt(GlobalClass.getTagSuccess()) != 0)
                if(jsonCarica.getInt(GlobalClass.getTagSuccess()) != 0){


                // Ottengo il database locale.
                DatabaseLocale db = new DatabaseLocale(context);
                SQLiteDatabase dbScrivibile = db.getWritableDatabase();

                // Cancello da linea e tratta.
                dbScrivibile.delete(DatabaseLocale.getTableNameLinea(), 
                        DatabaseLocale.getTagCodiceLinea() + " = '" + codiceLineaScelta + "'", null);                    
                dbScrivibile.delete(DatabaseLocale.getTableNameTratta(), 
                        DatabaseLocale.getTagCodiceLinea() + " = '" + codiceLineaScelta + "'", null);

                /// AGGIUNGO LA LINEA
                ContentValues valori = new ContentValues();
                valori.put(DatabaseLocale.getTagCodiceLinea(), codiceLineaScelta);
                valori.put(DatabaseLocale.getTagNomeLinea(), nomeLineaScelta);
                valori.put(DatabaseLocale.getTagCodiceCapolinea(), fermateDellaLinea.get(0));
                dbScrivibile.insert(DatabaseLocale.getTableNameLinea(), null, valori);

                for (int i = 0; i < paramsCarica.size(); i++) {
                    BasicNameValuePair valore = ((BasicNameValuePair) paramsCarica.get(i));
                    if(valore.getName() == "Fermate[]" && i != (paramsCarica.size() - 1)){                          
                        valori = new ContentValues();
                        valori.put(DatabaseLocale.getTagCodiceLinea(), codiceLineaScelta);
                        valori.put(DatabaseLocale.getTagCodiceFermata(), valore.getValue());
                        valori.put(DatabaseLocale.getTagSuccessiva(), ((BasicNameValuePair) paramsCarica.get(i + 1)).getValue());
                        dbScrivibile.insert(DatabaseLocale.getTableNameTratta(), null, valori);
                    }else if(i == (paramsCarica.size() - 1)){                           
                        valori = new ContentValues();
                        valori.put(DatabaseLocale.getTagCodiceLinea(), codiceLineaScelta.toString());
                        valori.put(DatabaseLocale.getTagCodiceFermata(), valore.getValue());
                        valori.put(DatabaseLocale.getTagSuccessiva(), 0);
                        dbScrivibile.insert(DatabaseLocale.getTableNameTratta(), null, valori);
                    }
                }

                // Chiudo le connessioni.
                dbScrivibile.close();
                db.close();

                Toast.makeText(context, "Linea modificata con successo.", Toast.LENGTH_LONG).show();
                }else Toast.makeText(context, "Errore nel caricamento della linea", Toast.LENGTH_LONG).show();
            else Toast.makeText(context, "Errore eliminando la linea", Toast.LENGTH_LONG).show();
        } catch (JSONException e) {
            Log.e(TAG, "Error " + e.toString());
            Toast.makeText(context, "Errore durante l'aggiornamento della linea nel database locale.", Toast.LENGTH_LONG).show();
        }
    }


    }

}

listView的适配器,这里我切换了可见性:

package fragments;

import [...]

/**
 * Questa classe ha il compito di gestire tutte le linee
 * della ListView, e quindi il loro comportamento. Ogni linea 
 * ha 4 Views, di cui ne mostra solo 2 per volta.
 * All'inizio mostra il nome della fermata ed il bottone per 
 * eliminarla. Se si clicca sul nome della linea queste due
 * Views vengono nascoste e viene mostrata una EditText
 * per inserire la nuova fermata ed un bottone per confermare.
 * @author giacomotb
 *
 */
public class AdapterModificaLinea extends ArrayAdapter<String> {

    private Context context = null;
    private LayoutInflater li = null;
private ArrayList<String> fermateDellaLinea = null;

// Variabile che indica se in almeno una riga
// si sta modificando la fermata(è mostrata 
// l'EditText.
private boolean stoModificandoUnaFermata = false;

// Il layout che viene usato per ogni riga.
private int layoutResourceId = 0; 

// Oggetto che contiene query al db locale.
private Query richiediAlDatabase = null;


/**
 * Classe statica che permette di evitare ripetuti
 * findViewById(), e risparmia il 15% del tempo.
 * http://www.vogella.com/tutorials/AndroidListView/article.html#adapterperformance
 * http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder
 *
 */
static class ViewHolder {
    TextView txtCambiaFermata;
    AutoCompleteTextView actModificaFermata;
    Button btnEliminaFermataModificaLinea;
    Button btnModificaFermataInModificaLinea;
}

/**
 * Costruttore.
 * @param context
 * @param resource
 * @param fermate
 */
public AdapterModificaLinea(Context context, int resource, ArrayList<String> fermate) {
    super(context, resource, fermate);
    this.context = context;
    layoutResourceId = resource;
    this.fermateDellaLinea = fermate;   
    li = LayoutInflater.from(context);
}

/**
 * Metodo che crea la row quando si disegna la ListView.
 * Assegna anche i listener ai suoi elementi.
 */
@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    richiediAlDatabase = new Query(context);

    // Tutte le fermare nel database locale.
    final ArrayList<String> tutteLeFermate = richiediAlDatabase.caricaFermate();

    // Permette di riutilizzare le View che sono fuori dallo schermo
    // per risparmiare tempo.
    // http://www.vogella.com/tutorials/AndroidListView/article.html#adapterperformance
    if(convertView == null){
        convertView = li.inflate(layoutResourceId, null);

        // configure view holder
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.txtCambiaFermata = (TextView) convertView.findViewById(R.id.txtCambiaFermata);
        viewHolder.actModificaFermata = (AutoCompleteTextView) convertView.findViewById(R.id.actModificaFermata);
        viewHolder.btnEliminaFermataModificaLinea = (Button) convertView.findViewById(R.id.btnEliminaFermataModificaLinea);
        viewHolder.btnModificaFermataInModificaLinea = (Button) convertView.findViewById(R.id.btnModificaFermataInModificaLinea);         
        convertView.setTag(viewHolder);
    }

    final ViewHolder holder = (ViewHolder) convertView.getTag();

    if(!stoModificandoUnaFermata){
        // Setto la visibilità di default.
        holder.btnModificaFermataInModificaLinea.setVisibility(Button.GONE);
        holder.actModificaFermata.setVisibility(AutoCompleteTextView.GONE);
        holder.btnEliminaFermataModificaLinea.setVisibility(Button.VISIBLE);
        holder.txtCambiaFermata.setVisibility(TextView.VISIBLE);
        // Aggiungo il testo alla TextView
        holder.txtCambiaFermata.setText(fermateDellaLinea.get(position));
        // Aggiungo l'adapter all'AutoCompleteTextView.
        holder.actModificaFermata.setAdapter(new ArrayAdapter<String>(context,android.R.layout.simple_dropdown_item_1line, tutteLeFermate));            
    }

    // Se si preme sulla textview la scambio con una all'AutoCompleteTextView per cambiare fermata.
    holder.txtCambiaFermata.setOnClickListener(new OnClickListener() {          
        @Override
        public void onClick(View v) {               

            // Se non sto già modificando un'altra fermata.
            if(!stoModificandoUnaFermata){
                // Dichiaro che sto modificando una fermata.
                stoModificandoUnaFermata = true;

                // Assegno all'AutoComplete.. il testo della TextView nascosta.
                holder.actModificaFermata.setText(holder.txtCambiaFermata.getText().toString());
                // Cambio visibilità agli elementi.
                holder.txtCambiaFermata.setVisibility(TextView.GONE);
                holder.btnEliminaFermataModificaLinea.setVisibility(Button.GONE);
                holder.actModificaFermata.setVisibility(AutoCompleteTextView.VISIBLE);
                holder.btnModificaFermataInModificaLinea.setVisibility(Button.VISIBLE);


                // Listener al bottone che conferma la modifica della fermata.
                holder.btnModificaFermataInModificaLinea.setOnClickListener(new View.OnClickListener() {                        
                    @Override
                    public void onClick(View v) {

                        // Non sto più modificando alcuna riga.
                        stoModificandoUnaFermata = false;

                        // Se la fermata è una di quelle consigliate.
                        if(tutteLeFermate.contains(holder.actModificaFermata.getText().toString()))
                            // Se non è presente tra quelle già inserite
                            if(!fermateDellaLinea.contains(holder.actModificaFermata.getText().toString())
                                    // Ma la posizione non è la stessa di quella che si sta modificando,
                                    // nel caso in cui si reinserisca la fermata che si voleva modificare.
                                    || fermateDellaLinea.indexOf(holder.actModificaFermata.getText().toString()) == position){

                                // Cambio la fermata nella lista a cui fa riferimento la ListView.
                                fermateDellaLinea.set(position, holder.actModificaFermata.getText().toString());
                                // Notifico i cambiamenti.
                                AdapterModificaLinea.this.notifyDataSetChanged();

                                // Cambio le visibilità.
                                holder.btnModificaFermataInModificaLinea.setVisibility(Button.GONE);
                                holder.actModificaFermata.setVisibility(AutoCompleteTextView.GONE);
                                holder.btnEliminaFermataModificaLinea.setVisibility(Button.VISIBLE);
                                holder.txtCambiaFermata.setVisibility(TextView.VISIBLE);

                            }else Toast.makeText(context, "Fermata già presente: prima di inserirla eliminare la medesima fermata dalla lista"
                                        , Toast.LENGTH_LONG).show();
                        else Toast.makeText(context, "La fermata deve assumere uno dei valori suggeriti."
                                    , Toast.LENGTH_LONG).show();
                    }
                });             
            }else Toast.makeText(context, "Confermate la fermata che si sta modificando."
                    , Toast.LENGTH_LONG).show();
        }
    });


    // Bottone che permette di eliminare una data riga e la sua fermata.
    holder.btnEliminaFermataModificaLinea.setOnClickListener(new OnClickListener() {            
        @Override
        public void onClick(View v) {
            fermateDellaLinea.remove(position);
            AdapterModificaLinea.this.notifyDataSetChanged();
        }
    });

    return convertView;
}

public boolean isStoModificandoUnaFermata() {
    return stoModificandoUnaFermata;
    }


}

感谢您的帮助!!!

1 个答案:

答案 0 :(得分:0)

Try to replace this pieace of code
 if(convertView == null){
        convertView = li.inflate(layoutResourceId, null);

        // configure view holder
        ViewHolder viewHolder = new ViewHolder();
        viewHolder.txtCambiaFermata = (TextView) convertView.findViewById(R.id.txtCambiaFermata);
        viewHolder.actModificaFermata = (AutoCompleteTextView) convertView.findViewById(R.id.actModificaFermata);
        viewHolder.btnEliminaFermataModificaLinea = (Button) convertView.findViewById(R.id.btnEliminaFermataModificaLinea);
        viewHolder.btnModificaFermataInModificaLinea = (Button) convertView.findViewById(R.id.btnModificaFermataInModificaLinea);         
        convertView.setTag(viewHolder);
    }

    final ViewHolder holder = (ViewHolder) convertView.getTag();

有了这个

ViewHolder viewHolder;
 if(convertView == null){
            convertView = li.inflate(layoutResourceId, null);

        // configure view holder
        viewHolder = new ViewHolder();
        viewHolder.txtCambiaFermata = (TextView) convertView.findViewById(R.id.txtCambiaFermata);
        viewHolder.actModificaFermata = (AutoCompleteTextView) convertView.findViewById(R.id.actModificaFermata);
        viewHolder.btnEliminaFermataModificaLinea = (Button) convertView.findViewById(R.id.btnEliminaFermataModificaLinea);
        viewHolder.btnModificaFermataInModificaLinea = (Button) convertView.findViewById(R.id.btnModificaFermataInModificaLinea);         
        convertView.setTag(viewHolder);
    }else{
        holder = (ViewHolder) convertView.getTag();
    }