28 votes

Faire pivoter la hiérarchie de vue de 90 degrés

Je suis en train de travailler sur une sous-classe de FrameLayout qui est censé faire tourner tous ses enfants de 90 degrés. Je suis en train de faire ce pour surmonter le paysage seule caméra limitation présent dans android 2.1 et au-dessous, en ayant l'activité dans le paysage, mais la pose de mon appareil photo superposition dans ce framelayout superposition de la faire apparaître comme si il était en mode portrait (c'est de cette façon Layar t-il) Pour ce faire, je suis l'adaptation de Jeff Sharkey du code pour faire pivoter les vues. Mon problème est que je peut faire tourner le Framelayout, mais je ne peux pas redimensionner pour qu'elle corresponde à la nouvelle dimension. Donc sur mon g1, au lieu d'un 320x480 portrait de vue sur un 480x320 vue de la caméra en mode paysage, je reçois un 320x320 zone dans le milieu montrant mon portrait avec les côtés coupés.

Voici mon code pour l'instant:

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);
    }
}

J'ai essayé primordial OnMeasure pour changer les dimensions X et Y de la Vue, mais n'ont pas été en mesure d'obtenir que cela fonctionne. Toute aide que vous pouvez fournir est grandement apprécié.

37voto

Georg Points 336

J'ai eu le même problème et a réussi à le résoudre. Au lieu de la rotation de chaque point de vue ou la mise en page à la main, j'ai utilisé un LayoutAnimationController.

Tout d'abord, placer un fichier dans /res/anim/ a appelé 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>

Puis, dans votre Activité est onCreate, ne

  @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 vous souhaitez faire pivoter des éléments qui se trouvent au-dessus de votre appareil photo aperçu (SurfaceHolder), il suffit de placer un FrameLayout au-dessus de la SurfaceHolder, placez tous vos éléments FrameLayout et d'appeler la "Mise en page MyScreen_ContentLayout". Fait.

L'espoir qui a aidé quelqu'un m'a fallu un certain temps pour obtenir tout ensemble.

4voto

Aleross Points 1258

L'aide de l'API de niveau 11 et plus tard, vous pouvez utiliser la méthode setRotation(degreesFloat); pour modifier la rotation d'un point de vue de la programmation, ou vous pouvez utiliser l'attribut XML android:rotation="" de changement dans votre XML. Il existe également des méthodes/attributs pour modifier uniquement l'X ou Y les valeurs de vue de la rotation: Android Docs - Vue (setRotation).

Ainsi, de nos jours aussi longtemps que vous êtes à l'aide de l'API de niveau 11 ou au-dessus, vous devriez être en mesure d'appliquer la rotation à un wrapper nœud disposition. Cependant, vous aurez probablement aussi changer les dimensions de haut-niveau de mise en page pour correspondre aux dimensions que vous désirez après la rotation. I. e. si vous avez un portrait de la vue w/ dimensions 800x1280, vous aurez à les changer en 1280x800 pour mettre en ligne après la rotation du paysage.

3voto

nickes Points 5469

En utilisant cette bibliothèque, vous pouvez faire pivoter la hiérarchie de la vue entière https://github.com/rongi/rotate-layout

Comme ça

entrez la description de l'image ici

0voto

Li_W Points 374

Je pense que vous avez oublié une ligne dans votre onMeasure.

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

Tiré du code pour une barre de recherche verticale ici: Besoin de <fonctionnement> barre de recherche verticale!

Vous devrez peut-être jouer avec getMeasuredHeight () pour lui donner la taille correcte de votre écran.

0voto

DoDo Points 98

Essayez de désactiver l'écrêtage des enfants de votre vue racine: appelez setClipChildren(false) sur le parent de votre RotateLayout et dans la méthode onMeasure de votre RotateLayout, mettez ces lignes:

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

J'ai essentiellement le même problème que vous et je n'ai toujours pas testé ma solution - je le ferai demain et je dirai si cela fonctionne correctement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X