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 :

Inflater une Vue personnalisée d'un fichier XML, puis changer sa hauteur et sa largeur.


Sujet :

Android

  1. #1
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut Inflater une Vue personnalisée d'un fichier XML, puis changer sa hauteur et sa largeur.
    Bonjour !

    Je me perd dans ce problème depuis un bon moment... Après de longues recherches infructueuses, j'en appelle aux pouvoirs du cr... Heu, j'en appelle à votre aide

    Dans mon application, j'ai créé un layout personnalisé calendrieradmin_day.xml :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="utf-8"?>
    <TableRow xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/CalendrierAdmin_Day_Event_TableRow"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
     
        <!--  <TextView
            android:id="@+id/CalendrierAdmin_Day_Event_TextView_Name"
            android:layout_width="match_parent"
            android:layout_height="fill_parent"
            android:gravity="center" />-->
    </TableRow>
    Pour le moment, c'est simplement un TableRow, mais j'aurais sans doute besoin d'y ajouter des choses plus tard (comme le TextView en commentaires, par exemple).

    J'ai créé trois class : Row, EventRow et EmptyRow. Row est une class abstraite, EventRow et EmptyRow héritent de Row. Row hérite de TableRow.

    Je veux ajouter plusieurs EventRow et EmptyRow dans un TableLayout, et j'ai besoin de paramétrer leur taille de façon dynamique.

    Dans le constructeur de EventRow et de EmptyRow, j'appelle une méthode init(), que voici pour EventRow :

    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
    private void init(Context c, TableLayout root) {    
        root = (TableLayout)LayoutInflater.from(c).inflate(R.layout.calendrieradmin_day_event, root, true);
     
        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) root.getLayoutParams();
     
        lp.height = getHeightOfMinute() * getDuree();
        lp.width = getTheWidth();
     
        /*
        Some other stuff
        ...
        ...
        */
     
        this.setLayoutParams(lp);
     
        root.addView(this);
     
        setOnClickListener(this);
        setOnLongClickListener(this);
    }
    Évidement, ça ne fonctionne pas... l'EventRow n'est pas affiché.

    root est le TableLayout que je passe dans le constructeur. getHeightOfMinute() et getDuree() fonctionnent correctement et me retournent les valeurs (en pixels) auxquelles je m'attend à chaque fois. Auparavant, j'utilisais la méthode inflate() de cette manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    inflate(R.layout.calendrieradmin_day_event, null, false)
    , mais Eclipse me donnait une alerte, comme quoi ce n'était pas bon de passer null comme argument de vue racine. Même si cela fonctionnait, j'ai voulu chercher une solution plus convenable.

    J'utilisais également les méthodes setMinimumHeight() et setMinimumWidth() afin de paramétrer la taille exacte. Là encore, ça fonctionne, mais cette solution ne me convient pas : j'ai envie de comprendre pourquoi utiliser la méthode conventionnelle du LayoutParams ne fonctionne pas chez moi.

    Est-ce que quelqu'un pourrait m'expliquer clairement comment fonctionne la méthode inflate() et ses histoires de vue racine ? Quel type de LayoutParams dois-je appliquer exactement ? Qui y a t-il d'incorrecte dans ma manière de procéder ?

    Merci d'avance

  2. #2
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 969
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 969
    Points : 3 375
    Points
    3 375
    Par défaut
    Fais attention avec les SetWidth certains appareils en tiendront strictement compte et d'autres pas

    Ex: tu définis un bouton de Width : 50px => sur Samsung S4 il sera bien de 50px mais sur un LG Optimus 2x, soit plus petit, égal ou plus grand

    Je me suis une fois cassé la tête pourquoi sur l'Optimus tout était bien affiché mais sur le S4, j'avais des boutons extrêmement petits.

    Si par malheur ton 50px est trop petit pour afficher le texte, tu risques de n'avoir qu'un quart de bouton sur un S4 lol.

    Perso, je travaille de préférence avec des layouts MATCH_PARENT (ou FILL_PARENT) au lieu de WRAP_CONTENT.
    http://developer.android.com/referen...outParams.html

    Ton layout prendre tout la taille en largueur.
    Si la réponse vous a aidé, pensez à cliquer sur +1

  3. #3
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut
    Merci pour la réponse. Mais en attendant, ça ne répond pas vraiment à ma question...

    Tout ce que je cherche à faire pour le moment, c'est afficher mon EventRow, les soucis de convenances, on verra plus tard. D'autant que mon appli est destinée à ne tourner qu'exclusivement sur tablette. Je veux bien utiliser MATCH_PARENT pour la largeur, seulement comment faire ? Par contre, pour la hauteur, là je serais obligé de la définir de façon dynamique, car elle dépend directement de la durée d'un évènement (Oui, en gros, je suis en train de programmer une sorte d'agenda). A la limite je chercherai un moyen d'éviter le pixel comme unité de mesure, ou je débrouillerai avec la propriété weight. Mais le problème reste entier : comment je fais pour changer de LayoutParams ????!!!!

  4. #4
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 969
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 969
    Points : 3 375
    Points
    3 375
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    protected final LayoutParams _layoutParamsMatch = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);


    Je remarque ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.setLayoutParams(lp);
    Perso, je nomme les contrôles au lieu d'utiliser This.
    Assure-toi que le contrôle en question n'est pas null.
    Si la réponse vous a aidé, pensez à cliquer sur +1

  5. #5
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut
    Citation Envoyé par hotcryx Voir le message
    Perso, je nomme les contrôles au lieu d'utiliser This.
    Assure-toi que le contrôle en question n'est pas null.
    Qu'entends-tu exactement par "je nomme les contrôles" ?


    En attendant, je remarque déjà que ça foire rien qu'au niveau de l' "inflentation" ( ?), car juste

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    private void init(Context c, TableLayout root) {	
    		TableRow tr = (TableRow) LayoutInflater.from(c).inflate(R.layout.calendrieradmin_day_event, root, false);
     
                    root.addView(tr);
     
    		setOnClickListener(this);
    		setOnLongClickListener(this);
    }
    ne fonctionne pas. Dans l'activité dans laquelle je créé mes EmptyRow et mes EventRow, il se passe cela :

    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
     
    public class CalendrierAdmin_Day extends ActivityAdmin  {
        /**
        * Des trucs...
        **/
     
        private EventDAO eDao;
     
        private TableLayout tlHours;
     
        private ArrayList<Event> listEvents;
     
        /**
        * D'autres trucs...
        **/
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    	setContentView(R.layout.calendrieradmin_day);
     
            // On récupère tous les Events de la base de données relatif au jour donné
    	eDao = new EventDAO(CalendrierAdmin_Day.this);
    	eDao.open();		
    	listEvents = eDao.selectAllOfThisDay(getDateClicked());
     
            tlHours = (TableLayout)findViewById(R.id.CalendrierAdminDay_TableLayout_Hours);
     
            populate(listEvents);
        }
     
        public void populate(ArrayList<Event> listEvents) {
            tlHours.removeAllViews();
     
            int current_event_index = 0;
    	Calendar cal = Calendar.getInstance();
     
    	DisplayMetrics metrics = new DisplayMetrics();
    	getWindowManager().getDefaultDisplay().getMetrics(metrics);
    	int width = ((metrics.widthPixels / 2) / 4) * 3;
     
    	int minutesDebJour = (int) ((timestamp_deb / 1000) / 60);
    	int minutesFinJour = (int) ((timestamp_fin / 1000) / 60);
    	int current_min = minutesDebJour;
     
    	boolean pair = true;
     
    	while(current_min < minutesFinJour && current_event_index < listEvents.size()) {
    		Event e = listEvents.get(current_event_index);			
    		cal.setTime(e.getDateDeb());
    		int minutesEventDeb = (int) ((cal.getTimeInMillis() / 1000) / 60);
     
    		if(current_min < minutesEventDeb) { // si il y a un "trou" dans le planning				
    			final EmptyRow emptyRow = new EmptyRow(this, minutesDebJour, minutesFinJour, current_min, minutesEventDeb - current_min, width, tlHours);
    			current_min = minutesEventDeb; // la minute courante devient celle de l'évènement
     
    			emptyRow.setHandler(new RowHandler(this, emptyRow));
    		}
     
    		EventColor color;
     
    		if(pair) {
    			pair = false;
    			color = EventColor.BLUE;
    		}
    		else {
    			pair = true;
    			color = EventColor.GREEN;
    		}
     
    //C'est vraiment ici que c'est intéressant	
    		final EventRow eventRow = new EventRow(this, minutesDebJour, minutesFinJour, EventType.NORMAL, width, e, color, tlHours);
    		tlHours.addView(eventRow);
    //	
    		eventRow.setHandler(new RowHandler(this, eventRow));
     
    		current_min += e.getDuree();
     
    		current_event_index++;
    	}
     
    	//On fini éventuellement de remplir le planning
    	if(current_min < minutesFinJour) {
    		EmptyRow emptyRow = new EmptyRow(this, minutesDebJour, minutesFinJour, current_min, minutesFinJour - current_min, width, tlHours);
    		//tlHours.addView(emptyRow);
    		emptyRow.setHandler(new RowHandler(this, emptyRow));
    	}
        }
    }

  6. #6
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 969
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 969
    Points : 3 375
    Points
    3 375
    Par défaut
    Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    root.setLayoutParams(lp);
    au lieu de:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.setLayoutParams(lp);
    Si la réponse vous a aidé, pensez à cliquer sur +1

  7. #7
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut
    Citation Envoyé par hotcryx Voir le message
    Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    root.setLayoutParams(lp);
    au lieu de:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this.setLayoutParams(lp);
    Et bien justement, ça j'aimerais vachement comprendre ! T'es en train de me dire que c'est rigoureusement la même chose dans ce cas ci ?

    root est mon TableLayout alors que this représente l' EventRow (TableRow) que je suis en train de créer, non ? Ce n'est donc pas du tout la même chose, j'imagine...

    PS: j'ai édité mon dernier post

  8. #8
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 969
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 969
    Points : 3 375
    Points
    3 375
    Par défaut
    J'ai jamais dit que c'était la même chose, ce n'était qu'un exemple

    Le This est parfois un faux-ami et comme on peut changer la taille de tous les contrôles, on fait vite une erreur.
    Comme ça peut influencer l'arborescence des contrôles, c'est vite galère pour corriger un seul contrôle.
    On le corrige c'est bon mais pas visuellement car il dépend d'autres contrôles les uns dans les autres.

    Mais tu peux faire comme tu veux, c'est toi le chef lol
    Si la réponse vous a aidé, pensez à cliquer sur +1

  9. #9
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut
    Bah oui mais ce sont les paramètres de mon EventRow que je veux changer, pas ceux de son parent !

    Enfin j'imagine que c'est ça que je dois faire, non ?

    Sérieux, je suis complètement largué

  10. #10
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 969
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 969
    Points : 3 375
    Points
    3 375
    Par défaut
    Il n'y a pas qu'un seul paramètre de layout à changer.

    Tu as les items (ou row de la table) mais également la table.
    Et également les contrôles de chaque row.

    Mets tout en commentaire et vérifie par tâtonnement:

    - d'abord tu n'affiches que la table (vide)
    - ensuite tu ne mets qu'une row avec du contenu
    - tu paramètres le layout de la row
    - tu paramètres les contrôles de la row
    - tu paramètres la table.

    Rem: pour débugger dans l'émulateur: programme Settings/Developer options/Show layout bounds.
    Ca te permet de voir toutes les marges et bords des contrôles, ça aide grandement pour les dimensionner.
    Si la réponse vous a aidé, pensez à cliquer sur +1

  11. #11
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut
    T'es en train de me dire qu'il faut que je change les LayoutParams de tout le layout de mon activité ?!

    Je veux pas être chiant, mais j'ai vraiment besoin d'indication précise sur le principe de fonctionnement. Parce que là, avec des tas d'infos qui se croisent, je suis de plus en plus embrouillé...

  12. #12
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 969
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 969
    Points : 3 375
    Points
    3 375
    Par défaut
    T'es en train de me dire qu'il faut que je change les LayoutParams de tout le layout de mon activité ?!
    Oui si t'as un problème d'affichage et DEBUG comme expliquer plus haut.
    Si la réponse vous a aidé, pensez à cliquer sur +1

  13. #13
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut
    Bon, je vais essayer de me plonger là dedans, histoire d'essayer de comprendre les notions qui m'échappent.

  14. #14
    Membre régulier Avatar de Rappunzell
    Homme Profil pro
    Technicien Help Desk
    Inscrit en
    Novembre 2007
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Technicien Help Desk

    Informations forums :
    Inscription : Novembre 2007
    Messages : 93
    Points : 91
    Points
    91
    Par défaut
    Bien,

    Alors voici les quelques changements que j'ai apporté pour tenter de résoudre mon problème.

    D'abord, j'ai ajouté un TextView à calendrier_day_admin_event.xml avec un texte hautement philosophique dedans :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <TableRow xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/CalendrierAdmin_Day_Event_TableRow"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
     
    	<TextView
    	    android:id="@+id/CalendrierAdmin_Day_Event_TextView_Name"
    	    android:layout_width="match_parent"
    	    android:layout_height="match_parent"
    	    android:gravity="center" 
    	    android:text="prout"/>
    </TableRow>
    Ensuite, j'ai ajouté un attribut à ma class Row :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    protected TableLayout.LayoutParams lp = new TableLayout.LayoutParams();
    En effet, la lecture de cette page (Guide officiel du développeur Android) montre que le LayoutParams d'une vue doit être la sous-classe correspondant à la vue parente (je ne sais pas si je m'exprime bien, mais regardez le schéma qui illustre mes propos).
    Nom : layoutparams.png
Affichages : 459
Taille : 60,5 Ko

    Mes Row étant contenu dans un TableLayout, je dois donc utiliser la class TableLayout.LayoutParams.

    Enfin, la méthode init() de EventRow :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    private void init(Context c, TableLayout root) {	
    	TableRow tr = (TableRow) LayoutInflater.from(c).inflate(R.layout.calendrieradmin_day_event, root, false);
     
    	lp.height = getHeightOfMinute() * getDuree();
    	lp.width = getTheWidth();
     
    	tr.setLayoutParams(lp);
     
    	root.addView(tr);
     
    	setOnClickListener(this);
    	setOnLongClickListener(this);
    }
    Avec un TextView contenant un texte, la largeur est bien prise en compte. Par contre, la hauteur ne l'est pas, pourquoi ?
    Sans TextView, rien n'est affiché.

    Pourrait-on m'aiguiller un peu plus ? Merci

Discussions similaires

  1. Réponses: 13
    Dernier message: 27/10/2006, 11h50
  2. Réponses: 1
    Dernier message: 10/09/2006, 16h09
  3. Faire une liaison externe avec un fichier xml
    Par vodevil dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 11/01/2006, 11h18
  4. Réponses: 3
    Dernier message: 04/01/2006, 20h53
  5. Comment Lire une valeur à partir d'un fichier XML en C++?
    Par Hamdi Hedhili dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 13/12/2005, 10h09

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