在我的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;
}
}
感谢您的帮助!!!
答案 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();
}