studio - Android: ¿por qué no hay maxHeight para una vista?
que es un textview en android studio (14)
Las vistas tienen un minHeight
pero de alguna manera les falta un maxHeight
:
Lo que intento 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).
¿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.
Aquí hay una solución corta que funcionó en mi RecyclerView. Envolví mi RecyclerView entre dos Vistas con pesos iguales a 1, luego encerré todo en 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 te olvides de usar android:layout_height="wrap_content"
para tu RecyclerView.
Espero que esto ayude a cualquiera de ustedes. :)
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.
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)
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.
<LinearLayout
android:id="@+id/subsParent"
android:layout_width="match_parent"
android:layout_height="150dp"
android:gravity="bottom|center_horizontal"
android:orientation="vertical">
<ScrollView
android:id="@+id/subsScroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginEnd="15dp"
android:layout_marginStart="15dp">
<TextView
android:id="@+id/subsTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/longText"
android:visibility="visible" />
</ScrollView>
</LinearLayout>
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
<declare-styleable name="MaxHeightScrollView">
<attr name="maxHeight" format="dimension" />
</declare-styleable>
diseño de ejemplo
<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>
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.
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
<declare-styleable name="MaxHeightScrollView">
<attr name="mhs_maxHeight" format="dimension" />
</declare-styleable>
Utilizando
<....MaxHeightScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:mhs_maxHeight="100dp"
>
...
</....MaxHeightScrollView>
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
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));
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.
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 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) ));
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:
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/topview"
android:layout_below="@+id/bottomview" >