Android에서 레이아웃의 방향 변경을 감지하는 방법은 무엇입니까?


110

방금 방향 변경 기능을 구현했습니다. 예를 들어 레이아웃이 세로에서 가로로 (또는 그 반대로) 변경 될 때. 방향 변경 이벤트가 언제 끝났는지 어떻게 알 수 있습니까?

OrientationEventListener작동하지 않았다. 레이아웃 방향 변경 이벤트에 대한 알림을 받으려면 어떻게해야합니까?


제 경우에는 방향이 변경 될 때 onCreate ()가 호출되었습니다.
Josiel Novaes

답변:


293

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
이것은 좋지만, layout-land 폴더에 레이아웃 xml을로드하면 세로 xml 레이아웃 파일을 사용합니다.
프로그래머

22
Aztec Coder에서 "android : configChanges ="orientation "을 포함하면 방향 변경을 처리 할 것임을 선언하는 것입니다. 이는 가로로 전환 할 때 활동이 다시 생성되지 않음을 의미합니다. 대신 onConfigurationChanged가 호출됩니다. 이것이 바람직하지 않은 경우 , 변수를 사용하여 활동의 방향을 기억하고 onPause (예 :)를 통해 갈 때마다 방향이 여전히 동일한 지 확인할 수 있습니다.
Elena

14
API 레벨 13 (3.2) 이상으로 개발하는 경우 android : configChanges = "orientation | screenSize"를 지정해야합니다. 그렇지 않으면 onConfigurationChanged가 호출되지 않습니다. developer.android.com/guide/topics/resources/…
Arne

1
안녕하세요, 저는 API 10 (Android 2.3.3)으로 앱을 빌드하고 있습니다. 그리고 android : configChanges = "orientation | keyboardHidden"을 사용할 때 방향을 완벽하게 인식합니다. 하지만 Android 4.1.2를 실행하는 Nexus S가 방향 변경을 감지하지 못하는 경우 어떻게해야하나요?
Karthik Andhamil

2
사용은 안드로이드 : configChanges = | "방향으로 화면 크기" 대신 안드로이드의 : configChanges = "오리엔테이션 | keyboardHidden"매니페스트 파일 및 검사에 ...!
Dinesh Sharma 2012

15

에서 레이아웃로드를 들어 레이아웃 토지 폴더 수단을 당신은 두 개의 별도의 레이아웃을 가지고 당신은 확인해야합니다 setContentView으로 onConfigurationChanged하는 방법.

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

레이아웃이 하나만있는 경우이 메서드에서 setContentView를 만들 필요가 없습니다. 간단히

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

19
재정의하는 대신 layout / main.xml 및 layout-land / main.xml을 사용하십시오.
Jared Burrows 2013 년

@JaredBurrows : 참조하십시오 stackoverflow.com/questions/23789605/…
B. Clay Shannon

화면 회전으로 인해 내 활동이 종료되었음을 감지하고 싶었습니다. onConfigurationChanged(Configuration newConfig)이 답변에서와 같이 메서드를 구현 했지만 직접 처리하는 대신 Boolean 플래그를 설정 한 다음 recreate()메서드 를 호출하여 Android가 정상적인 방식으로 활동을 다시 만들도록했습니다.
혼란스러워

recreate()방법의 한 가지 문제 는 화면이 잠깐 검은 색으로 깜박이게한다는 것입니다. 이러한 이유로 저는 다른 접근 방식을 사용했습니다. (1)에서 화면 너비를 저장하고 onCreate(...), (2) 활동이 종료 될 때 모든 라이프 사이클 방법에서 저장된 화면 너비를 현재 화면과 비교합니다 (예 :) onSaveInstanceState(...).
dazed

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()하면 방향이 변경 될 때 instanceState가 파괴되지 않으므로 저장할 필요가 없습니다. 활동 수명주기의 다른 이벤트를 위해 저장하고 싶을 수도 있지만 모르겠습니다.
izzy

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>


1

위에서 설명한대로 여러분 중 일부와 관련된 또 다른 대안을 제안하고 싶습니다.

android:configChanges="orientation|keyboardHidden" 

주입 할 레이아웃을 명시 적으로 선언했음을 의미합니다.

레이아웃 랜드 및 레이아웃 폴더 덕분에 자동 주입을 유지하려는 경우. 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

0

수락 된 답변이 작동하지 않는 경우 매니페스트 파일에 정의하지 않았는지 확인하세요.

android:screenOrientation="portrait"

내 경우입니다.


0

위에 지정되지 않았기 때문에 이것이 최신 개발자에게 사용되는 경우. 아주 명시 적으로 말하면 :

onConfigurationChanged를 사용하는 경우 두 가지가 필요합니다 .

  1. onConfigurationChanged활동 클래스 의 방법

  2. 메서드에서 처리 할 구성 변경 사항 매니페스트에 지정 합니다.onConfigurationChanged

위 답변의 매니페스트 스 니펫은 매니페스트가 속한 특정 앱에 대해 정확하지만 액티비티 클래스에서 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"/>

이제는 분명히 모든 것을 처리하고 싶지 않기 때문에 위의 옵션을 한 번에 하나씩 제거하기 시작했습니다. 제거 할 때마다 내 앱을 다시 빌드하고 테스트합니다.

또 다른 중요한 점 : onCreate를 트리거하는 구성 옵션이 하나만 자동으로 처리되는 경우 (위의 매니페스트에 나열되어 onConfigurationChanged있지 않음) 작동하지 않는 것처럼 나타납니다 . 모든 관련 항목을 매니페스트에 넣어야합니다.

원래 onCreate를 트리거하는 3 개로 끝났고, S10 +에서 테스트했고 여전히 onCreate를 받고 있었기 때문에 제거 연습을 다시해야했고 |screenSize. 따라서 다양한 플랫폼에서 테스트하십시오.

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

그래서 내 제안은 누군가가 이것에 구멍을 뚫을 수 있다고 확신하지만 :

  1. onConfigurationChangedTOAST 또는 LOG를 사용하여 활동 클래스에 메서드를 추가 하면 작동시기를 확인할 수 있습니다.

  2. 가능한 모든 구성 옵션을 매니페스트에 추가합니다.

  3. onConfigurationChanged앱을 테스트 하여 방법이 작동하는지 확인합니다 .

  4. 매니페스트 파일에서 각 구성 옵션을 한 번에 하나씩 제거하고 각각 후에 앱을 테스트합니다.

  5. 최대한 다양한 장치에서 테스트하십시오.

  6. 위의 스 니펫을 매니페스트 파일에 복사 / 붙여 넣기하지 마십시오. Android 업데이트는 목록을 변경하므로 팝업 Android Studio 힌트를 사용하여 모두 가져와야합니다.

이것이 누군가의 시간을 절약하기를 바랍니다.

onConfigurationChanged아래 정보에 대한 내 방법. 새 방향을 사용할 수있게 된 UI가 다시 생성 되기 전에onConfigurationChanged 수명주기에서 호출됩니다 . 따라서 첫 번째 방향이 올바르게 작동하는지 확인한 다음 내 UI ImageView의 가시성을보기 위해 중첩 된 두 번째 도 올바르게 작동합니다.ifif

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