2010-10-29 23 views
139

View's have a minHeight pero de alguna manera se carece de un maxHeight:Android: ¿por qué no hay maxHeight para una vista?

Lo que estoy tratando de lograr es tener algunos artículos (visitas) llenar un ScrollView. Cuando hay 1..3 elementos, quiero mostrarlos directamente. Lo que significa que el ScrollView tiene la altura de 1, 2 o 3 elementos.

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

Sin embargo, lamentablemente no hay forma de establecer un maxHeight. Por lo tanto, 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 existe un minHeight?

(Por cierto: algunos puntos de vista, como ImageView tienen un maxHeight implementado.)

+0

He publicado una solución en otro hilo: http://stackoverflow.com/questions/18425758/how-to-set-a-maximum-height-with-wrap-content-in-android/26758657 # 26758657 – JMPergar

+2

He creado una solución para esto en http://chintanrathod.com/maxheightscrollview-in-android-using-android-studio/ –

+0

Google eliminar maxHeight es molesto e inconveniente. Mire todas las cosas que tiene que hacer ahora para obtener el mismo resultado. –

Respuesta

1

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

Si tenía que estirar varias vistas, el valor se convertirá 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.

Some more info here listed under Linear Layout.

+1

El problema con los pesos es que son relativos. Diferentes tamaños de pantalla, diferentes resultados, p. con una pantalla de 800px puedo establecer un peso a un cierto valor, de modo que un área específica termine con los 200px deseados. Sin embargo, con una pantalla de 850px, el área específica termina siendo más grande que 200px, pero los elementos incluidos aún son solo 200px. Es por eso que preferí tener un 'maxHeight' que puedo establecer en un valor de inmersión específico. (Finalmente terminé para calcular y establecer las alturas programáticamente) – znq

0

Creo que u puede establecer el heiht en tiempo de ejecución de 1 artículo apenas scrollView.setHeight(200px), por 2 artículos scrollView.setheight(400px) de 3 o más scrollView.setHeight(600px)

+8

No desea establecer la Dimensión en 'px'. Es muy probable que no obtenga el resultado que desea en múltiples dispositivos. http://developer.android.com/guide/topics/resources/more-resources.html#Dimension –

+0

@HerndDerBeld así es como funciona en el código. si lo desea, siempre se puede convertir de DP a los píxeles con bastante facilidad: píxeles de flotación = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_DIP, DP, context.getResources() \t \t \t \t .getDisplayMetrics()); –

1

Como sabemos los dispositivos que ejecutan 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 configura una altura máxima, puede forzar a la vista a no obtener suficiente espacio o ocupar 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.

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

+6

Esto está mal. Según esta lógica, tampoco podrías decir android: layout_width = "500dp". –

+0

No veo lo que debería estar mal ni tu interpretación lógica.Si configura layout_width (que a veces está bien), no está garantizado que lo obtenga. 500dp tal vez busquen en un dispositivo apropiado, en otro no. ¡Gerentes de diseño ftw! Tal vez podría explicar más bcs, el voto abajo molesta :) –

+3

Es tan válido decir android: maxWidth = "500dp" como para decir android: layout_width = "500dp". Ambos fuerzan dimensiones específicas en la vista. –

3

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 el descubrimiento de la altura de un elemento que haga:

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

Para ajustar la altura de hacer 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)); 
1

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

setLayoutParams(new LayoutParams(Y, X); 

recuerde tomar en cuenta la densidad de la pantalla del dispositivo de lo contrario podría obtener un comportamiento muy extraño en diferentes dispositivos. Por ejemplo:

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

Con el fin de crear un ScrollView o ListView con un maxHeight sólo tiene que crear un LinearLayout transparente alrededor con una altura de lo que quiere el maxHeight sea. A continuación, establece la altura de ScrollView en wrap_content. Esto crea un ScrollView que parece crecer hasta que su altura sea igual al LinearLayout principal.

+2

Esto fue útil para evitar que un diálogo con contenido desplazable se expanda a la altura máxima de la pantalla. –

+0

Una pequeña sugerencia sería usar un FrameLayout en lugar de un LinearLayout pero dudo que importe. –

+36

Si hay algún diseño presente debajo de la vista de desplazamiento entonces este truco no funcionará –

64

Ninguna de estas soluciones funcionó para lo que necesitaba, que era un ScrollView configurado para wrap_content pero con un maxHeight por lo que dejaría de expandirse después de cierto punto y comenzar 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); 
} 

Esto puede no funcionar en todas las situaciones, pero sin duda me da los resultados necesarios para mi diseño. Y también aborda el comentario de madhu.

Si alguna disposición del presente por debajo ScrollView entonces este truco no funcionará - Madhu 5 Mar a las 4:36

+1

¿Cuándo no funcionaría? Esto parece una solución muy limpia. Me hace preguntarme por qué no lo implementaron en el xml. –

+1

Probablemente no funcionaría si configuró manualmente la altura para decir 240. No me molesté en verificar el modo en que se encuentra la vista de desplazamiento porque solo necesitaba admitir 1 modo específico (wrap_content). – whizzle

+5

buen truco, simplemente no te olvides de convertir dp a píxeles –

0

En primer lugar obtener la altura en píxeles elemento

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

si ustedes quieren hacer una vista de desplazamiento sin desbordamiento o una vista de lista, solo pero en un RelativeLayout con una vista superior y bottomview en la parte superior e inferior para ello:

<ScrollView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_above="@+id/topview" 
    android:layout_below="@+id/bottomview" > 
+0

Esto necesita más crédito. Implementación específica pero simple. –

25

Esto funcionó para mí 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

<declare-styleable name="MaxHeightScrollView"> 
     <attr name="maxHeight" format="dimension" /> 
    </declare-styleable> 

ejemplo diseño

<blah.blah.MaxHeightScrollView android:layout_weight="1" 
       app:maxHeight="90dp" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content"> 
       <EditText android:id="@+id/commentField" 
        android:hint="Say Something" 
        android:background="#FFFFFF" 
        android:paddingLeft="8dp" 
        android:paddingRight="8dp" 
        android:gravity="center_vertical" 
        android:maxLines="500" 
        android:minHeight="36dp" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" /> 
      </blah.blah.MaxHeightScrollView> 
+0

Crear una vista personalizada es definitivamente la mejor manera de lograr esto. –

4

Me han comentado sobre la respuesta de whizzle si pudiera, pero considerado útil en cuenta que para que a solucionar este problema en el contexto de la multi-ventana el modo en Android N, necesitaba cambiar ligeramente el código a esto:

@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 la disposición para cambiar el tamaño a ser menor que la altura máxima, sino que también impide que sea mayor que TH e altura máxima. Usé esto es una clase de diseño que reemplaza RelativeLayout y esto me permitió crear un cuadro de diálogo personalizado con ScrollView como el hijo de MaxHeightRelativeLayout que no expande la altura completa de la pantalla y también se contrae para caber dentro del tamaño de viuda más pequeño en multi- N. ventana para Android

0

Mi opinión MaxHeightScrollView encargo

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

<declare-styleable name="MaxHeightScrollView"> 
    <attr name="mhs_maxHeight" format="dimension" /> 
</declare-styleable> 

Usando

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

    ... 

</....MaxHeightScrollView> 
0

Aquí es una solución a corto que trabajó en mi RecyclerView. Envolví mi RecyclerView entre dos puntos de vista con pesos iguales a 1, entonces cerrado todo el asunto en un LinearLayout, así:

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 
    <View 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1"/> 
    <android.support.v7.widget.RecyclerView 
     android:scrollbars="vertical" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     /> 
    <View 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1"/> 
</LinearLayout> 

No se olvide de utilizar android:layout_height="wrap_content" para su RecyclerView.

Espero que esto ayude a cualquiera de ustedes. :)

Cuestiones relacionadas