Comment détecter le changement d'orientation dans la mise en page sous Android?

110

Je viens de mettre en œuvre une fonction de changement d'orientation - par exemple lorsque la mise en page passe du portrait au paysage (ou vice versa). Comment puis-je détecter la fin de l'événement de changement d'orientation.

Le OrientationEventListenern'a pas fonctionné. Comment puis-je recevoir des notifications sur les événements de changement d'orientation de la disposition?

utilisateur403015
la source
Dans mon cas, onCreate () a été appelé lorsque l'orientation change.
Josiel Novaes

Réponses:

293

Utilisez la méthode d'activité onConfigurationChanged . Voir le code suivant:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

Vous devez également modifier les dans votre fichier manifeste pour inclure l' android: configChanges Il suffit de voir le code ci-dessous:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

REMARQUE: avec Android 3.2 (niveau d'API 13) ou supérieur, la «taille de l'écran» change également lorsque l'appareil bascule entre l'orientation portrait et paysage. Ainsi, si vous souhaitez empêcher le redémarrage de l'exécution en raison d'un changement d'orientation lors du développement pour le niveau d'API 13 ou supérieur, vous devez déclarer android: configChanges = "orientation | screenSize" pour le niveau d'API 13 ou supérieur .

J'espère que ceci vous aidera... :)

Dinesh Sharma
la source
3
C'est bien, mais il ne charge pas le layout xml dans le dossier layout-land, il utilise les fichiers de layout xml portrait.
Programmeur
23
Aztec Coder, lorsque vous incluez "android: configChanges =" orientation ", vous déclarez que vous allez gérer le changement d'orientation, ce qui signifie que votre activité ne sera pas recréée lorsque vous basculerez en mode paysage. Au lieu de cela, onConfigurationChanged est appelé. Si cela n'est pas souhaité , vous pouvez utiliser une variable pour vous souvenir de l'orientation de votre activité et à chaque fois que vous passez en pause (par exemple) pour vérifier si l'orientation est toujours la même.
Elena
14
Si vous développez pour le niveau d'API 13 (3.2) ou supérieur, vous devez spécifier android: configChanges = "orientation | screenSize", sinon onConfigurationChanged ne sera pas appelé: developer.android.com/guide/topics/resources/…
Arne
1
Bonjour, je construis mon application avec l'API 10 (Android 2.3.3). Et il reconnaît parfaitement l'orientation lorsque j'utilise Android: configChanges = "orientation | keyboardHidden". Mais mon Nexus S qui exécute Android 4.1.2 ne détecte pas le changement d'orientation, que dois-je faire?
Karthik Andhamil
2
utilisez android: configChanges = "orientation | screenSize" au lieu de android: configChanges = "orientation | keyboardHidden" dans votre fichier manifeste et vérifiez ... !!!
Dinesh Sharma
15

Pour le chargement de la mise en disposition terrestres moyens de dossier que vous avez deux dispositions distinctes , alors vous devez faire setContentViewen onConfigurationChangedméthode.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

Si vous n'avez qu'une seule disposition, il n'est pas nécessaire de créer setContentView dans cette méthode. simplement

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Veerababu Medisetti
la source
19
Au lieu de remplacer, utilisez simplement layout / main.xml et layout-land / main.xml.
Jared Burrows
@JaredBurrows: S'il vous plaît voir stackoverflow.com/questions/23789605/…
B. Clay Shannon
Je voulais détecter que mon activité avait pris fin en raison d'une rotation de l'écran. J'ai implémenté la onConfigurationChanged(Configuration newConfig)méthode (comme dans cette réponse), mais plutôt que de la gérer moi-même, j'ai défini un indicateur booléen, puis j'ai appelé la recreate()méthode pour qu'Android recrée l'activité de manière normale.
étourdi
Un problème avec la recreate()méthode est qu'elle fait clignoter brièvement l'écran en noir. Pour cette raison, j'ai utilisé une autre approche: (1) enregistrer la largeur de l'écran dans le onCreate(...), (2) comparer la largeur de l'écran enregistrée à la largeur de l'écran actuelle dans n'importe quelle méthode de cycle de vie lorsque l'activité est terminée (par exemple onSaveInstanceState(...)).
étourdi
13

Je voulais juste vous montrer un moyen de sauvegarder tout votre Bundle après onConfigurationChanged:

Créez un nouveau pack juste après votre cours:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

Ensuite, après "protected void onCreate", ajoutez ceci:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

Si vous ajoutez cela, toutes vos classes crated dans MainActivity seront enregistrées.

Mais le meilleur moyen est d'ajouter ceci dans votre AndroidManifest:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Nikolay Hristov
la source
7
C'est trompeur. La mise en œuvre onConfigurationChanged()permet à votre instanceState de ne pas être détruit lorsque l'orientation change, vous n'avez donc pas à l'enregistrer. Vous voudrez peut-être l'enregistrer pour d'autres événements du cycle de vie de l'activité, mais je ne sais pas.
izzy
5

utilisez cette méthode

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

Et n'oubliez pas d'ajouter ceci dans votre Androidmainfest.xml

android:configChanges="orientation|screenSize"

comme ça

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>
Sai Gopi moi
la source
2

Remplacer la méthode de l'activité onConfigurationChanged

Flavio
la source
Je tiens à souligner que sans la ligne suivante à l'intérieur de la balise <activity> dans le manifeste, le rappel onConfigurationChanged () ne serait même pas déclenché. android: configChanges = "orientation"
Sreekanth Karumanaghat
1

Je veux juste proposer une autre alternative qui concernera certains d'entre vous, en effet, comme expliqué ci-dessus:

android:configChanges="orientation|keyboardHidden" 

implique que nous déclarons explicitement la mise en page à injecter.

Au cas où nous souhaiterions conserver l'injection automatique grâce aux dossiers layout-land et layout. Tout ce que vous avez à faire est de l'ajouter à onCreate:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

Ici, on affiche ou non la barre d'action en fonction de l'orientation du téléphone

Z3nk
la source
0

Créez une instance de OrientationEventListenerclasse et activez-la.

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();
James Fenn
la source
2
Veuillez ne pas vandaliser votre réponse. Si vous souhaitez le supprimer, vous pouvez trouver le bouton de suppression en bas à gauche de votre réponse.
CalvT
0

Si la réponse acceptée ne fonctionne pas pour vous, assurez-vous de ne pas avoir défini dans le fichier manifeste:

android:screenOrientation="portrait"

C'est mon cas.

Jiyeh
la source
0

Au cas où cela serait utile à certains développeurs plus récents car ce n'est pas spécifié ci-dessus. Juste pour être très explicite:

Vous avez besoin de deux choses si vous utilisez onConfigurationChanged :

  1. Une onConfigurationChangedméthode dans votre classe d'activité

  2. Spécifiez dans votre manifeste les modifications de configuration qui seront gérées par votre onConfigurationChangedméthode

L'extrait de code manifeste dans les réponses ci-dessus, bien qu'il soit sans aucun doute correct pour l'application particulière à laquelle appartient le manifeste, n'est PAS exactement ce que vous devez ajouter dans votre manifeste pour déclencher la méthode onConfigurationChanged dans votre classe d'activité. c'est-à-dire que l'entrée de manifeste ci-dessous peut ne pas être correcte pour votre application.

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

Dans l'entrée de manifeste ci-dessus, il existe diverses actions Android pour android:configChanges=""lesquelles peuvent déclencher onCreate dans le cycle de vie de votre activité.

Ceci est très important - Ceux qui ne sont PAS spécifiés dans le manifeste sont ceux qui déclenchent votre onCreate et ceux qui sont spécifiés dans le manifeste sont ceux qui déclenchent votre onConfigurationChangedméthode dans votre classe d'activité.

Vous devez donc identifier les modifications de configuration que vous devez gérer vous-même. Pour l'encyclopédie Android contestée comme moi, j'ai utilisé la fenêtre contextuelle des conseils rapides dans Android Studio et ajouté presque toutes les options de configuration possibles. La liste de tous ces éléments disait que je gérerais tout et onCreate ne sera jamais appelé en raison de configurations.

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

Maintenant, évidemment, je ne veux pas tout gérer, alors j'ai commencé à éliminer les options ci-dessus une par une. Reconstruire et tester mon application après chaque suppression.

Un autre point important : s'il n'y a qu'une seule option de configuration gérée automatiquement qui déclenche votre onCreate (vous ne l'avez pas répertoriée dans votre manifeste ci-dessus), alors il semblera que cela onConfigurationChangedne fonctionne pas. Vous devez mettre tous les éléments pertinents dans votre manifeste.

J'ai fini avec 3 qui déclenchaient onCreate à l'origine, puis j'ai testé sur un S10 + et je recevais toujours le onCreate, donc j'ai dû refaire mon exercice d'élimination et j'avais également besoin du |screenSize. Alors testez sur une sélection de plateformes.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

Donc ma suggestion, même si je suis sûr que quelqu'un peut faire des trous dans ceci:

  1. Ajoutez votre onConfigurationChangedméthode dans votre classe d'activité avec un TOAST ou un journal afin que vous puissiez voir quand cela fonctionne.

  2. Ajoutez toutes les options de configuration possibles à votre manifeste.

  3. Confirmez que votre onConfigurationChangedméthode fonctionne en testant votre application.

  4. Supprimez chaque option de configuration de votre fichier manifeste une par une, en testant votre application après chacune.

  5. Testez sur une aussi grande variété d'appareils que possible.

  6. Ne copiez / collez pas mon extrait ci-dessus dans votre fichier manifeste. Les mises à jour Android modifient la liste, utilisez donc les astuces Android Studio pour vous assurer de toutes les avoir.

J'espère que cela fera gagner du temps à quelqu'un.

Ma onConfigurationChangedméthode juste pour info ci-dessous. onConfigurationChangedest appelée dans le cycle de vie une fois que la nouvelle orientation est disponible, mais avant que l'interface utilisateur n'ait été recréée. Par conséquent, ma première ifvérification de l'orientation fonctionne correctement, puis la deuxième imbriquée ifpour regarder la visibilité de mon UI ImageView fonctionne également correctement.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }
DMur
la source
0

pour la mise en œuvre de Kotilin dans la forme la plus simple - se déclenche uniquement lorsque l'écran passe de portrait <--> paysage si besoin d'un appareil une détection de retournement (180 degrés) vous devrez vous connecter aux valeurs du capteur de gravité

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


    }
}
alpha911
la source