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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé 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
    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 970
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

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

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 970
    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.

  3. #3
    Membre confirmé 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
    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 970
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

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

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 970
    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.

  5. #5
    Membre confirmé 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
    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 970
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

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

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 970
    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);

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