¿Por qué LayoutInflater ignora los parámetros de diseño layout_width y layout_height que he especificado?

He tenido problemas graves para que LayoutInflater funcione como se esperaba, y también lo hicieron otras personas: ¿Cómo usar layoutinflator para agregar vistas en tiempo de ejecución? .

¿Por qué LayoutInflater ignora los parámetros de diseño que he especificado? Por ejemplo, ¿por qué no se layout_height valores de layout_width y layout_height de mis recursos XML?

Investigué este problema, me referí a los documentos de LayoutInflater y establecí un pequeño proyecto de demostración de muestra. Los siguientes tutoriales muestran cómo rellenar dinámicamente un diseño utilizando LayoutInflater .

Antes de comenzar, consulte los parámetros de LayoutInflater.inflate() :

  • recurso : ID para cargar un recurso de diseño XML (p. ej., R.layout.main_page )
  • root : vista opcional para ser el padre de la jerarquía generada (si attachToRoot es true ), o simplemente un objeto que proporciona un conjunto de valores de LayoutParams para la raíz de la jerarquía devuelta (si attachToRoot es false )
  • attachToRoot : si la jerarquía inflada se debe asociar al parámetro raíz? Si es falso, root solo se usa para crear la subclase correcta de LayoutParams para la vista raíz en el XML.

  • Devuelve : la vista raíz de la jerarquía inflada. Si se proporcionó root y attachToRoot es true , esto es root; de lo contrario, es la raíz del archivo XML inflado.

Ahora para el diseño de muestra y el código.

Diseño principal ( main.xml ):

    

En este contenedor se agrega un TextView por separado, visible como un pequeño cuadrado rojo si los parámetros de diseño se aplican correctamente desde XML ( red.xml ):

   

Ahora LayoutInflater se usa con varias variaciones de parámetros de llamada

 public class InflaterTest extends Activity { private View view; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ViewGroup parent = (ViewGroup) findViewById(R.id.container); // result: layout_height=wrap_content layout_width=match_parent view = LayoutInflater.from(this).inflate(R.layout.red, null); parent.addView(view); // result: layout_height=100 layout_width=100 view = LayoutInflater.from(this).inflate(R.layout.red, null); parent.addView(view, 100, 100); // result: layout_height=25dp layout_width=25dp // view=textView due to attachRoot=false view = LayoutInflater.from(this).inflate(R.layout.red, parent, false); parent.addView(view); // result: layout_height=25dp layout_width=25dp // parent.addView not necessary as this is already done by attachRoot=true // view=root due to parent supplied as hierarchy root and attachRoot=true view = LayoutInflater.from(this).inflate(R.layout.red, parent, true); } } 

Los resultados reales de las variaciones de los parámetros están documentados en el código.

SINOPSIS: Llamar a LayoutInflater sin especificar la raíz lleva a inflar la llamada ignorando los parámetros de diseño del XML. Las llamadas infladas con root no son null y attachRoot=true carga los parámetros de diseño, pero devuelve el objeto raíz nuevamente, lo que evita más cambios de diseño en el objeto cargado (a menos que pueda encontrarlo usando findViewById() ). La convención de llamadas que más te gustaría usar es, por lo tanto, esta:

 loadedView = LayoutInflater.from(context) .inflate(R.layout.layout_to_load, parent, false); 

Para ayudar con los problemas de diseño, el visor de jerarquía es muy recomendable.

andig tiene razón en que una razón común para que LayoutInflater ignore tus layout_params sería porque no se especificó una raíz. Mucha gente piensa que puedes pasar null para root. Esto es aceptable para algunos escenarios, como un diálogo, donde no tiene acceso a la raíz en el momento de la creación. Una buena regla a seguir, sin embargo, es que si tiene root, se lo da a LayoutInflater.

Escribí una publicación en profundidad sobre este tema que puede consultar aquí:

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/