IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Appliquer style particulier sur un item d'une liste


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    108
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 108
    Par défaut Appliquer style particulier sur un item d'une liste
    Bonjour,

    Je développe actuellement un widget qui comporte une liste d'items. Aujorud'hui, le chargement de cette liste est faite à l'aide de données qui sont pour le moment stockées dans un tableau multidimensionnel. Dans ce tableau se trouve un champ (repertoire[i][5]) qui est une chaine égale à true ou false.

    Je souhaiterai effectuer un traitement sur cette chaine et affecter un un textview présent dans chaque item de ma liste dans mon widget, la couleur verte si la chaine est égale à true et rouge sinon. Je ne sais pas ou positionner mon code pour opérer mon traitement.

    Aujourd'hui, je l'ai fait dans la méthode onCreate() et getViewAt() mais ce traitement est opéré que pour le premier item de la liste. Comment pouvoir l'appliquer à l'ensemble des éléments ?

    Voici le code de ma classe monWidgetService.java :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
     
    import java.util.ArrayList;
    import java.util.List;
    import android.appwidget.AppWidgetManager;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.widget.RemoteViews;
    import android.widget.RemoteViewsService;
     
    public class StackWidgetService extends RemoteViewsService {
        @Override
        public RemoteViewsFactory onGetViewFactory(Intent intent) {
            return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
        }
    }
     
    class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
        private static int mCount;
        private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
        private Context mContext;
        private int mAppWidgetId;
        public Boolean isFinished = false;
     
        public StackRemoteViewsFactory(Context context, Intent intent) {
            mContext = context;
            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        }
     
        public void onCreate() {
            // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
            // for example downloading or creating content etc, should be deferred to onDataSetChanged()
            // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
     
        	String[][] repertoire = new String[][]{
                    {"HP Touchpad", "descriptionHP", "http://google.frfrfr", "99€", "80€", "true"},
                    {"test1", "desc1", "http://monsite1.fr", "10€", "80€", "false"},
                    {"test2", "desc2", "http://monsite2.fr", "20€", "80€", "true"},
                    {"test3", "desc3", "http://monsite3.fr", "20€", "80€", "true"},
                    {"test4", "desc4", "http://monsite4.fr", "20€", "80€", "false"},
                    {"test5", "desc5", "http://monsite5.fr", "20€", "80€", "true"},
                    {"test5", "desc6", "http://monsite6.fr", "20€", "80€", "false"}};
     
        	mCount = repertoire.length;
     
            for (int i = 0; i < repertoire.length; i++) {
                mWidgetItems.add(new WidgetItem(repertoire[i][0], repertoire[i][1], repertoire[i][2], repertoire[i][3], repertoire[i][4], repertoire[i][5]));
                if (repertoire[i][5] == "true"){
                	isFinished = true;
                }
                else {
                	isFinished = false;
                }
            }
     
            // We sleep for 3 seconds here to show how the empty view appears in the interim.
            // The empty view is set in the StackWidgetProvider and should be a sibling of the
            // collection view.
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
     
        public void onDestroy() {
            // In onDestroy() you should tear down anything that was setup for your data source,
            // eg. cursors, connections, etc.
            mWidgetItems.clear();
        }
     
        public int getCount() {
            return mCount;
        }
     
        public RemoteViews getViewAt(int position) {
            // position will always range from 0 to getCount() - 1.
     
            // We construct a remote views item based on our widget item xml file, and set the
            // text based on the position.
            RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
            rv.setTextViewText(R.id.titre, mWidgetItems.get(position).titre);
            rv.setTextViewText(R.id.description, mWidgetItems.get(position).description);
            rv.setTextViewText(R.id.url, mWidgetItems.get(position).site);
            rv.setTextViewText(R.id.ancienprix, mWidgetItems.get(position).ancienprix);
            rv.setTextViewText(R.id.nouveauprix, mWidgetItems.get(position).nouveauPrix);
     
            if (isFinished == false) {
            	rv.setInt(R.id.isFinished, "setBackgroundColor", android.graphics.Color.GREEN);
            } else {
            	rv.setInt(R.id.isFinished, "setBackgroundColor", android.graphics.Color.RED);
            }
     
            // Next, we set a fill-intent which will be used to fill-in the pending intent template
            // which is set on the collection view in StackWidgetProvider.
            Bundle extras = new Bundle();
            extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
            Intent fillInIntent = new Intent();
            fillInIntent.putExtras(extras);
            rv.setOnClickFillInIntent(R.id.titre, fillInIntent);
            rv.setOnClickFillInIntent(R.id.description, fillInIntent);
            rv.setOnClickFillInIntent(R.id.url, fillInIntent);
            rv.setOnClickFillInIntent(R.id.ancienprix, fillInIntent);
            rv.setOnClickFillInIntent(R.id.nouveauprix, fillInIntent);
     
            // You can do heaving lifting in here, synchronously. For example, if you need to
            // process an image, fetch something from the network, etc., it is ok to do it here,
            // synchronously. A loading view will show up in lieu of the actual contents in the
            // interim.
            try {
                System.out.println("Loading view " + position);
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
     
            // Return the remote views object.
            return rv;
        }
     
        public RemoteViews getLoadingView() {
            // You can create a custom loading view (for instance when getViewAt() is slow.) If you
            // return null here, you will get the default loading view.
            return null;
        }
     
        public int getViewTypeCount() {
            return 1;
        }
     
        public long getItemId(int position) {
            return position;
        }
     
        public boolean hasStableIds() {
            return true;
        }
     
        public void onDataSetChanged() {
            // This is triggered when you call AppWidgetManager notifyAppWidgetViewDataChanged
            // on the collection view corresponding to this factory. You can do heaving lifting in
            // here, synchronously. For example, if you need to process an image, fetch something
            // from the network, etc., it is ok to do it here, synchronously. The widget will remain
            // in its current state while work is being done here, so you don't need to worry about
            // locking up the widget.
        }
    }

  2. #2
    Membre Expert
    Avatar de Hephaistos007
    Profil pro
    Enseignant Chercheur
    Inscrit en
    Décembre 2004
    Messages
    2 493
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 493
    Par défaut
    J'aurais plutôt redéfini la méthode getView de l'Adapter pour y gérer cela.
    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  3. #3
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    108
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 108
    Par défaut
    Merci pour votre réponse.

    Pouvez-vous me donner un exemple sur mon cas svp en utilisant le getview?

  4. #4
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    @Hephaistos
    Mais y a pas d'adapter là... on est dans un stacked widget.... pas d'Adapter... mais un StackRemoteViewsFactory... (qui ressemble beaucoup à un adapter ceci dit).

    A quoi sert le "public Boolean isFinished = false;"
    (au passage, Eclipse devrait mettre un warning "auto-boxing").... la déclaration correcte étant:
    "public Boolean isFinished = Boolean.FALSE;" (objet, nullable)
    ou
    "public boolean isFinished = false;" (base-type)

    Quel est l'interêt du:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    d'autant que la fonction getLoadingView() renvoit null ?


    Il me semble que le code a un soucis... il y a un boolean isFinished pour tout le factory.... et qui est utilisé pour toutes les views (getViewAt)... donc tous les éléments seront de la même couleur....

    En fait, tout le code du onCreate me semble étrange....On dirait que la signature du constructeur de WidgetItem soit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public WidgetItem(String name, String desc, Stirng url, String newPrice, String oldPrice, String ended)
    A mon avis il serait plus judicieux de bénéficier du typage fort de Java:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public WidgetItem(String name, String desc, URL url, BigDecimal amount1, BigDecimal amount2, Currency currency, boolean ended)
    Ensuite le code du onCreate commence par parser une double array de String pour créer des WidgetItem...
    Pourquoi ne pas simplement avoir:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    mWidgetItems = new WidgetItem[] {
         new WidgetItem("HP Touchpad", "descriptionHP", new URL("http://google.frfrfr"), new BigDecimal(99), new BigDecimal(80), true),
         new WidgetItem("test1", "desc1", new URL("http://monsite1.fr"), new BigDecimal(10), new BigDecimal(80), false),
         ...
    };
    Et dans le code de getViewAt():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    public RemoteViews getViewAt(int position) {
            // position will always range from 0 to getCount() - 1.
            WidgetItem item = mWidgetItems[position];
     
            NumberFormat formatter = NumberFormat.getCurrencyInstance();
            formatter.setCurrency(item.currency);
     
            // We construct a remote views item based on our widget item xml file, and set the
            // text based on the position.
            RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
            rv.setTextViewText(R.id.titre, item.titre);
            rv.setTextViewText(R.id.description, item.description);
            rv.setTextViewText(R.id.url, item.url.toString()); 
            rv.setTextViewText(R.id.ancienprix, formatter.format(mContext.ancienprix));
            rv.setTextViewText(R.id.nouveauprix, formatter.format(nouveauPrix));
            rv.setInt(R.id.isFinished, "setBackgroundColor", item.ended ? android.graphics.Color.RED : android.graphics.Color.GREEN);
     
    }

  5. #5
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    108
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 108
    Par défaut
    Bonjour et d'abord merci pour ta réponse complète.

    J'ai suivi tes conseils, pour le typage, j'ai cependant gardé un String pour les prix 1 et 2 car je ne sais pas encore trop comment je vais les gérer.

    Cependant, après avoir fait tes modifs, rien ne s'affiche dans la listeiew de mon widget. J'ai vu que tu avais utilisé un tableau pour mWidgetItems, pour ma part j'utilisais une liste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
    J'ai donc adapté un peut le code que tu avais fait mais aucun item ne s'affiche.

    Voici le code de la classe WidgetItem :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    import java.net.URL;
     
    public class WidgetItem {
        public String titre, description ;
        URL site;
        String ancienprix, nouveauPrix;
        boolean ended;
     
     
        public WidgetItem(String titre, String description, URL site, String ancienprix, String nouveauPrix, boolean ended) {
            this.titre = titre;
            this.description = description;
            this.site = site;
            this.ancienprix = ancienprix;
            this.nouveauPrix = nouveauPrix;
            this.ended = ended;
        }
    }
    Et celui de StackWidgetService.java :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
     
    import java.util.ArrayList;
    import java.util.List;
    import android.appwidget.AppWidgetManager;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.widget.RemoteViews;
    import android.widget.RemoteViewsService;
     
    import java.net.MalformedURLException;
    import java.net.URL;
     
    public class StackWidgetService extends RemoteViewsService {
        @Override
        public RemoteViewsFactory onGetViewFactory(Intent intent) {
            return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
        }
    }
     
    class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
        private static int mCount;
        private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
        private Context mContext;
        private int mAppWidgetId;
        public Boolean isFinished = false;
     
        public StackRemoteViewsFactory(Context context, Intent intent) {
            mContext = context;
            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        }
     
        public void onCreate() {
            // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
            // for example downloading or creating content etc, should be deferred to onDataSetChanged()
            // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
     
     
        	try {
    			mWidgetItems.add(new WidgetItem("Produit 1", "desc1", new URL("http://google1.frfrfr"), "10€", "20€", true));
    	    	mWidgetItems.add(new WidgetItem("Produit 2", "desc2", new URL("http://google2.frfrfr"), "10€", "20€", false));
    		} catch (MalformedURLException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
     
            // We sleep for 3 seconds here to show how the empty view appears in the interim.
            // The empty view is set in the StackWidgetProvider and should be a sibling of the
            // collection view.
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
     
        public void onDestroy() {
            // In onDestroy() you should tear down anything that was setup for your data source,
            // eg. cursors, connections, etc.
            mWidgetItems.clear();
        }
     
        public int getCount() {
            return mCount;
        }
     
        public RemoteViews getViewAt(int position) {
            // position will always range from 0 to getCount() - 1.
     
            // We construct a remote views item based on our widget item xml file, and set the
            // text based on the position.
     
            WidgetItem item = mWidgetItems.get(position); 
            // We construct a remote views item based on our widget item xml file, and set the
            // text based on the position.
            RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
            rv.setTextViewText(R.id.titre, item.titre);
            rv.setTextViewText(R.id.description, item.description);
            rv.setTextViewText(R.id.url, item.site.toString()); 
            rv.setTextViewText(R.id.ancienprix, item.ancienprix);
            rv.setTextViewText(R.id.nouveauprix, item.nouveauPrix);
            rv.setInt(R.id.isFinished, "setBackgroundColor", item.ended ? android.graphics.Color.RED : android.graphics.Color.GREEN);
     
            // Next, we set a fill-intent which will be used to fill-in the pending intent template
            // which is set on the collection view in StackWidgetProvider.
            Bundle extras = new Bundle();
            extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
            Intent fillInIntent = new Intent();
            fillInIntent.putExtras(extras);
            rv.setOnClickFillInIntent(R.id.titre, fillInIntent);
            rv.setOnClickFillInIntent(R.id.description, fillInIntent);
            rv.setOnClickFillInIntent(R.id.url, fillInIntent);
            rv.setOnClickFillInIntent(R.id.ancienprix, fillInIntent);
            rv.setOnClickFillInIntent(R.id.nouveauprix, fillInIntent);
     
            // You can do heaving lifting in here, synchronously. For example, if you need to
            // process an image, fetch something from the network, etc., it is ok to do it here,
            // synchronously. A loading view will show up in lieu of the actual contents in the
            // interim.
            try {
                System.out.println("Loading view " + position);
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
     
            // Return the remote views object.
            return rv;
        }
     
        public RemoteViews getLoadingView() {
            // You can create a custom loading view (for instance when getViewAt() is slow.) If you
            // return null here, you will get the default loading view.
            return null;
        }
     
        public int getViewTypeCount() {
            return 1;
        }
     
        public long getItemId(int position) {
            return position;
        }
     
        public boolean hasStableIds() {
            return true;
        }
     
        public void onDataSetChanged() {
            // This is triggered when you call AppWidgetManager notifyAppWidgetViewDataChanged
            // on the collection view corresponding to this factory. You can do heaving lifting in
            // here, synchronously. For example, if you need to process an image, fetch something
            // from the network, etc., it is ok to do it here, synchronously. The widget will remain
            // in its current state while work is being done here, so you don't need to worry about
            // locking up the widget.
        }
    }

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Peut être parceque mCount est à 0....

    Bon... array ou collection, dans le cas présent c'est la même chose vu que la collection est une ArrayList<> (donc ... une array), et que la construction est statique (ou presque puisque dans le onCreate).
    La seule chose qui change c'est la manière d'y accéder:
    array.length collection.size()
    array[idx] collection.get(idx)

    Pourquoi conserver mCount... utiliser directement la valeur du contenant est plus "dynamique" (et moins bug-prone)... donc array.length ou collection.size()

    Ensuite juste une remarque sur l'intent à la fin... je ne sais pas si c'est pas des "PendingIntent" qu'il faut, et dans ce cas... enfin bref on verra plus tard.
    En tous cas, tu fais un setIntent sur toutes les views du layout... pourquoi ne pas simplement fare un setOnClickIntent sur le layout lui-meme ? (ca permettra de pouvoir cliquer n'importe ou dans le layout plutot que précisément sur un objet potentiellement petit si le texte n'est pas grand)

    Quand je dis sur le layout, je veux dire sur le ViewGroup à la racine du layout...
    R.layout.widget_item doit forcément commencer par un ViewGroup (qui contient les autres views), c'est celui-ci qui pourrait être identifié (R.id.viewGroup par exemple), et recevoir l'info du onClick (éventuellement forcer les views dedans à être non clickable).

Discussions similaires

  1. Réponses: 5
    Dernier message: 12/05/2015, 13h40
  2. Droits d'accès sur les Items d'une Liste
    Par mimosa803 dans le forum SharePoint
    Réponses: 30
    Dernier message: 11/05/2009, 20h28
  3. [Infobulle]sur les item d'une liste déroulante
    Par mamiberkof dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 24/05/2007, 11h31
  4. [VBA] événements souris sur un item d'une listview
    Par DJBORIE dans le forum VBA Access
    Réponses: 11
    Dernier message: 13/04/2007, 15h08
  5. Se positionner sur un item d'une liste déroulante
    Par pyxosledisciple dans le forum IHM
    Réponses: 1
    Dernier message: 08/02/2006, 20h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo