2013-05-14 4 views
0

Je suis intéressé à remplir un écran/une activité avec un nombre défini par l'utilisateur de vues identiques. Chaque vue aura exactement la même mise en page: couple TextViews et quelques boutons. Le fait est que chaque bouton contrôlera ce que chaque TextView affichera.Ajouter dynamiquement plusieurs vues et classes à la vue actuelle

La façon dont je pensais l'implémenter était d'avoir une classe XML et une classe Java. Puis, en fonction du nombre entré par l'utilisateur, remplir l'écran avec autant de vues (en utilisant une boucle for). La question est, peut-elle être faite? Comment? est-ce que j'y pense de la bonne façon?

S'il vous plaît aider avec toute entrée ou réflexions, les exemples de code seront également très bien.

+0

Je n'ai encore rien essayé. J'ai lu le meilleur et le plus efficace pour le faire. J'ai vu des fragments, des inflateurs, et listview. mais je cherche à le faire réagir aux pressions de bouton sur chaque vue supplémentaire séparée. Je n'ai pas trouvé d'explication documentée pour cela. – KingsInnerSoul

+0

Vous devriez supprimer votre question. Vous serez marqué et downvoted comme l'enfer. – Siddharth

+0

c'est une autre chose que je cherchais. comment supprimer des questions? – KingsInnerSoul

Répondre

1

Bien sûr, il peut être fait.

Je pense que le plus facile à votre situation, plus vous pouvez alors étendre facilement, est de créer des fonctions d'assistance qui prennent en charge:

1) créant un écran vide 2) créer un bouton pour un écran 3) créer un textview pour un écran et enfin 4) créer un écran et le remplir

vous devez décider de l'élément racine approprié pour votre point de vue, en fonction de l'enfant que vous avez besoin arragement. Pour simplifier, choisissons un LinearLayout, mais pour un RelativeLayout ou un TableLayout, l'exemple est le même, il ne change que lorsque vous ajoutez les éléments, vous devez utiliser des paramètres supplémentaires pour les placer correctement.

Notez que la fonction permettant de créer une vue personnalisée vide renvoie un ViewGroup ("d'où proviennent toutes les dispositions"). De cette façon, vous travaillez toujours avec ViewGroups et définissez simplement le type de disposition d'écran une fois, dans createCustomView. Ainsi, vous pouvez changer le type d'écrans juste là, et le reste du code ne fonctionnera ...

Voici un code pour votre inspiration:

private ViewGroup createCustomView(Context context) { 

    LinearLayout myCoolNewView=new LinearLayout(context); // or RelativeLayout, etc.. 
    return myCoolNewView; 
} 

private Button createButton(Context context, String buttonText) { 
    Button newButton=new Button(context); 
    newButton.setText(buttonText); 
    return newButton; 
} 

private TextView createText(Context context, String initialText) { 
    TextView newText=new TextView(context); 
    newText.setText(buttonText); 
    return newText; 
} 

private ViewGroup createScreen(Context context, int numberOfButtons, int numberOfTextfields) { 

    ViewGroup newScreen=createCustomView(context); 
    TextView[] textViews=new TextView[numberOfTextFields]; 

    for (int i=0; i<numberOfTextfields; i++) { 
      textViews[i]=createText(context, "hi i am text "+i); 
      newScreen.addView(textViews[i]); // you ideally provide here layoutparams to properly place your buttons 

    } 
    for (int j=0; i<numberOfButtons; j++) { 
      Button button=createButton(context, "hi i am button "+j); 
      button.setOnClickListener(new OnClickListener() { 
       public void onClick (View clickedView) { 
        // here you have a button keypress and you know all the textviews 
        textView[i%j].setText("hey you pressed me"); 
       } 
      }); 
      newScreen.addView(button); 
    } 
    return newScreen; 
} 

Alors maintenant, vous pouvez:

ViewGroup screen1=createScreen(context, 10, 10); 
ViewGroup screen2=createScreen(context, 5, 3); 
ViewGroup screen3=createScreen(context, 2, 5); 

et ajoutez les écrans à une mise en page de parent, à un ViewFlipper, à un ViewSwitcher, etc ... comme ceci:

ViewGroup parentLayoutOfAllScreens=findViewById(R.id.root_of_screens); 
parentLayoutOfAllScreens.addView(screen1); 
parentLayoutOfAllScreens.addView(screen2); 
parentLayoutOfAllScreens.addView(screen3); 

Dans le fichier XML, il suffit de créer la mise en page racine, et nommez-le root_of_screens ...

bon codage !!! Je suppose qu'il y aura des erreurs dans le code ci-dessus, je l'ai juste tapé ici, mais j'espère que vous aurez l'idée et l'adaptera à vos besoins!

EDIT: v2.0: Extension d'une vue Créez un nouveau fichier .java nommé "MyCoolScreen".java » ou tout autre nom, dans le même dossier où votre activité est (pour simplifier):

package ........ 
public class MyCoolScreen extends LinearLayout { 

    /** Now every view holds its own buttons, and they are private, it's good for encapsulating */ 
    private TextView[] mTextViews; // <-- as a convention, members should start with "m" 
    private Button[] mButtons; 
    private UserPressedButtons mUserPressedButtonsListener; // See below 

    /** The following constructors must always be present for a custom view, and must always call super */ 
    public MyCoolScreen(Context context) { 
     // This is the constructor you will use when creating your view programmatically 
     super(context); 
    } 

    public MyCoolScreen(Context context, AttributeSet attrs) { 

     // This is the constructor Android calls when you include your custom view in an XML 
     // You can do this too!! 
     // The ATTRS will then include your numberofbuttons and numberoftextfields from the XML 
     // this is beyond the example, but read about it, it's interesting 

     super(context, attrs); // this MUST ALWAYS be here for custom views, or they will not work. 
           // it tells the parent view to continue the construction. 
    } 

    public MyCoolScreen(Context context, AttributeSet attrs, int defStyle) { 
     // Another constructor Android calls from the XML 
     super(context, attrs, defStyle); 
    } 


    /** We create an "init" method to initialize this view from outside */ 
    public void init(int numberOfTextViews, int numberOfButtons) { 
     createScreen(numberOfTextViews, numberOfButtons); 
    } 


    /** This is the same */ 
    private Button createButton(Context context, String buttonText) { 
     Button newButton=new Button(context); 
     newButton.setText(buttonText); 
     return newButton; 
    } 

    /** This is the same */ 
    private TextView createText(Context context, String initialText) { 
     TextView newText=new TextView(context); 
     newText.setText(buttonText); 
     return newText; 
    } 

    /** We tweak this function so it doesnt return a view, but rather fills up this one :) */ 

    private void createScreen(int numberOfButtons, int numberOfTextfields) { 

     ViewGroup newScreen=this; // It's this view the one we gonna fill up! 
     mTextViews=new TextView[numberOfTextfields]; 
     mButtons=new Button[numberOfButtons]; 
     Context context=getContext(); // Views always know their context after constructed 

     for (int i=0; i<numberOfTextfields; i++) { 
       mTextViews[i]=createText(context, "hi i am text "+i); 
       newScreen.addView(textViews[i]); // you ideally provide here layoutparams to properly place your buttons 
     } 

     for (int j=0; i<numberOfButtons; j++) { 
       Button button=createButton(context, "hi i am button "+j); 
       button.setId(j); 
       button.setOnClickListener(new OnClickListener() { 
        public void onClick (View clickedView) { 
         // here you have a button keypress and you know all the textviews 
         if (mUserPressedButtonsListener!=null) mUserPressedButtonsListener.OnButtonPressed(j); 
         textView[i%j].setText("hey you pressed me"); 
        } 
       }); 
       mButtons[j]=button; 
       newScreen.addView(button); 
     } 
    } 

    public interface UserPressedButtons { 
     public void OnButtonPressed(int buttonNumber); 
    } 

    public void setUserPressedButtonsListener (UserPressedButtons listener) { 
     mUserPressedButtonsListener=listener; 
    } 
} 

Ok, maintenant pour pouvoir l'utiliser, dans votre activité que vous pouvez faire:

import ....... .MyCoolScreen; 
    import ....... .MyCoolScreen.UserPressedButtons; 

    . 
    . 
    . 

    MyCoolScreen screen1=new MyCoolScreen(context); 
    screen1.init(5,5); // initializes the screen. 

    myRootLayout.addView(screen1); 

Ce qui est cool à ce sujet, la fonctionnalité est maintenant totalement encapsulée dans votre vue personnalisée, et elle réside dans un autre fichier .java, donc votre code d'activité est très propre, et vous pouvez même étendre la fonctionnalité View sans la rendre moche

pratique courante pour créer des interfaces et des auditeurs pour vos points de vue à communiquer avec le monde extérieur, donc par exemple, nous pouvons faire:

 screen1.setUserPressedButtonsListener(new MyCoolScreen.UserPressedButtons() { 
     @Override 
     public void OnButtonPressed (int number) { 
       // you know the user pressed button "number", and you can do stuff about it without 
       // having to include it inside the MyCoolScreen class. Of course in your example you 
       // don't need this at the moment, because the View will modify its textfield, but suppose 
       // one of the buttons is "rocket launch" , that is something you will handle at the activity level, ie. 

       if (number==ROCKET_LAUNCH) RocketLauncher.setTarget(10,10).launch(); // Your MyCoolScreen doesnt know how to launch rockets, but your activity maybe yes... 

     } 
    }); 

Vous pouvez faire toutes sortes de choses cool avec votre nouvelle vue personnalisée. Par exemple, vous pouvez définir:

 @Override 
    public void OnDraw(Canvas c) { 
      c.drawEllipse ... 
      c.drawRectangle .... 
    } 

Et vous pouvez peindre des cercles, des lignes, etc ... sur vos textfields & boutons :) Pour que cela fonctionne, vous devez mettre

setWillNotDraw(false) on the constructor. 

Il peut-être des erreurs, il suffit de taper le code ici, mais j'espère que cela vous aide!

+0

Je n'ai pas testé ce code, mais il semble correct. Tout comme ce que je pensais faire. La chose qui me manquait, et votre message a soulevé que la pensée pour la solution, était de générer des ID uniques pour chaque élément créé. J'ajouterais à votre code '.setId (i);' pour chaque élément ajouté. :-) Il est tard, et je vais le tester demain et répondra. -Cheers – KingsInnerSoul

+0

noprob :) Mais maintenant que vous connaissez setId, laissez-moi vous parler de setTag(). C'est le cousin le plus âgé, de cette façon vous pouvez assigner n'importe quoi à un bouton, pas seulement un identifiant. Vous pouvez faire: view.setTag ("mon bouton"), ou view.setTag (new String [] {"button1", "screen2"}) ou encore view.setTag (nouveau MyStuffInfo (a, b, c, d , e))) .... et plus tard view.getTag() pour l'obtenir :) – rupps

+0

Cela fonctionne comme un charme (après avoir grandement modifié votre code pour correspondre à mes perspectives). Maintenant, j'ai des problèmes avec les ID et les balises et l'ordre des éléments dans le LinearLayout. Vous ne pouvez pas trouver le bon moyen de rappeler les TextViews dans onClick pour les boutons. – KingsInnerSoul

0

Add and Remove Views in Android Dynamically?

Cela vous aide à la plupart ...

+0

Je l'ai déjà lu auparavant. Ce n'est pas ce que je cherche. Je cherche à ajouter dynamiquement plusieurs vues - qui proviennent d'une vue - et être capable de contrôler les événements pour chaque vue indépendamment. Des événements tels que la modification de TextViews et d'ImageViews pour chaque vue séparée. – KingsInnerSoul

Questions connexes