Autore Topic: Problema ListView con due bottoni  (Letto 746 volte)

Offline Peppin2o

  • Nuovo arrivato
  • *
  • Post: 36
  • Respect: +1
    • Mostra profilo
  • Sistema operativo:
    Windows 8.1 Pro x64
Problema ListView con due bottoni
« il: 21 Novembre 2013, 17:40:03 CET »
0
salve ragazzi ;)
Ho seguito l'ottimo tutorial di Ohmnibus sull'inserimento di un bottone in un item di listView. Io però ne ho inseriti due.

Il codice è uguale solo che invece di gestirne uno, ne gestisco due. I due bottoni servono ad aumentare di uno a diminuire, sempre di uno, il valore che si trova in una TextView presente in mezzo ai due bottoni.

L'evento di click sull'ITEM viene gestito bene (e in questo senso, l'utilizzo del Toast come "prova" è stato ottimo), mentre per i bottoni non va bene: premento sul bottone "+" dell'item x viene aumentato il valore della TextView dell'item y, il tutto in modo apparentemente casuale :O e lo stesso dicasi per il bottone "-". E qui il Toast non è di aiuto, perchè anch'esso va ad penem (fatemi passare il termine) :O

Posto il codice:

Adapter per la ListView:
Codice (Java): [Seleziona]
package it.paradiso_giuseppe.util;


import java.util.ArrayList;
import java.util.HashMap;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class ProductsViewAdapter extends ArrayAdapter<HashMap<String, String>>{
        private int resource;
    private LayoutInflater inflater;
    private char tag;
   
    private TextView tvPid;
    private TextView tvNome;
    private TextView tvDescr;
    private TextView tvPrezzo;
    private TextView tvQuantita;
    private Button btPlus;
    private Button btMinus;
    private HashMap<String, String> prodotto;
   
     
        public ProductsViewAdapter(Context context, int resourceId,
            ArrayList<HashMap<String, String>> objects, char t) {
        super(context, resourceId, objects);
        resource = resourceId;
        inflater = LayoutInflater.from(context);
        tag=t;
        }
       
        @Override
        public View getView ( int position, View convertView, ViewGroup parent ) {

                // Recuperiamo l'oggetti che dobbiamo inserire a questa posizione
                prodotto = getItem( position );

                ProductsViewCache viewCache;

                if ( convertView == null ) {

                        convertView = inflater.inflate( resource, null );
                        viewCache = new ProductsViewCache( convertView );
                        convertView.setTag( viewCache );
                }
                else {
                        viewCache = ( ProductsViewCache ) convertView.getTag();
                }

                // Prendiamo le view dalla cache e mettiamoci i valori

                tvPid = viewCache.getTxtId();
                if (tag == 'p'){
                        tvPid.setText(prodotto.get("idProdotto"));
                       
                }
                else{
                        tvPid.setText(prodotto.get("idBibita"));
                }
                       
                tvNome = viewCache.getTxtNome();
                tvNome.setText( prodotto.get("nome") );
               
                tvDescr = viewCache.getTxtDescr();
                tvDescr.setText( prodotto.get("descrizione") );
               
                tvPrezzo = viewCache.getTxtPrezzo();
                tvPrezzo.setText( prodotto.get("prezzo") );
               
               
                tvQuantita = viewCache.getTxtQuantita();
               
               
                Button btPlus = viewCache.getBtnPlus();
                btPlus.setTag(prodotto);
                btPlus.setOnClickListener(new OnClickListener() {
                        public void onClick(View view) {
                                int val = Integer.parseInt(tvQuantita.getText().toString())+1;
                                tvQuantita.setText(String.valueOf(val));
                Toast.makeText(
                                view.getContext(),
                                "Click sulla bottone nella riga " + prodotto.get("nome"),
                                Toast.LENGTH_LONG
                                ).show();
                        }
                });
               
               
                Button btMinus = viewCache.getBtnMinus();
                btMinus.setTag(prodotto);
                btMinus.setOnClickListener(new OnClickListener() {
                        public void onClick(View view) {
                                int val = Integer.parseInt(tvQuantita.getText().toString());
                                if (val > 0 ){
                                        val--;
                                        tvQuantita.setText(String.valueOf(val));
                                }
                        }
                });

                return convertView;

        }
}

Cache:

Codice (Java): [Seleziona]
package it.paradiso_giuseppe.util;


import it.paradiso_giuseppe.cooking.R;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class ProductsViewCache {
        private View baseView;
        private TextView txtId;
        private TextView txtNome;
        private TextView txtDescr;
        private TextView txtPrezzo;
        private TextView txtQuantita;
        private Button btnPlus;
        private Button btnMinus;
       
        public ProductsViewCache (View baseView){
                this.baseView=baseView;
        }
       
        public TextView getTxtId(){
                if ( txtId == null ) {
                        txtId = ( TextView ) baseView.findViewById( R.id.pid );
                }
                return txtId;
        }
       
        public TextView getTxtNome(){
                if ( txtNome == null ) {
                        txtNome = ( TextView ) baseView.findViewById( R.id.name );
                }
                return txtNome;
        }
        public TextView getTxtDescr(){
                if ( txtDescr == null ) {
                        txtDescr = ( TextView ) baseView.findViewById( R.id.description );
                }
                return txtDescr;
        }
       
        public TextView getTxtPrezzo(){
                if ( txtPrezzo == null ) {
                        txtPrezzo = ( TextView ) baseView.findViewById( R.id.price );
                }
                return txtPrezzo;
        }
       
        public TextView getTxtQuantita(){
                if ( txtQuantita == null ) {
                        txtQuantita = ( TextView ) baseView.findViewById( R.id.lblQty );
                }
                return txtQuantita;
        }
       
        public Button getBtnPlus(){
                if(btnPlus==null){
                        btnPlus = (Button) baseView.findViewById(R.id.btnPlus);
                }
                return btnPlus;
        }
        public Button getBtnMinus(){
                if(btnMinus==null){
                        btnMinus = (Button) baseView.findViewById(R.id.btnMinus);
                }
                return btnMinus;
        }
       
       
}

list Item:

Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:orientation="vertical" >

    <!-- Product id (pid) - will be HIDDEN - used to pass to other activity -->

    <TextView
       android:id="@+id/pid"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:visibility="gone" />

    <!-- Name Label -->

    <TextView
       android:id="@+id/name"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:paddingLeft="6dip"
       android:paddingTop="6dip"
       android:textSize="24dp"
       android:textStyle="normal" />

    <!-- Description Label -->

    <TextView
       android:id="@+id/description"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:paddingLeft="6dip"
       android:paddingTop="6dip"
       android:textSize="20dp"
       android:textStyle="italic" />

    <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >
        <!-- Price Label -->
        <TextView
           android:id="@+id/price"
           android:layout_width="108dp"
           android:layout_height="34dp"
           android:layout_marginRight="53dp"
           android:layout_weight="1.34"
           android:text="TextView" />

        <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="match_parent" >

            <it.paradiso_giuseppe.util.ListButton
               android:id="@+id/btnPlus"
               style="?android:attr/buttonStyleSmall"
               android:layout_width="35dp"
               android:layout_height="wrap_content"
               android:text="+"
               android:onClick="myClickHandlerPlus" />

            <TextView
               android:id="@+id/lblQty"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="0"
               android:textAppearance="?android:attr/textAppearanceSmall"
               android:width="35dp" />

            <it.paradiso_giuseppe.util.ListButton
               android:id="@+id/btnMinus"
               style="?android:attr/buttonStyleSmall"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="-"
               android:width="35dp"
               android:onClick="myClickHandlerMinus" />

        </LinearLayout>
    </LinearLayout>

</LinearLayout>

Activity con View:
Codice (Java): [Seleziona]
package it.paradiso_giuseppe.cooking;

import it.paradiso_giuseppe.util.ProdottoFinito;
import it.paradiso_giuseppe.util.ProductsViewAdapter;

import java.util.ArrayList;
import java.util.HashMap;

import android.os.Bundle;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Intent;
import android.graphics.Color;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class AllProducts_View extends ListActivity {
        private static final String TAG_PID = "idProd";
    private static final String TAG_NAME = "nome";
    private static final String TAG_PREZZO = "prezzo";
    private static final String TAG_DESCRIZIONE = "descrizione";
    private static final String TAG_QUANTITA = "quantita";
   
    public static SaveDataList saveData;
    SaveOrderData saveOrder; //public static
    Button btnConfirm, btnPlus, btnMinus;
    TextView lblQty;
    ListView lv;
    ArrayList<HashMap<String, String>> productsList;
    int [] valori_qty;
   
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.list_products);
                btnConfirm = (Button) findViewById(R.id.confermaProd);
               
                btnMinus = (Button)findViewById(R.id.btnMinus);
                btnPlus = (Button)findViewById(R.id.btnPlus);
                lblQty = (TextView)findViewById(R.id.lblQty);
               
                Intent in=getIntent();
               
                saveData = (SaveDataList)in.getExtras().getSerializable("mySaveData");
                saveOrder = (SaveOrderData)in.getExtras().getSerializable("mySaveOrder");
                String cid = in.getStringExtra("myCID");
                productsList = saveData.getProdottiPerCategoria(cid);
                lv = getListView();
               
                ProductsViewAdapter adapter = new ProductsViewAdapter(
                                AllProducts_View.this, R.layout.list_item_from_cat, productsList, 'p'
                                );
                /*AllProducts_View.this, productsList,
                R.layout.list_item_from_cat, new String[] { TAG_PID,
                        TAG_NAME, TAG_DESCRIZIONE, TAG_PREZZO},
                new int[] { R.id.pid, R.id.name, R.id.description, R.id.price});*/

        // updating listview
        lv.setAdapter(adapter);
        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    HashMap<String, String> p = (HashMap<String, String>) parent.getItemAtPosition(position);
                    Toast.makeText(
                                    view.getContext(),
                                    "Click sulla riga " + p.get("nome"),
                                    Toast.LENGTH_LONG
                                    ).show();
            }
    });
        btnConfirm.setVisibility(View.VISIBLE);
        }
}


Il codice del ListButton non è stato in alcun modo modificato....

Qualcuno ha un'idea sul perchè del malfunzionamento?

Grazie infinite in anticipo:)
 

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Problema ListView con due bottoni
« Risposta #1 il: 21 Novembre 2013, 19:44:23 CET »
0
Il problema è che quando l'OnClickListener() che hai creato per un certo Button viene eseguito, la getView() nella quale ci sono le variabili tipo tvQuantita, è già cambiata (perchè la getView() viene continuamente chiamata).

Non ho mai provato, ma secondo me nell'OnClickListener() devi recuperare la position del Button che ha generato il click e a quel punto aggiornare la variabile corrispondente.

Qualcosa tipo (tutto da provare):

Codice (Java): [Seleziona]
btPlus.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
         // recuperi la position del Button cliccato
         final int position = getListView().getPositionForView(v);
         // se la position è valida
         if (position != ListView.INVALID_POSITION) {
              // devi farti una funzione che aumenta il prodotto alla position
              AumentaProdotto(position);
         }
     }
});

NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Peppin2o

  • Nuovo arrivato
  • *
  • Post: 36
  • Respect: +1
    • Mostra profilo
  • Sistema operativo:
    Windows 8.1 Pro x64
Re:Problema ListView con due bottoni
« Risposta #2 il: 22 Novembre 2013, 00:20:02 CET »
0
non ho provato il codice che hai postato (ero fuori casa), però se può servire a inquadrare meglio il problema, ti dico che se la listView contiene più elementi di quelli visualizzabili effettivamente, i tasti "+" e "-" di tutti gli item vanno a modificare solo il primo e l'ultimo (ho notato al massimo il secondo e il penultimo) degli item visualizzati...cambiando gli item visualizzati (quindi scorrendo la lista) cambiano anche gli item interessati dall'evento onClick() del bottone "+"/"-"..

PS: la stessa cosa mi succedeva quando, al posto dei bottoni per aumentare e diminuire il valore, ho usato semplicemente una TextEdit con un SimpleAdapter... Più che altro vorrei capire per bene il perchè di questo malfunzionamento :|

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Problema ListView con due bottoni
« Risposta #3 il: 22 Novembre 2013, 07:02:58 CET »
0
Il perché l'ho scritto sopra, il listener che crei viene eseguito quando i riferimenti alla textview non sono più validi.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Peppin2o

  • Nuovo arrivato
  • *
  • Post: 36
  • Respect: +1
    • Mostra profilo
  • Sistema operativo:
    Windows 8.1 Pro x64
Re:Problema ListView con due bottoni
« Risposta #4 il: 22 Novembre 2013, 09:49:34 CET »
0
ma io nell'adapter ho già:

prodotto = getItem( position );
uso quel position o devo assumere che sia già "cambiato"?



E come posso fare nell'adapter per ricavarmi la listView per poter fare
if (position != ListView.INVALID_POSITION) ?

Scusami per le troppe domande ;) e ti ringrazio per la pazienza ;)
« Ultima modifica: 22 Novembre 2013, 09:56:53 CET da Peppin2o »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Problema ListView con due bottoni
« Risposta #5 il: 22 Novembre 2013, 10:18:24 CET »
0
ma io nell'adapter ho già:

prodotto = getItem( position );
uso quel position o devo assumere che sia già "cambiato"?

E come posso fare nell'adapter per ricavarmi la listView per poter fare
if (position != ListView.INVALID_POSITION) ?

Scusami per le troppe domande ;) e ti ringrazio per la pazienza ;)

Quando scrivi:
Codice (Java): [Seleziona]
new OnClickListener() { }
Tu stai creado un pezzo di codice che NON viene eseguito in quel momento. Viene passato al sistema e dici al sistema di eseguirlo se il Button viene premuto. Al sistema passi SOLO quella parte e non tutta la precedente parte nella getView. Detto in altro modo: la parte dove hai prodotto = getItem( position ); viene eseguita quando crei la la ListView, mentre la parte new OnClickListener() viene eseguita quando clicchi il Button.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Peppin2o

  • Nuovo arrivato
  • *
  • Post: 36
  • Respect: +1
    • Mostra profilo
  • Sistema operativo:
    Windows 8.1 Pro x64
Re:Problema ListView con due bottoni
« Risposta #6 il: 22 Novembre 2013, 10:42:26 CET »
0
questo mi è chiaro, ma non riesco a capire come posso ricavare  la posizione effettiva nella lista del bottone premuto direttamente nell'onClick() dell'adapter per il bottone :S


Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Problema ListView con due bottoni
« Risposta #7 il: 22 Novembre 2013, 10:55:15 CET »
0
Te l'ho scritto sopra un codice da provare.

Codice (Java): [Seleziona]
btPlus.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
         // recuperi la position del Button cliccato
         final int position = getListView().getPositionForView(v);
         // se la position è valida
         if (position != ListView.INVALID_POSITION) {
              // devi farti una funzione che aumenta il prodotto alla position
              AumentaProdotto(position);
         }
     }
});
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Peppin2o

  • Nuovo arrivato
  • *
  • Post: 36
  • Respect: +1
    • Mostra profilo
  • Sistema operativo:
    Windows 8.1 Pro x64
Re:Problema ListView con due bottoni
« Risposta #8 il: 22 Novembre 2013, 11:00:02 CET »
0
Si, prima non te l'ho scritto...

il
Codice (Java): [Seleziona]
getListView()
non è definito all'interno dell'onClickListener :|

Post unito: 22 Novembre 2013, 13:51:55 CET
A costo di sembrare scortese, qualcuno può aiutarmi in qualche modo? Possibile che sia un problema esclusivamente mio? :|
« Ultima modifica: 22 Novembre 2013, 13:51:55 CET da Peppin2o, Reason: Merged DoublePost »