programacion - propiedades de la clase view android
Cómo dimensionar una vista de Android según las dimensiones de sus padres (11)
Ahora puede usar PercentRelativeLayout. ¡Auge! Problema resuelto.
¿Cómo puedo clasificar una vista según el tamaño de su diseño principal? Por ejemplo, tengo un RelativeLayout
que llena la pantalla completa, y quiero una vista secundaria, digamos un ImageView
, para tomar toda la altura y 1/2 de ancho.
Intenté reemplazar todo en onMeasure
, onLayout
, onSizeChanged
, etc. y no pude hacerlo funcionar ...
Creo que el enfoque XML de Mayras puede ser claro . Sin embargo, es posible hacerlo más preciso, con una sola vista configurando weightSum. Ya no llamaría a esto un hack pero, en mi opinión, el enfoque más directo:
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1">
<ImageView android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="0.5"/>
</LinearLayout>
De esta manera puedes usar cualquier peso, 0.6 por ejemplo (y centrado) es el peso que me gusta usar para los botones.
Cuando define un diseño y una vista en XML, puede especificar el ancho y el alto de diseño de una vista para que se ajuste el contenido o para que se llene el elemento principal. Tomar la mitad del área es un poco más difícil, pero si tuvieras algo que quisieras en la otra mitad podrías hacer algo como lo siguiente.
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="1"/>
<ImageView android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="1"/>
</LinearLayout>
Dar dos cosas del mismo peso significa que se estirarán para ocupar la misma proporción de la pantalla. Para obtener más información sobre diseños, consulte los documentos de desarrollo.
Es algo como esto:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.company.myapp.ActivityOrFragment"
android:id="@+id/activity_or_fragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/linearLayoutFirst"
android:weightSum="100"> <!-- Overall weights sum of children elements -->
<Spinner
android:layout_width="0dp" <!-- It''s 0dp because is determined by android:layout_weight -->
android:layout_weight="50"
android:layout_height="wrap_content"
android:id="@+id/spinner" />
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_below="@+id/linearLayoutFirst"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/linearLayoutSecond">
<EditText
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="75"
android:inputType="numberDecimal"
android:id="@+id/input" />
<TextView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="25"
android:id="@+id/result"/>
</LinearLayout>
</RelativeLayout>
He descubierto que es mejor no perder el tiempo estableciendo las dimensiones medidas usted mismo. De hecho, hay un poco de negociación entre las vistas padre e hijo y no desea volver a escribir todo ese code .
Sin embargo, lo que puede hacer es modificar measureSpecs y luego llamar a super con ellos. Su vista nunca sabrá que recibe un mensaje modificado de su padre y se encargará de todo por usted:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int myWidth = (int) (parentHeight * 0.5);
super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}
No sé si alguien todavía está leyendo este hilo o no, pero la solución de Jeff solo te llevará a la mitad (literalmente). Lo que su onMeasure hará es mostrar la mitad de la imagen en la mitad del elemento principal. El problema es que al llamar a super.onMeasure antes de setMeasuredDimension
se miden todos los elementos setMeasuredDimension
en la vista en función del tamaño original, y luego se corta la vista a la mitad cuando el setMeasuredDimension
lo setMeasuredDimension
.
En su lugar, debe llamar a setMeasuredDimension
(como se requiere para una anulación onMeasure) y proporcionar un nuevo LayoutParams
para su vista, luego llame a super.onMeasure
. Recuerde, sus LayoutParams
se derivan del tipo principal de su vista, no del tipo de vista.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Creo que la única vez que tendrá problemas con el padre LayoutParams
es si el padre es un AbsoluteLayout
(que está en desuso, pero a veces útil).
Prueba esto
int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();
luego puede usar LinearLayout.LayoutParams para configurar los parámetros de chileView
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
Puede resolver esto creando una vista personalizada y anulando el método onMeasure (). Si siempre usa "fill_parent" para el layout_width en su xml, entonces el parámetro widthMeasureSpec que se pasa al método onMeasusre () debe contener el ancho del principal.
public class MyCustomView extends TextView {
public MyCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth / 2, parentHeight);
}
}
Tu XML se vería así:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<view
class="com.company.MyCustomView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
Roman, si quieres hacer tu diseño en código Java (descendiente ViewGroup), es posible. El truco es que tienes que implementar los métodos onMeasure y onLayout. Primero se llama a onMeasure y se debe "medir" la subvista (dimensionándola de manera efectiva al valor deseado) allí. Necesitas ajustar el tamaño nuevamente en la llamada onLayout. Si no realiza esta secuencia o no llama a setMeasuredDimension () al final de su código onMeasure, no obtendrá resultados. Por qué esto está diseñado de una manera tan complicada y frágil me supera.
Si el otro lado está vacío. Supongo que la manera más sencilla sería agregar una vista vacía (por ejemplo, un diseño lineal) y luego establecer el ancho de ambas vistas en fill_parent y sus dos ponderaciones en 1.
Esto funciona en LinearLayout ...
Tengo otra solución. Podemos obtener el ancho y la altura del elemento principal, y luego usarlo para calcular el tamaño y asignarlo a los parámetros de diseño.
Me gusta esto:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); // Don''t for get this
int parentWidth = ((View) getParent()).getMeasuredWidth();
int parentHeight = ((View) getParent()).getMeasuredHeight();
if (parentWidth*parentHeight != 0) { // Check if both width and height in non-zero
LayoutParams lp = getLayoutParams();
lp.width = parentWidth / 2;
lp.height = parentHeight;
}
}