Androidでレイアウトの向きの変化を検出するにはどうすればよいですか?


110

方向変更機能を実装しました-たとえば、レイアウトが縦から横に(またはその逆に)変更された場合。方向変更イベントがいつ終了したかをどのように検出できますか?

OrientationEventListener動作しませんでした。レイアウト方向変更イベントに関する通知を受け取るにはどうすればよいですか?


私の場合、向きが変わるとonCreate()が呼び出されました。
Josiel Novaes

回答:


292

Activity のonConfigurationChangedメソッドを使用します。次のコードを参照してください。

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

また、適切な編集も必要です android:configChangesを含めるマニフェストファイルの要素 以下のコードをご覧ください。

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

注: Android 3.2(APIレベル13)以降では、デバイスを縦向きと横向きに切り替えると、「画面サイズ」も変化します。したがって、APIレベル13以降の開発時に方向の変更によるランタイムの再起動を防止する場合は、APIレベル13以降のandroid:configChanges = "orientation | screenSize"を宣言する必要があります。

これがあなたを助けることを願っています... :)


3
これは良いことですが、portrait xmlレイアウトファイルを使用するlayout-landフォルダーにレイアウトxmlをロードしません。
プログラマー

22
Aztec Coderでは、「android:configChanges = "orientation"を含めると、向きの変更を処理することを宣言します。つまり、ランドスケープに切り替えてもアクティビティは再作成されません。代わりに、onConfigurationChangedが呼び出されます。これが望ましくない場合、変数を使用してアクティビティの方向を記憶し、毎回(たとえば)onPauseを通過するたびに方向が同じかどうかを確認できます
Elena

14
あなたはAPIレベル13(3.2)以上のために開発している場合は、アンドロイドを指定する必要がありますconfigChanges =「オリエンテーション|画面サイズ」、それ以外の場合は呼び出されませんonConfigurationChanged:developer.android.com/guide/topics/resources/...
アルネ

1
こんにちは、API 10(Android 2.3.3)でアプリを構築しています。そして、android:configChanges = "orientation | keyboardHidden"を使用すると、向きが完全に認識されます。しかし、Android 4.1.2を実行するNexus Sは方向の変更を検出しません。どうすればよいですか?
Karthik Andhamil 2012

2
使用はアンドロイド:configChanges =「オリエンテーション|画面サイズ」の代わりに、アンドロイド:configChanges =「オリエンテーション| keyboardHidden」マニフェストファイルとチェック中を... !!!
Dinesh Sharma

15

レイアウトをlayout-landフォルダーにロードするには、2つの個別のレイアウトがありsetContentViewonConfigurationChangedメソッドで作成する必要があります。

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

レイアウトが1つしかない場合は、このメソッドでsetContentViewを作成する必要はありません。単に

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

19
オーバーライドする代わりに、layout / main.xmlとlayout-land / main.xmlを使用するだけです。
Jared Burrows 2013年


画面の回転によりアクティビティが終了したことを検出したいと思いました。onConfigurationChanged(Configuration newConfig)(この回答のように)メソッドを実装しましたが、自分で処理するのではなく、ブールフラグを設定してrecreate()メソッドを呼び出し、Androidが通常の方法でアクティビティを再作成するようにしました。
2018年

このrecreate()方法の1つの問題は、画面が一瞬黒く点滅することです。このため、別のアプローチを使用しました:(1)画面幅をに保存しonCreate(...)、(2)保存された画面幅を、アクティビティが終了しているときのライフサイクルメソッド(たとえばonSaveInstanceState(...))で現在の画面幅と比較します。
2018年

13

onConfigurationChangedの後ですべてのバンドルを保存する方法を示したかっただけです。

クラスの直後に新しいバンドルを作成します。

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

次に、「protected void onCreate」の後にこれを追加します。

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

これを追加すると、すべてのクレートされたクラスがMainActivityに保存されます。

しかし、最善の方法は、これをAndroidManifestに追加することです。

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

7
これは誤解を招くものです。実装onConfigurationChanged()するとインスタンスの状態が変更されてもインスタンス状態が破棄されないため、保存する必要はありません。アクティビティライフサイクルの他のイベントのために保存することもできますが、わかりません。
izzy、2015

5

この方法を使用

@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
   }
}

そして、あなたのAndroidmainfest.xmlにこれを追加することを忘れないでください

android:configChanges="orientation|screenSize"

このような

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

    </activity>

2

アクティビティのメソッドonConfigurationChangedをオーバーライドする


マニフェストの<activity>タグ内に次の行がないと、onConfigurationChanged()コールバックがトリガーされないことを指摘しておきます。android:configChanges = "orientation"
Sreekanth Karumanaghat

1

上記の説明のように、実際に一部のユーザーに関係する別の代替案を提案したいのですが

android:configChanges="orientation|keyboardHidden" 

挿入するレイアウトを明示的に宣言することを意味します。

layout-landとlayoutフォルダーのおかげで自動注入を維持したい場合に備えて。これをonCreateに追加するだけです。

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

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

ここでは、電話の向きに応じてアクションバーを表示するかどうかを示します


0

OrientationEventListenerクラスのインスタンスを作成して有効にします。

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

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();

2
あなたの答えを破壊しないでください。削除したい場合は、解答の左下に削除ボタンがあります。
CalvT 2018年

0

受け入れられた回答が機能しない場合は、マニフェストファイルで定義していないことを確認してください。

android:screenOrientation="portrait"

それは私の場合です。


0

上記で指定されていないため、これが一部の新しい開発者に役立つ場合。非常に明確にするために:

onConfigurationChangedを使用する場合、次の 2つが必要です

  1. onConfigurationChangedアクティビティクラスのメソッド

  2. 設定の変更は、あなたのマニフェストに指定によって処理されますあなたのonConfigurationChanged方法

マニフェストが属する特定のアプリケーションのための正しいは間違いないが、ある一方、上記の回答ではマニフェストスニペット、NOTあなたが追加する必要があるかを正確にあなたのマニフェストあなたのアクティビティクラスでonConfigurationChangedメソッドをトリガーします。つまり、以下のマニフェストエントリがアプリに対して正しくない場合があります。

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

上記のマニフェストエントリにandroid:configChanges=""は、アクティビティのライフサイクルでonCreateをトリガーできるさまざまなAndroidアクションがあります。

これは非常に重要である- マニフェストに指定されていないものは、あなたのonCreateをトリガーするものですし、マニフェストに指定されたものは、あなたの引き金ものですonConfigurationChanged方法あなたのアクティビティクラスでは。

したがって、自分で処理するために必要な構成変更を特定する必要があります。私のようなAndroid Encyclopedically Challengedの場合、私はAndroid Studioのクイックヒントポップアウトを使用し、ほとんどすべての可能な構成オプションに追加しました。これらすべてをリストすると、基本的にはすべてを処理、構成のためにonCreateが呼び出されることはないと述べました。

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

今は明らかにすべてを処理したくないので、上記のオプションを1つずつ削除し始めました。削除するたびにアプリを再構築してテストします。

別の重要なポイント:onCreateをトリガーする自動的に処理される構成オプションが1つしかない場合(上記のマニフェストにリストされていない場合)、機能してonConfigurationChangedいないように見えます。関連するすべてのものをマニフェストに入れる必要があります。

元々onCreateをトリガーしていた3つで終了し、その後S10 +でテストしましたが、それでもonCreateを取得していたため、消去演習を再度行う必要があり、も必要でした|screenSize。したがって、選択したプラットフォームでテストします。

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

だから私の提案、誰かがこれに穴を開けることができると確信していますが:

  1. onConfigurationChangedTOASTまたはLOGを使用してアクティビティクラスにメソッドを追加すると、いつ動作するかを確認できます。

  2. 可能なすべての構成オプションをマニフェストに追加します。

  3. onConfigurationChangedアプリをテストして、メソッドが機能していることを確認します。

  4. マニフェストファイルから各構成オプションを1つずつ削除し、それぞれの後にアプリをテストします。

  5. できるだけ多くのデバイスでテストします。

  6. 上記のスニペットをマニフェストファイルにコピー/貼り付けしないでください。Androidのアップデートによりリストが変更されるため、ポップアウトのAndroid Studioのヒントを使用して、すべてを入手してください。

これが誰かの時間の節約になることを願っています。

onConfigurationChanged以下の情報のための私の方法。onConfigurationChangedライフサイクルで呼び出された後、新たな向きが利用可能ですが、前の UIが再作成されました。したがって、最初ifに向きを確認する最初の動作が正しく機能し、次に2番目のネストifがUI ImageViewの可視性を確認するために正しく動作します。

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

        }
    }

0

最も単純な形式でのKotilin実装の場合-画面が縦向きから横向きに変化したときにのみ発火します---重力センサー値にタブで移動する必要があるデバイスのフリップ検出(180度)が必要な場合は横向き

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")


    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.