Android: agregar vistas dinámicamente a la vista

148

Tengo un diseño para una vista.

<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>

Lo que quiero hacer es en mi actividad principal con un diseño como este

<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>

Quiero recorrer mi modelo de datos e inyectar múltiples vistas que consisten en el primer diseño en el diseño principal. Sé que puedo hacer esto construyendo los controles completamente dentro del código, pero me preguntaba si había una manera de construir dinámicamente las vistas para poder continuar usando un diseño en lugar de poner todo en el código.

Josh
fuente
Puede consultar la respuesta para este stackoverflow.com/questions/3995215/…
Dime cómo el

Respuestas:

230

Use LayoutInflaterpara crear una vista basada en su plantilla de diseño y luego inyéctela en la vista donde la necesite.

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));

Puede que tenga que ajustar el índice donde desea insertar la vista.

Además, establezca los LayoutParams de acuerdo con la forma en que desea que se ajuste a la vista principal. por ejemplo con FILL_PARENT, o MATCH_PARENT, etc.

Mark Fisher
fuente
2
es donde quiera poner el diseño generado dinámicamente en su vista principal. ese es el bit que debe completar desde su propio código.
Mark Fisher
Para aquellos que quieren probar esto ahora - el inflador diseño obtenido como se muestra en la primera línea todavía resuelve, pero no parece que el trabajo, en lugar de utilizargetLayoutInflater()
Brendan
2
Úselo LayoutInflater vi = getLayoutInflater();de una actividad para preservar el tema de actividad que de otro modo no obtendrá.
akarthik10
1
@MrG Debería plantear una pregunta separada sobre SO. Esta pregunta trata sobre cómo crear vistas dinámicamente, no sobre fragmentos.
Mark Fisher
2
@Arsh Si tiene una nueva pregunta y un problema específico, plantee una pregunta SO separada que detalle qué código ha probado que no funciona en lugar de comentar aquí.
Mark Fisher
36

Ver la LayoutInflaterclase

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
fuente
¿Cómo agrego onClicklistener a las vistas individuales que se inflan? Proporcione un fragmento
Sagar Devanga
14

Para que la respuesta de @Mark Fisher sea más clara, la vista insertada que se está inflando debe ser un archivo xml debajo de la carpeta de diseño pero sin un diseño (ViewGroup) como LinearLayout, etc. Mi ejemplo:

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"/>

Luego, el punto de inserción debe ser un diseño como 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>

Entonces el código debería ser

@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 razón por la que publico esta respuesta muy similar es que cuando traté de implementar la solución de Mark, me quedé atascado en qué archivo xml debería usar para insert_point y la vista secundaria. En primer lugar, utilicé el diseño en la vista infantil y no funcionaba por completo, lo que me llevó varias horas descubrir. Así que espero que mi exploración pueda ahorrarle tiempo a otros.

York Yang
fuente
@York Yang, ¿cómo puedo agregar Id's de vies aquí si agregamos más de una vista usando for loop?
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
fuente
1
Si bien este fragmento de código puede ser la solución, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código.
yivi
¿Cómo puedo obtener ID de diferentes vistas creadas usando For Loop?
Rahul Kushwaha