para - manual de programacion android pdf
Android: obtenga la altura de una vista antes de que se dibuje (6)
Ok, con respecto a la publicación actualizada, esto es lo que te ayudará: Método de Animation#initialize . Deberías poner la inicialización allí en lugar del constructor, y tendrás todos los tamaños que necesites allí.
Para una animación, necesito saber la altura desde una vista. El problema es que el método getHeight () devuelve siempre 0 a menos que se dibuje la vista. Entonces, ¿hay alguna forma de obtener altura sin dibujarla?
En este caso, la vista es un LinearLayout.
EDITAR: Intento adaptar la animación expandida de https://github.com/Udinic/SmallExamples/blob/master/ExpandAnimationExample/src/com/udinic/expand_animation_example/ExpandAnimation.java
Con esto quiero expandir más información para un elemento de la lista. No pude lograr el mismo efecto a través de xml. Por el momento, la animación solo funciona cuando conoces el tamaño del diseño antes de dibujarlo.
Parece que quieres obtener la altura pero ocultar la vista antes de que sea visible.
Tenga la visibilidad en la vista configurada como visible o invisible para comenzar (solo para que se cree una altura). No se preocupe, lo cambiaremos a invisible / ido en el código como se muestra a continuación:
private int mHeight = 0;
private View mView;
class...
// onCreate or onResume or onStart ...
mView = findViewByID(R.id.someID);
mView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener(){
@Override
public void onGlobalLayout() {
// gets called after layout has been done but before display
// so we can get the height then hide the view
mHeight = mView.getHeight(); // Ahaha! Gotcha
mView.getViewTreeObserver().removeGlobalOnLayoutListener( this );
mView.setVisibility( View.GONE );
}
});
Podría intentar comenzar con la vista visible y luego agregar algo como esto:
view.post(new Runnable() {
@Override
public void run() {
// hide view here so that its height has been already computed
view.setVisibility(View.GONE);
}
});
Ahora cuando llame a view.getHeight (), debe devolver la altura que espera.
No estoy seguro de si realmente es una buena manera de hacerlo, pero al menos debería funcionar.
Técnicamente, puede llamar al método de measure
en la vista y luego obtener su altura a través de getMeasureHeight
. Consulte esto para obtener más información: https://developer.android.com/guide/topics/ui/how-android-draws.html . MeasureSpec
embargo, tendrá que darle una MeasureSpec
.
Pero, en realidad, el tamaño de la vista está influenciado por su diseño principal, por lo que puede obtener un tamaño diferente al que realmente se dibuja.
Además, puede intentar usar valores RELATIVE_TO_SELF
en sus animaciones.
Tuve un problema similar con una situación similar.
Tuve que crear una anmiación para la cual requería la altura de la view
que está sujeta a la animación. Dentro de esa view
, que es LinearLayout
puede ser una vista secundaria de tipo TextView
. Ese TextView
es multilínea y la cantidad de líneas realmente requeridas varía.
Todo lo que hice acabo de obtener la altura medida para la vista como si el TextView
tuviera solo una línea para llenar. No es de extrañar que esto funcionara bien cada vez que el texto resultaba lo suficientemente corto para una sola línea, pero falló cuando el texto era más largo en línea.
Consideré esta respuesta: https://.com/a/6157820/854396 Pero esa no me funcionó demasiado bien porque no puedo acceder al TextView
incrustado directamente desde aquí. (Sin embargo, podría haber iterado a través del árbol de vistas de niños).
Eche un vistazo a mi código ya que funciona por ahora:
view
es la vista que debe ser animada. Es un LinearLayout
(La solución final será un poco más tipo guardar aquí) this
es una vista personalizada que contiene la view
y también hereda de LinearLayout
.
private void expandView( final View view ) {
view.setVisibility(View.VISIBLE);
LayoutParams parms = (LayoutParams) view.getLayoutParams();
final int width = this.getWidth() - parms.leftMargin - parms.rightMargin;
view.measure( MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
final int targetHeight = view.getMeasuredHeight();
view.getLayoutParams().height = 0;
Animation anim = new Animation() {
@Override
protected void applyTransformation( float interpolatedTime, Transformation trans ) {
view.getLayoutParams().height = (int) (targetHeight * interpolatedTime);
view.requestLayout();
}
@Override
public boolean willChangeBounds() {
return true;
}
};
anim.setDuration( ANIMATION_DURATION );
view.startAnimation( anim );
}
Esto fue casi todo, pero cometí otro error. Dentro de la jerarquía de vistas hay dos vistas personalizadas involucradas que son subclases de LinearLayout
y su xml se fusiona con una etiqueta de merge
como etiqueta de raíz xml. Dentro de una de estas etiquetas de merge
pasé por alto para configurar el atributo android:orientation
en vertical
. Eso no molestó demasiado para el diseño en sí, porque dentro de este ViewGroup
fusionado ViewGroup
había un ViewGroup
secundario y, por lo tanto, no podía ver la orientación incorrecta en la pantalla. Pero estaba allí y rompió un poco esta lógica de medición de diseño.
Además de lo anterior, puede ser necesario deshacerse de todos los rellenos asociados con LinearLayout
sy subclases dentro de la jerarquía de vistas. Reemplácelos por los márgenes, incluso si tiene que envolver otro diseño alrededor para que se vea igual.
static void getMeasurments(View v) {
v.measure(View.MeasureSpec.makeMeasureSpec(PARENT_VIEW.getWidth(),
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED));
final int targetHeight = v.getMeasuredHeight();
final int targetWidth = v.getMesauredWidth();
}