Cómo agregar vistas mediante programación a vistas

179

Digamos que tengo un LinearLayout, y quiero agregarle una Vista, en mi programa desde el código Java. ¿Qué método se usa para esto? No estoy preguntando cómo se hace en XML, lo que sí sé, sino cómo puedo hacer algo similar a este código de muestra.

(One View).add(Another View)

Como uno puede hacer en Swing.

Moki
fuente

Respuestas:

248

Llamar addViewes la respuesta correcta, pero debe hacer un poco más que eso para que funcione.

Si crea una vista a través de un constructor (p. Ej. Button myButton = new Button();), setLayoutParamsDeberá llamar a la vista recién construida, pasando una instancia de la clase interna LayoutParams de la vista principal, antes de agregar su hijo recién construido a la vista principal.

Por ejemplo, puede tener el siguiente código en su onCreate()función suponiendo que su LinearLayout tenga id R.id.main:

LinearLayout myLayout = findViewById(R.id.main);

Button myButton = new Button(this);
myButton.setLayoutParams(new LinearLayout.LayoutParams(
                                     LinearLayout.LayoutParams.MATCH_PARENT,
                                     LinearLayout.LayoutParams.MATCH_PARENT));

myLayout.addView(myButton);

Asegurarse de establecer los LayoutParams es importante. Cada vista necesita al menos un parámetro layout_width y layout_height. También es importante obtener la clase interna correcta. Luché para que las Vistas agregadas a TableRow se mostraran correctamente hasta que descubrí que no estaba pasando una instancia de TableRow.LayoutParams a setLayoutParams de la vista secundaria.

Brian Cooley
fuente
55
¿Cómo crearía la vista mediante programación, pero utilizando un archivo de diseño XML que escribió específicamente para esta nueva vista?
SK9
9
@ SK9 Usaría un LayoutInflater, que puede obtener de un Contexto, generalmente la Actividad actual. Algo así como: LayoutInflater myInflater = getLayoutInflater; Ver myView = myInflater.inflate (R.layout.myLayout, parent, false);
Brian Cooley
1
En realidad, getLayoutInflater () proviene de la clase Window (no Context), y es un método conveniente en Activity.
Brian Cooley
2
Como práctica de codificación, en findViewById, se convierte en ViewGroup o siempre en la forma más genérica de un objeto, de modo que si cambia de LinearLayout a RelativeLayout, no tiene que refactorizar.
Joel Teply
1
Estos son algunos detalles: D
Vivek Solanki
51

para cualquiera que esté interesado:

La mejor manera que encontré es usar el método inflado estático de View.

View inflatedView = View.inflate(context, yourViewXML, yourLinearLayout);

donde yourViewXML es algo como R.layout.myView

tenga en cuenta que necesita un ViewGroup para agregar una vista (que es cualquier diseño que se le ocurra)

así que, por ejemplo, supongamos que tiene un fragmento que se ve inflado y sabe que la vista raíz es un diseño, y desea agregarle una vista:

    View view = getView(); // returns base view of the fragment
    if (view == null)
        return;
    if (!(view instanceof ViewGroup))
        return;

    ViewGroup viewGroup = (ViewGroup) view;
    View popup = View.inflate(viewGroup.getContext(), R.layout.someView, viewGroup);
ndori
fuente
También podría escribir un método estático, algo así addView(View v){ // your code after get view }tomaría una vista encontrada usando findViewById(int resourceID)o inflada como su inflatedView... solo para expandir su ejemplo de fragmento.
zgc7009
22

Esto es tarde pero esto puede ayudar a alguien :) :) Para agregar la vista mediante programación intente como

LinearLayout rlmain = new LinearLayout(this);      
LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);          
LinearLayout   ll1 = new LinearLayout (this);

ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.logo);              
LinearLayout .LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);

iv.setLayoutParams(lp);
ll1.addView(iv);
rlmain.addView(ll1);              
setContentView(rlmain, llp);

Esto creará su vista completa del programa de manera virtual. Puede agregar cualquier cantidad de vistas igual. Espero que esto pueda ayudar. :)

AndroidOptimist
fuente
3

Una forma más de agregar una vista desde la actividad

ViewGroup rootLayout = findViewById(android.R.id.content);
rootLayout.addView(view);
yoAlex5
fuente
0

La idea de establecer restricciones mediante programación puede ser agotadora. Esta solución a continuación funcionará para cualquier diseño, ya sea de restricción, lineal, etc. La mejor manera sería establecer un marcador de posición, es decir, un FrameLayout con las restricciones adecuadas (o la colocación adecuada en otro diseño como lineal) en la posición donde esperaría la vista creada mediante programación. tener.

Todo lo que necesita hacer es inflar la vista mediante programación y de forma secundaria a FrameLayout mediante el addChild()método. Luego, durante el tiempo de ejecución, su vista se inflará y se colocará en la posición correcta. Según la recomendación de Android, debe agregar solo un childView a FrameLayout [enlace] .

Así es como se vería su código, suponiendo que desee crear TextView mediante programación en una posición particular:

Paso 1:

En su diseño que contendría la vista que se inflará, coloque un FrameLayout en la posición correcta y dele una identificación, por ejemplo, "contenedor".

Paso 2 Cree un diseño con elemento raíz como la vista que desea inflar durante el tiempo de ejecución, llame al archivo de diseño como "textview.xml":

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

</TextView>

Por cierto, configure los parámetros de diseño de su frameLayout en wrap_content siempre que no sea así, el diseño del marco será tan grande como el padre, es decir, la actividad, es decir, la pantalla del teléfono.

android:layout_width="wrap_content"
android:layout_height="wrap_content"

Si no se establece, porque una vista secundaria del marco, por defecto, va a la parte superior izquierda del diseño del marco, por lo tanto, su vista simplemente volará a la parte superior izquierda de la pantalla.

Paso 3

En su método oncreate, haga esto:

FrameLayout frameLayout = findViewById(R.id.container);
                TextView textView = (TextView) View.inflate(this, R.layout.textview, null);
                frameLayout.addView(textView);

(Tenga en cuenta que la configuración último parámetro de findViewByIda nully la adición de vista llamando addView()a la vista recipiente (FrameLayout) es el mismo que simplemente fijar la vista inflado mediante el paso trueen tercero parámetro de findViewById(). Para más información, ver este .)

kush
fuente
0

¡Ustedes también deben asegurarse de que cuando anulen onLayout, DEBEN llamar super.onLayoutcon todas las propiedades, o la vista no se inflará!

Oz Shabat
fuente