studio programacion herramientas fundamentos con avanzado aplicaciones android android-layout animation android-widget

programacion - manual de android en pdf



Girar la jerarquía de vista 90 grados (6)

Estoy trabajando en una subclase de FrameLayout que se supone que rota todos sus hijos en 90 grados. Hago esto para superar la limitación de cámara exclusiva del paisaje presente en Android 2.1 y versiones posteriores, al tener la actividad en el paisaje, pero colocando la superposición de mi cámara en esta superposición de diseño de cuadros para que parezca como si fuera un retrato ( así es como Layar lo hace ) Para lograr esto, estoy adaptando el código de Jeff Sharkey para rotar las vistas. Mi problema es que puedo rotar Framelayout, pero no puedo cambiar su tamaño para que coincida con las nuevas dimensiones. Por lo tanto, en mi g1, en lugar de una vista de retrato de 320x480 sobre una vista de cámara de 480x320 en paisaje, recibo una caja de 320x320 en el medio que muestra mi vista de retrato con los lados recortados.

Aquí está mi código hasta ahora:

public class RotateLayout extends FrameLayout { private Matrix mForward = new Matrix(); private Matrix mReverse = new Matrix(); private float[] mTemp = new float[2]; public RotateLayout(Context context) { super(context); } public RotateLayout(Context context, AttributeSet attrs) { super(context, attrs); } /* (non-Javadoc) * @see android.widget.FrameLayout#onMeasure(int, int) */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //This didn''t work: //super.onMeasure(heightMeasureSpec, widthMeasureSpec); } /* (non-Javadoc) * @see android.widget.FrameLayout#onSizeChanged(int, int, int, int) */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } @Override protected void dispatchDraw(Canvas canvas) { canvas.rotate(270, getWidth()/2, getHeight()/2); //This code will stretch the canvas to accommodate the new screen size. This is not what I want. //float scaleX=(float)getHeight()/getWidth(); //float scaleY=(float)getWidth()/getHeight(); //canvas.scale(scaleX, scaleY, getWidth()/2, getHeight()/2); mForward = canvas.getMatrix(); mForward.invert(mReverse); canvas.save(); canvas.setMatrix(mForward); //This is the matrix we need to use for proper positioning of touch events super.dispatchDraw(canvas); canvas.restore(); } @Override public boolean dispatchTouchEvent(MotionEvent event) { final float[] temp = mTemp; temp[0] = event.getX(); temp[1] = event.getY(); mReverse.mapPoints(temp); event.setLocation(temp[0], temp[1]); return super.dispatchTouchEvent(event); } }

He intentado reemplazar OnMeasure para cambiar las dimensiones X e Y de la Vista, pero no he podido hacer que funcione. Cualquier ayuda que puedas darnos es muy apreciada.


Creo que olvidó una línea en su onMeasure.

@Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); }

Tomado del código para una barra de búsqueda vertical aquí: ¿Cómo puedo obtener una SeekBar vertical en funcionamiento en Android?

Es posible que deba manipular el getMeasuredHeight () para que sea el tamaño correcto de su pantalla.


Esto es lo que funcionó para mí en general.

private void init() { setRotation(90f); } public YourViewOrViewGroup(final Context context) { super(context); init(); } ... (all the View/ViewGroup constructors) ... @Override protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) { super.onLayout(changed, l, t, r, b); final int width = getWidth(); final int height = getHeight(); final int offset = Math.abs(width - height) / 2; setTranslationX(-offset); setTranslationY(offset); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { super.onMeasure(heightMeasureSpec, widthMeasureSpec); }

Lo que quiere hacer es intercambiar el ancho con la altura y luego colocar los desplazamientos X e Y para que la vista se convierta en pantalla completa después de la rotación.

Lo anterior es una versión rotada por ''paisaje''. Para lograr un paisaje invertido simplemente aplique una rotación de 270 grados. Puede modificar el código dentro del fragmento o aplicar la rotación al exterior de una manera más genérica, es decir,

final YourViewOrViewGroup layout = inflater.inflate(...); if (currentOrientation.isInverted()) { layout.setRotation(layout.getRotation + 180f); }

de esta forma, puede incrustar la Vista / Grupo de Vistas giradas dentro de la definición xml e inflar las versiones ''puerto'' y ''terreno'' mientras la orientación de la pantalla cambia, pero esto parece fuera de este tema.

Editar: en realidad es mucho mejor diferir la configuración de desplazamiento hasta que haya terminado al menos un pase de diseño. Esto se debe al hecho de que en mi caso después de first onMeasure () la vista se dibujaría (antes de que se configuraran los desplazamientos). Eventualmente podría experimentarse como glitching porque la vista / disposición no se dibujaría dentro de los límites finales al principio. (actualizado el fragmento)


Intente desactivar el recorte de niños de su raíz de vista: llame a setClipChildren(false) en el padre de su RotateLayout y en el método onMeasure de su RotateLayout ponga estas líneas:

super.onMeasure(heightMeasureSpec, widthMeasureSpec); setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());

Básicamente tengo el mismo problema que tú y todavía no he probado mi solución. Lo haré mañana y contaré si funciona correctamente.


Tuve el mismo problema y logré resolverlo. En lugar de rotar cada vista o diseño a mano, utilicé un LayoutAnimationController.

Primero, coloque un archivo en / res / anim / llamado rotation.xml

<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="-90" android:pivotX="50%" android:pivotY="50%" android:duration="0" android:fillAfter="true"> </rotate>

Luego, en la Actividad onCreate, haz

@Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.myscreen); Animation rotateAnim = AnimationUtils.loadAnimation(this, R.anim.rotation); LayoutAnimationController animController = new LayoutAnimationController(rotateAnim, 0); FrameLayout layout = (FrameLayout)findViewById(R.id.MyScreen_ContentLayout); layout.setLayoutAnimation(animController); }

Si desea rotar los elementos que se encuentran sobre la vista de vista previa de la cámara (SurfaceHolder), simplemente coloque un FrameLayout sobre SurfaceHolder, coloque todos sus elementos en ese FrameLayout y llame al Diseño "MyScreen_ContentLayout". Hecho.

La esperanza de que ayudó a alguien, me llevó bastante tiempo reunir todo.


Usando API nivel 11 y posterior puedes usar el método setRotation(degreesFloat); para cambiar la rotación de una vista mediante programación, o puede usar el atributo XML android:rotation="" para cambiarlo en su XML. También hay métodos / atributos para cambiar solo los valores X o Y de la rotación de una vista: Android Docs - View (setRotation) .

Por lo tanto, hoy en día, siempre que use API de nivel 11 o superior, debería poder aplicar la rotación a un nodo de distribución de envoltura. Sin embargo, probablemente también tendrá que cambiar las dimensiones del diseño de nivel superior para que coincida con las dimensiones que desea después de la rotación. Es decir, si tiene una vista vertical con dimensiones de 800x1280, tendrá que cambiarlas a 1280x800 para que se alinee después de girar a horizontal.