layout_width - linearlayout android caracteristicas
Forma automática de anular onMeasure()? (8)
Creo que depende del padre lo que está anulando.
Por ejemplo, si está ampliando un ViewGroup (como FrameLayout), cuando haya medido el tamaño, debe llamar a continuación.
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
porque es posible que desee ViewGroup para hacer el trabajo de descanso (haga algunas cosas en la vista infantil)
Si está ampliando una Vista (como ImageView), puede simplemente llamar a this.setMeasuredDimension(width, height);
, porque la clase de padres simplemente hará algo como lo que has hecho habitualmente.
En una palabra, si quieres algunas funciones que tu clase para padres ofrece gratis, debes llamar a super.onMeasure()
(pasar MeasureSpec.EXACTLY mode measure spec por lo general); de lo contrario, llama a this.setMeasuredDimension(width, height);
es suficiente.
¿Cuál es la forma correcta de anular onMeasure ()? He visto varios enfoques. Por ejemplo, Professional Android Development usa MeasureSpec para calcular las dimensiones y luego finaliza con una llamada a setMeasuredDimension (). Por ejemplo:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
}
Por otro lado, según esta publicación , la forma "correcta" es usar MeasureSpec, llamar a setMeasuredDimensions (), seguido de una llamada a setLayoutParams (), y finalizar con una llamada a super.onMeasure (). Por ejemplo:
@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);
}
Entonces, ¿cuál es la forma correcta? Ninguno de los enfoques ha funcionado al 100% para mí.
Creo que realmente lo que estoy preguntando es si alguien sabe de un tutorial que explica onMeasure (), el diseño, las dimensiones de las vistas de los niños, etc.
Depende del control que estás usando. Las instrucciones en la documentación funcionan para algunos controles (TextView, Button, ...), pero no para otros (LinearLayout, ...). La forma en que funcionó muy bien para mí fue llamar al súper cuando terminé. Basado en el artículo en el siguiente enlace.
http://humptydevelopers.blogspot.in/2013/05/android-view-overriding-onmeasure.html
La documentación es la autoridad en este asunto: here y http://developer.android.com/guide/topics/ui/custom-components.html
Para resumir: al final de su método onMeasure
anulado debe llamar a setMeasuredDimension
.
No debe llamar a super.onMeasure
después de llamar a setMeasuredDimension
, que simplemente borrará todo lo que configure. En algunas situaciones, es posible que desee llamar primero a super.onMeasure
y luego modificar los resultados llamando a setMeasuredDimension
.
No onMeasure
setLayoutParams
en onMeasure
. El diseño ocurre en un segundo pase después de la medición.
Las otras soluciones no son exhaustivas. Pueden funcionar en algunos casos, y son un buen lugar para comenzar, pero no se garantiza que funcionen.
Cuando se llama a onMeasure, puede o no tener los derechos para cambiar el tamaño. Los valores que se pasan a su onMeasure ( widthMeasureSpec
, heightMeasureSpec
) contienen información sobre lo que su vista hija puede hacer. Actualmente hay tres valores:
-
MeasureSpec.UNSPECIFIED
- Puede ser tan grande como desee -
MeasureSpec.AT_MOST
: tan grande como desee (hasta el tamaño de la especificación), This esparentWidth
en su ejemplo. -
MeasureSpec.EXACTLY
- No hay elección. El padre ha elegido.
Esto se hace para que Android pueda realizar varias pasadas para encontrar el tamaño correcto para cada artículo, consulte here para obtener más detalles.
Si no sigue estas reglas, no se garantiza que su enfoque funcione.
Por ejemplo, si desea verificar si puede cambiar el tamaño, puede hacer lo siguiente:
final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
boolean resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
boolean resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
Con esta información sabrá si puede modificar los valores como en su código. O si se requiere que hagas algo diferente. Una manera rápida y fácil de resolver su tamaño deseado es usar uno de los siguientes métodos:
int resolveSizeAndState (int size, int measureSpec, int childMeasuredState)
int resolveSize (int size, int measureSpec)
Mientras que el primero solo está disponible en Honeycomb, el segundo está disponible en todas las versiones.
Nota: Puede encontrar que resizeWidth
o resizeHeight
siempre son falsos. Descubrí que este es el caso si estaba solicitando MATCH_PARENT
. Pude solucionarlo solicitando WRAP_CONTENT
en mi diseño principal y luego durante la fase UNSPECIFIED solicitando un tamaño de Integer.MAX_VALUE
. Si lo haces, obtendrás el tamaño máximo que tus padres permiten en el próximo pase en Medida.
Si cambia el tamaño de las vistas dentro de onMeasure
todo lo que necesita es la llamada a setMeasuredDimension
. Si está cambiando el tamaño fuera de onMeasure
, necesita llamar a setLayoutParams
. Por ejemplo, cambiar el tamaño de una vista de texto cuando se cambia el texto.
Supongo que setLayoutParams y volver a calcular las medidas es una solución alternativa para cambiar el tamaño de las vistas secundarias correctamente, ya que esto generalmente se hace en onMeasure de la clase derivada.
Sin embargo, esto rara vez funciona correctamente (por la razón que sea ...), invoque mejor measureChildren (al derivar un ViewGroup) o intente algo similar cuando sea necesario.
así es como resolví el problema:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
....
setMeasuredDimension( measuredWidth, measuredHeight );
widthMeasureSpec = MeasureSpec.makeMeasureSpec( measuredWidth, MeasureSpec.EXACTLY );
heightMeasureSpec = MeasureSpec.makeMeasureSpec( measuredHeight, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Además, era necesario para el componente ViewPager
puede tomar este fragmento de código como un ejemplo de onMeasure () ::
public class MyLayerLayout extends RelativeLayout {
public MyLayerLayout(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int currentChildCount = getChildCount();
for (int i = 0; i < currentChildCount; i++) {
View currentChild = getChildAt(i);
//code to find information
int widthPercent = currentChildInfo.getWidth();
int heightPercent = currentChildInfo.getHeight();
//considering we will pass height & width as percentage
int myWidth = (int) Math.round(parentWidth * (widthPercent / 100.0));
int myHeight = (int) Math.round(parentHeight * (heightPercent / 100.0));
//Considering we need to set horizontal & vertical position of the view in parent
AlignmentTraitValue vAlign = currentChildInfo.getVerticalLocation() != null ? currentChildlayerInfo.getVerticalLocation() : currentChildAlignmentTraitValue.TOP;
AlignmentTraitValue hAlign = currentChildInfo.getHorizontalLocation() != null ? currentChildlayerInfo.getHorizontalLocation() : currentChildAlignmentTraitValue.LEFT;
int topPadding = 0;
int leftPadding = 0;
if (vAlign.equals(currentChildAlignmentTraitValue.CENTER)) {
topPadding = (parentHeight - myHeight) / 2;
} else if (vAlign.equals(currentChildAlignmentTraitValue.BOTTOM)) {
topPadding = parentHeight - myHeight;
}
if (hAlign.equals(currentChildAlignmentTraitValue.CENTER)) {
leftPadding = (parentWidth - myWidth) / 2;
} else if (hAlign.equals(currentChildAlignmentTraitValue.RIGHT)) {
leftPadding = parentWidth - myWidth;
}
LayoutParams myLayoutParams = new LayoutParams(myWidth, myHeight);
currentChildLayoutParams.setMargins(leftPadding, topPadding, 0, 0);
currentChild.setLayoutParams(myLayoutParams);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}