Android - Ajouter dynamiquement des vues dans la vue

148

J'ai une mise en page pour une vue -

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="0px"
    android:orientation="vertical">

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/items_header"
        style="@style/Home.ListHeader" />

    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/items_none"
        android:visibility="gone"
        style="@style/TextBlock"
        android:paddingLeft="6px" />

    <ListView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/items_list" />


</LinearLayout>

Ce que je veux faire, c'est dans mon activité principale avec une mise en page comme celle-ci

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="0px"
    android:id="@+id/item_wrapper">
</LinearLayout>

Je souhaite parcourir mon modèle de données et injecter plusieurs vues constituées de la première mise en page dans la mise en page principale. Je sais que je peux le faire en construisant les contrôles complètement dans le code, mais je me demandais s'il y avait un moyen de créer dynamiquement les vues afin que je puisse continuer à utiliser une mise en page au lieu de tout mettre dans le code.

Josh
la source
Vous pouvez vérifier la réponse pour ce stackoverflow.com/questions/3995215/…
Dites-moi comment

Réponses:

230

Utilisez le LayoutInflaterpour créer une vue basée sur votre modèle de disposition, puis injectez-la dans la vue là où vous en avez besoin.

LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.your_layout, null);

// fill in any details dynamically here
TextView textView = (TextView) v.findViewById(R.id.a_text_view);
textView.setText("your text");

// insert into main view
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.insert_point);
insertPoint.addView(v, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));

Vous devrez peut-être ajuster l'index à l'endroit où vous souhaitez insérer la vue.

En outre, définissez les LayoutParams en fonction de la manière dont vous souhaitez qu'ils tiennent dans la vue parent. par exemple avec FILL_PARENT, ou MATCH_PARENT, etc.

Mark Fisher
la source
2
c'est là où vous voulez placer la mise en page générée dynamiquement dans votre vue principale. c'est le peu que vous devez remplir à partir de votre propre code.
Mark Fisher
Pour ceux qui veulent essayer ceci maintenant - l'inflateur de mise en page obtenu comme indiqué dans la première ligne résout toujours mais ne semble pas fonctionner, utilisez plutôtgetLayoutInflater()
Brendan
2
Utilisez à LayoutInflater vi = getLayoutInflater();partir d'une activité pour préserver le thème de l'activité que vous n'obtiendrez pas autrement.
akarthik10
1
@MrG Vous devriez soulever une question distincte sur SO. Cette question concerne la création dynamique de vues et non les fragments.
Mark Fisher
2
@Arsh Si vous avez une nouvelle question et un problème spécifique, posez une question SO séparée détaillant le code que vous avez essayé qui ne fonctionne pas au lieu de commenter ici.
Mark Fisher
36

Voir la LayoutInflaterclasse.

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup parent = (ViewGroup)findViewById(R.id.where_you_want_to_insert);
inflater.inflate(R.layout.the_child_view, parent);
Gabriel Negut
la source
comment puis-je ajouter onClicklistener aux vues individuelles qui ont été gonflées.Veuillez fournir un extrait
Sagar Devanga
20

Cela ressemble à ce que vous voulez vraiment un ListView avec un adaptateur personnalisé pour gonfler la disposition spécifiée. À l'aide d'un ArrayAdapter et de la méthode, notifyDataSetChanged()vous avez un contrôle total sur la génération et le rendu des vues.

Jetez un œil à ces tutoriels

Aleadam
la source
14

Pour rendre la réponse de @Mark Fisher plus claire, la vue insérée gonflée doit être un fichier xml sous le dossier de mise en page mais sans mise en page (ViewGroup) comme LinearLayout, etc. à l'intérieur. Mon exemple:

res / layout / my_view.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/i_am_id"
    android:text="my name"
    android:textSize="17sp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"/>

Ensuite, le point d'insertion doit être une disposition comme LinearLayout:

res / layout / activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/aaa"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/insert_point"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </LinearLayout>

</RelativeLayout>

Ensuite, le code devrait être

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shopping_cart);

    LayoutInflater inflater = getLayoutInflater();
    View view = inflater.inflate(R.layout.my_view, null);
    ViewGroup main = (ViewGroup) findViewById(R.id.insert_point);
    main.addView(view, 0);
}

La raison pour laquelle je poste cette réponse très similaire est que lorsque j'ai essayé d'implémenter la solution de Mark, je suis resté coincé sur le fichier xml dois-je utiliser pour insert_point et la vue enfant. J'ai d'abord utilisé la mise en page dans la vue enfant et cela ne fonctionnait absolument pas, ce qui m'a pris plusieurs heures à comprendre. J'espère donc que mon exploration pourra faire gagner du temps aux autres.

York Yang
la source
@York Yang comment puis-je obtenir des identifiants de vies ajoutés ici si nous ajoutons plus d'une vue en utilisant la boucle for.
Rahul Kushwaha
5
// Parent layout
LinearLayout parentLayout = (LinearLayout)findViewById(R.id.layout);

// Layout inflater
LayoutInflater layoutInflater = getLayoutInflater();
View view;

for (int i = 1; i < 101; i++){
    // Add the text layout to the parent layout
    view = layoutInflater.inflate(R.layout.text_layout, parentLayout, false);

    // In order to get the view we have to use the new view with text_layout in it
    TextView textView = (TextView)view.findViewById(R.id.text);
    textView.setText("Row " + i);

    // Add the text view to the parent layout
    parentLayout.addView(textView);
}
Tienanhvn
la source
1
Bien que cet extrait de code puisse être la solution, inclure une explication contribue vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question aux lecteurs à l'avenir, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
yivi
Comment puis-je obtenir des identifiants de différentes vues créées à l'aide de For Loop.
Rahul Kushwaha