Android: ¿por qué no hay maxHeight para una vista?

Las vistas tienen un minHeight pero de alguna manera les falta un maxHeight :

Lo que bash lograr es tener algunos elementos (vistas) llenando un ScrollView . Cuando hay 1..3 elementos, quiero mostrarlos directamente. Lo que significa que ScrollView tiene la altura de 1, 2 o 3 elementos.

Cuando hay 4 o más elementos, quiero que ScrollView deje de expandirse (por lo tanto, maxHeight ) y comience a proporcionar desplazamiento.

Sin embargo, lamentablemente no hay forma de establecer un maxHeight . Así que probablemente tenga que establecer mi altura de ScrollView programáticamente en WRAP_CONTENT cuando haya 1..3 elementos y establecer la altura en 3*sizeOf(View) cuando haya 4 o más elementos.

¿Alguien puede explicar por qué no se proporciona maxHeight , cuando ya hay un minHeight ?

(Por cierto: algunas vistas, como ImageView tienen un maxHeight implementado).

Ninguna de estas soluciones funcionó para lo que necesitaba, que era un ScrollView configurado para wrap_content pero con un maxHeight para que dejara de expandirse después de cierto punto y comenzara a desplazarse. Simplemente anulé el método onMeasure en ScrollView.

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { heightMeasureSpec = MeasureSpec.makeMeasureSpec(300, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 

Puede que esto no funcione en todas las situaciones, pero ciertamente me da los resultados necesarios para mi diseño. Y también aborda el comentario de madhu.

Si hay algún diseño presente debajo de la vista de desplazamiento entonces este truco no funcionará – madhu 05 de marzo a las 4:36

Para crear un ScrollView o ListView con un maxHeight solo necesitas crear un LinearLayout transparente a su alrededor con un alto de lo que quieres que sea maxHeight. A continuación, establece el alto de ScrollView para wrap_content . Esto crea un ScrollView que parece crecer hasta que su altura sea igual al LinearLayout principal.

Esto funcionó para que sea personalizable en xml:

MaxHeightScrollView.java:

 public class MaxHeightScrollView extends ScrollView { private int maxHeight; private final int defaultHeight = 200; public MaxHeightScrollView(Context context) { super(context); } public MaxHeightScrollView(Context context, AttributeSet attrs) { super(context, attrs); if (!isInEditMode()) { init(context, attrs); } } public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (!isInEditMode()) { init(context, attrs); } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); if (!isInEditMode()) { init(context, attrs); } } private void init(Context context, AttributeSet attrs) { if (attrs != null) { TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView); //200 is a defualt value maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_maxHeight, defaultHeight); styledAttrs.recycle(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } 

attr.xml

    

diseño de ejemplo

    

Habría comentado la respuesta de whizzle si hubiera podido, pero me pareció útil señalar que para poder resolver este problema en el contexto del modo de múltiples ventanas en Android N, necesitaba cambiar el código ligeramente a este:

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if(MeasureSpec.getSize(heightMeasureSpec) > maxHeight) { heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 

Esto permite que el diseño cambie de tamaño para que sea más pequeño que la altura máxima, pero también evita que sea más grande que la altura máxima. Utilicé esta es una clase de diseño que reemplaza RelativeLayout y esto me permitió crear un diálogo personalizado con un ScrollView como el elemento secundario de MaxHeightRelativeLayout que no expande la altura completa de la pantalla y también se contrae para ajustarse al tamaño de viuda más pequeño en multi- ventana para Android N.

No hay forma de establecer maxHeight. Pero puedes establecer la altura.

Para hacer eso necesitarás descubrir la altura de cada elemento de tu scrollView. Después de eso, simplemente configure su altura de scrollView en numberOfItens * heightOfItem.

Para descubrir la altura de un artículo hazlo:

 View item = adapter.getView(0, null, scrollView); item.measure(0, 0); int heightOfItem = item.getMeasuredHeight(); 

Para establecer la altura, haz eso:

 // if the scrollView already has a layoutParams: scrollView.getLayoutParams().height = heightOfItem * numberOfItens; // or // if the layoutParams is null, then create a new one. scrollView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, heightOfItem * numberOfItens)); 

¿Has intentado utilizar el valor de layout_weight ? Si establece uno en un valor mayor que 0, extenderá esa vista en el espacio restante disponible.

Si tenía varias vistas que necesitaban estirarse, el valor se convertiría en un peso entre ellas.

Por lo tanto, si tuviera dos vistas configuradas en un valor de layout_weight de 1, ambas se estirarían para llenar el espacio, pero ambas tendrían la misma cantidad de espacio. Si establece uno de ellos al valor de 2, se estirará el doble que la otra vista.

Más información aquí en Linear Layout.

Como sabemos, los dispositivos con Android pueden tener diferentes tamaños de pantalla. Como sabemos más, las vistas deben ajustarse dinámicamente y convertirse en el espacio apropiado.

Si establece una altura máxima, puede forzar la vista para que no tenga suficiente espacio o para que ocupe menos espacio. Sé que a veces parece ser prácticamente establecer una altura máxima. ¡Pero si la resolución cambiará drásticamente, y lo hará !, entonces la vista, que tiene una altura máxima, no se verá apropiada.

Creo que no hay una forma adecuada de hacer exactamente el diseño que desea. Te recomendaría que pienses sobre tu diseño usando gestores de diseño y mecanismos relativos. No sé lo que estás tratando de lograr, pero me parece un poco extraño que una lista solo muestre tres elementos y luego el usuario tenga que desplazarse.

por cierto. minHeight no está garantizado (y tal vez tampoco debería existir). puede tener algún beneficio para obligar a los elementos a ser visibles, mientras que otros elementos relativos se hacen más pequeños.

Si alguien está considerando usar el valor exacto para LayoutParams, por ejemplo

 setLayoutParams(new LayoutParams(Y, X ); 

Recuerde tener en cuenta la densidad de la pantalla del dispositivo; de lo contrario, podría obtener un comportamiento muy extraño en diferentes dispositivos. P.ej:

 Display display = getWindowManager().getDefaultDisplay(); DisplayMetrics d = new DisplayMetrics(); display.getMetrics(d); setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, (int)(50*d.density) )); 

Creo que puedes configurar el heiht en tiempo de ejecución para 1 elemento simplemente scrollView.setHeight(200px) , para 2 elementos scrollView.setheight(400px) para 3 o más scrollView.setHeight(600px)

Primero, obtenga la altura del elemento en píxeles

 View rowItem = adapter.getView(0, null, scrollView); rowItem.measure(0, 0); int heightOfItem = rowItem.getMeasuredHeight(); 

entonces simplemente

 Display display = getWindowManager().getDefaultDisplay(); DisplayMetrics displayMetrics = new DisplayMetrics(); display.getMetrics(displayMetrics); scrollView.getLayoutParams().height = (int)((heightOfItem * 3)*displayMetrics .density); 

si quieren hacer una vista de desplazamiento o una vista de lista sin desbordamiento, solo en RelativeLayout con una vista superior y una vista inferior en la parte superior e inferior:

  

Mi vista personalizada MaxHeightScrollView

 public class MaxHeightScrollView extends ScrollView { private int maxHeight; public MaxHeightScrollView(Context context) { this(context, null); } public MaxHeightScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView); try { maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_mhs_maxHeight, 0); } finally { styledAttrs.recycle(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (maxHeight > 0) { heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } 

style.xml

    

Utilizando

 < ....MaxHeightScrollView android:layout_width="wrap_content" android:layout_height="wrap_content" app:mhs_maxHeight="100dp" > ...  

Envuelva su ScrollView alrededor de su LinearLayout con layout_height = “max_height”, esto hará un trabajo perfecto. De hecho, tengo este código en producción de los últimos 5 años sin problemas.

      

(Sé que esto no responde directamente la pregunta, pero podría ser útil para otros que buscan funcionalidad maxHeight)

ConstraintLayout ofrece la altura máxima para sus hijos a través de

 app:layout_constraintHeight_max="300dp" app:layout_constrainedHeight="true" 

o

 app:layout_constraintWidth_max="300dp" app:layout_constrainedWidth="true" 

Uso de muestra aquí .