Establecer un ancho máximo en un ViewGroup

¿Cómo configuro el ancho máximo de un ViewGroup? Estoy usando una actividad Theme.Dialog , sin embargo, esto no se ve tan bien cuando cambian de tamaño a pantallas más grandes, también es ligero y no quiero que ocupe toda la pantalla.

Intenté esta sugerencia en vano. Además, no hay propiedad android:maxWidth como algunas vistas.

¿Hay alguna manera de restringir la raíz LinearLayout para que solo sea (por ejemplo) 640 dip? Estoy dispuesto a cambiar a otro ViewGroup para esto.

¿Alguna sugerencia?

Una opción que es lo que hice es extender LinearLayout y anular la función onMeasure. Por ejemplo:

 public class BoundedLinearLayout extends LinearLayout { private final int mBoundedWidth; private final int mBoundedHeight; public BoundedLinearLayout(Context context) { super(context); mBoundedWidth = 0; mBoundedHeight = 0; } public BoundedLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BoundedView); mBoundedWidth = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_width, 0); mBoundedHeight = a.getDimensionPixelSize(R.styleable.BoundedView_bounded_height, 0); a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Adjust width as necessary int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); if(mBoundedWidth > 0 && mBoundedWidth < measuredWidth) { int measureMode = MeasureSpec.getMode(widthMeasureSpec); widthMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedWidth, measureMode); } // Adjust height as necessary int measuredHeight = MeasureSpec.getSize(heightMeasureSpec); if(mBoundedHeight > 0 && mBoundedHeight < measuredHeight) { int measureMode = MeasureSpec.getMode(heightMeasureSpec); heightMeasureSpec = MeasureSpec.makeMeasureSpec(mBoundedHeight, measureMode); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } 

Entonces tu XML usaría la clase personalizada:

    

Y la entrada del archivo attr.xml

     

EDITAR: Este es el código real que estoy usando ahora. Esto aún no está completo, pero funciona en la mayoría de los casos.

Sobre la base de la respuesta original de Chase (+1), haría un par de cambios (que se detallan a continuación).

  1. Tendría el ancho máximo establecido a través de un atributo personalizado (xml debajo del código)

  2. super.measure() a super.measure() primero y luego haría la Math.min(*) . Con el código de respuestas original, podemos encontrar problemas cuando el tamaño de entrada configurado en MeasureSpec es LayoutParams.WRAP_CONTENT o LayoutParams.FILL_PARENT . Como estas constantes válidas tienen valores de -2 y -1 respetivamente, el Math.min(*) original Math.min(*) vuelve inútil ya que preservará estos valores sobre el tamaño máximo, y dicen que el WRAP_CONTENT medido es más grande que nuestro tamaño máximo, esta verificación no Atrapalo. Me imagino que el OP estaba pensando en dims exactos solamente (para lo cual funciona muy bien)

     public class MaxWidthLinearLayout extends LinearLayout { private int mMaxWidth = Integer.MAX_VALUE; public MaxWidthLinearLayout(Context context) { super(context); } public MaxWidthLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthLinearLayout); mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthLinearLayout_maxWidth, Integer.MAX_VALUE); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //get measured height if(getMeasuredWidth() > mMaxWidth){ setMeasuredDimension(mMaxWidth, getMeasuredHeight()); } } } 

y el atributo xml

      

Aquí hay un mejor código para la respuesta de Dori.

En el método onMeasure , si llama a super.onMeasure(widthMeasureSpec, heightMeasureSpec); primero en el método, entonces no se cambiará el ancho de todos los objetos en el diseño. Porque se inicializaron antes de establecer el ancho del diseño (principal).

 public class MaxWidthLinearLayout extends LinearLayout { private final int mMaxWidth; public MaxWidthLinearLayout(Context context) { super(context); mMaxWidth = 0; } public MaxWidthLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MaxWidthLinearLayout); mMaxWidth = a.getDimensionPixelSize(R.styleable.MaxWidthLinearLayout_maxWidth, Integer.MAX_VALUE); a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); if (mMaxWidth > 0 && mMaxWidth < measuredWidth) { int measureMode = MeasureSpec.getMode(widthMeasureSpec); widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, measureMode); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } 

Y aquí hay un enlace para el uso de xml attr:
http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/

Gracias por esta pregunta y respuestas. Su respuesta me ha ayudado mucho, y espero que ayude a alguien más en el futuro también.

Ahora android.support.constraint.ConstraintLayout hace más fácil. Simplemente ajuste su vista (de cualquier tipo) con ConstraintLayout, y configure los siguientes atributos para la vista:

 android:layout_width="0dp" app:layout_constraintWidth_default="spread" app:layout_constraintWidth_max="640dp" 

http://tools.android.com/recent/constraintlayoutbeta5isnowavailable

Agregue una capa Diseño externo o Grupo de visualización a su archivo de diseño actual. El alto y ancho de este diseño será el alto / ancho máximo. Ahora su diseño interior se puede configurar para ajustar el contenido y está limitado por el diseño externo. P.ej:

        

Aquí hay una respuesta simple,

El ancho / alto parece que siempre deben establecerse juntos. Esto está funcionando en mi opinión.

   

El elemento primario del botón está configurado para ajustar el contenido, por lo que se reduce, pero hasta un máximo de 400 de ancho (4 botones).