회전 Android에서 활동 다시 시작


1379

내 안드로이드 응용 프로그램에서 장치를 Activity돌리면 ( 키보드를 밀면) 다시 시작됩니다 ( onCreate호출). 자, 이것이 아마도 예상되는 방법이지만 onCreate메소드 에서 초기 설정을 많이 수행 하므로 다음 중 하나가 필요합니다.

  1. 모든 초기 설정을 다른 기능으로 설정하여 장치 회전시 손실되지 않도록하십시오.
  2. 그렇게 확인 onCreate다시 호출되지 않고 레이아웃이 단지 조정 또는
  3. onCreate호출되지 않도록 앱을 세로로 제한하십시오 .

4
이 블로그 게시물의 활동 구성 변경 중에 장기 실행 비동기 작업을 유지하는 방법에 대한 약간의 설명 있습니다!
Adrian Monk

3
이것은 다른 사람들이 이미 답변 한 것처럼 직접적인 대답은 아니지만 수명주기와 관련하여 Android 앱에서 발생하는 일을 이해하기 위해 LogLifeCycle 을 살펴보십시오 .
Snicolas

답변:


965

응용 프로그램 클래스 사용

초기화에서 수행하는 작업에 Application따라 초기화 코드를 확장 하고 onCreate해당 클래스 내에서 재정의 된 메서드 로 이동 하는 새 클래스를 만드는 것을 고려할 수 있습니다.

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

onCreate전체 응용 프로그램을 만들 때 방향을 나 키보드 가시성이 변경에 활동 다시 시작을 유발하지 않도록 응용 프로그램 클래스에만 호출됩니다.

이 클래스의 인스턴스를 싱글 톤으로 노출하고 getter 및 setter를 사용하여 초기화하는 응용 프로그램 변수를 노출하는 것이 좋습니다.

참고 : 매니페스트에서 새 응용 프로그램 클래스의 이름을 지정하고 등록하고 사용하려면 다음을 수행해야합니다.

<application
    android:name="com.you.yourapp.MyApplicationClass"

구성 변경에 반응 [업데이트 : API 13부터 더 이상 사용되지 않습니다. 권장 대안 참조 ]

다른 대안으로, 응용 프로그램에서 방향 및 키보드 표시 변경과 같은 재시작을 유발하는 이벤트를 수신하여 활동 내에서 처리하도록 할 수 있습니다.

android:configChanges활동의 매니페스트 노드에 노드를 추가하여 시작하십시오.

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

또는 Android 3.2 (API 레벨 13) 이상 :

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

그런 다음 활동 내에서 onConfigurationChanged메소드를 대체 하고 호출 setContentView하여 GUI 레이아웃을 새 방향으로 다시 수행하십시오.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}

17
나는 두 번째 접근법이 효과가 있다고 생각하지 않습니다. 나는 그것을 시도했다; EditText를 가진 하나의 활동. 나는 거기에 약간의 텍스트를 썼고, 방향을 바꾸었고 텍스트는 사라졌다 / 재설정되었습니다.
Ted

231
앞으로 onRotate () 메소드를 볼 수 있기를 바랍니다. 이와 같은 것에 대해 걱정해야하는 것은 솔직한 좌절입니다.
Kelly Sutton

84
참고 안드로이드 개발자 가이드 :이 사용에 대한주의 사항 참고 : (사용 android:configChanges) 피해야 만 최후의 수단으로 사용되어야한다. 구성 변경으로 인한 재시작을 올바르게 처리하는 방법에 대한 자세한 내용은 런타임 변경 처리를 참조하십시오. 대신 회전 이벤트에서 데이터를 유지하려면 onSaveInstanceState Bundle; 또는 @로 존-O는 언급 , onRetainNonConfigurationInstance.
Jeffro

19
현재 알려진 구성 변경 에만 반응하기 때문에 이는 나쁜 해결책 입니다. 최신 Android 버전에서는 매니페스트의 모든 구성 변경 사항을 나열해야하기 때문에이 코드가 포착하지 못하는 다른 구성 변경 사항이 발생할 수 있습니다. 상태를 저장하는 솔루션은 onRetainNonConfigurationChanges내결함성이 뛰어나고 간단합니다.
Bananeweizen

16
3.2 에이 업데이트를 답변 추가해야한다고 생각합니다. 매우 중요하고 (문제에 직면했습니다) 간과 될 수 있습니다.
bigstones

185

Android 3.2 이상 업데이트 :

주의 : Android 3.2 (API 레벨 13)부터는 기기가 세로 방향과 가로 방향으로 전환 될 때 "화면 크기"도 변경 됩니다. 따라서 API 레벨 13 이상 (minSdkVersion 및 targetSdkVersion 속성에 의해 선언 된)으로 개발할 때 방향 변경으로 인한 런타임 재시작을 방지하려면 "screenSize"값 외에 값을 포함해야합니다 "orientation". 즉,을 선언해야합니다 android:configChanges="orientation|screenSize". 그러나 애플리케이션이 API 레벨 12 이하를 대상으로하는 경우 활동은 항상이 구성 변경 자체를 처리합니다 (이 구성 변경은 Android 3.2 이상 디바이스에서 실행중인 경우에도 활동을 다시 시작하지 않습니다).


1
이에 대한 위의 의견이 거의 그것을 조사하기 위해 나를 보냈기 때문에 그 설명에 감사드립니다. 현재 API 8을 대상으로하고 있으며 코드에 configChanges에 screenSize가 없으며 ICS를 실행하는 장치에서 방향이 변경되지 않고 제대로 작동하는지 확인할 수 있습니다.
Carl

이것을 지적 해 주셔서 감사합니다, 나는 android : configChanges = "orientation | screenSize"세트 만 가지고 있었고 방향 전환이 내 활동을 재현하고 있었고, 내 인생에서 나는 그 이유를 알 수 없었습니다!
크리스토퍼 페리

5
android : configChanges 추가 는 최후의 수단으로 만 사용해야합니다 . 사용을 고려 Fragments하고 setRetainInstance대신.
Simon Forsberg

요점은 screenSize내 문제를 해결 한 Android 3.2 이상입니다. 감사합니다!
fantouch

127

대신 막으려의 onCreate()전부 해고되는, 어쩌면 검사 시도 Bundle savedInstanceState가 널인지 아닌지 확인하기 위해 이벤트에 전달된다.

예를 들어, Activity모든 방향 변경이 아닌 실제로 생성 될 때 실행 해야하는 논리가있는 onCreate()경우 savedInstanceStatenull이있는 경우에만 해당 논리를 실행합니다 .

그렇지 않으면, 여전히 방향에 맞게 레이아웃을 다시 그리 길 원합니다.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

이것이 궁극적 인 대답인지 확실하지 않지만 그것은 나에게 효과적입니다.


6
그리고 실제로 상태를 어떻게 저장하고 있습니까?
Ewoks

5
이것은 저에게 효과적이며 가장 간단한 방법으로 보입니다. 응용 프로그램 서브 클래스 화에 대한 아이디어로 373 대 (내 것을 포함하여 5 개) 4 번만 얻었음을 알았습니다. 이 방법에 단점이 있습니까?
steveh

4
이 솔루션은 저에게 큰 도움이되었습니다. 내가 할 수 있었다 Intent serverintent = new Intent(MainActivity.this, MessageListener.class);startService(serverintent);을 만드는 serverSocket = new ServerSocket(0xcff2);Socket client = serverSocket.accept();A를BufferedReader(new InputStreamReader(client.getInputStream())); 내 안드로이드를 회전 활성 클라이언트 / 서버 연결을 유지, 아직 GUI의 회전을 가질 수 있습니다. 매뉴얼에 따르면 savedInstanceState는 마지막 활동이 종료되면 초기화됩니다.
프레드 F

3
이해가 안 돼요 어획량은 무엇입니까? 이것은 다른 솔루션보다 훨씬 훌륭하고 덜 복잡합니다.
RTF

3
이것은 안드로이드에서 올바른 방법입니다. 기본적으로 configChanges로 회전을 잡는 다른 방법과 부피가 크고 복잡하며 불필요한 모든 방법.
LukeWaggoner 2014

99

제가 한...

매니페스트에서 활동 섹션에 다음을 추가했습니다.

android:configChanges="keyboardHidden|orientation"

활동 코드에서 구현 :

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}

3
명확히하기 위해 : 구현시 이제 변수를 초기화 할 수 있습니다 onCreate () 및 onConfigurationChanged ()는 단순히 화면 회전을 위해 호출됩니다. 변수는 이제 화면 회전으로부터 분리됩니다 ;-) nice and ez
Somewhere Somewhere

2
여기에 설명 된대로 모든 것을 수행했지만 방향 변경 후 버튼을 누르면 NullPointerException이 발생합니다. 무엇이 잘못 될 수 있습니까?
Finnboy11

5
내 대답은 3 살이고 Android는 계속 발전하고 있습니다 ... Simon-샘플 코드에 대한 링크가 있습니까? 그것이 사람들에게 필요한 것입니다.
누군가 어딘가에

3
android : configChanges에 대해 경고 할 때 @ SimonAndréForsberg는 실제로 Android 문서를 해석 합니다. 런타임 변경 처리 에는 대안 (샘플 코드 포함)에 대한 자세한 정보가 있습니다.
Leif Arne Storset

67

설명하는 것이 기본 동작입니다. 다음을 추가하여 이러한 이벤트를 직접 감지하고 처리해야합니다.

android:configChanges

매니페스트와 처리하려는 변경 사항에 오리엔테이션의 경우 다음을 사용합니다.

android:configChanges="orientation"

키보드가 열리거나 닫히려면 다음을 사용하십시오.

android:configChanges="keyboardHidden"

둘 다 처리하려면 다음과 같이 파이프 명령으로 분리하십시오.

android:configChanges="keyboardHidden|orientation"

호출하는 모든 활동에서 onConfigurationChanged 메소드를 트리거합니다. 메소드를 대체하면 새 값을 전달할 수 있습니다.

도움이 되었기를 바랍니다.


2
@GregD 알고 있습니다. 이것이 오늘날의 상황을 반영하여 업데이트하기에 좋은시기입니다. 이 질문에 대한 의견 수를 감안할 때 여전히 SO에 대한 다른 질문에서 언급되고 있습니다.
Simon Forsberg

48

방금이 이야기를 발견했습니다.

오리엔테이션 변화를 통해 생존 활동을 유지하고이를 통해 처리하기 위해 onConfigurationChanged, 문서코드 샘플은 위의 매니페스트 파일이 제안 :

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

항상 작동한다는 추가 이점이 있습니다.

보너스 지식은 keyboardHidden논리적으로 보이지만 에뮬레이터에서 실패를 유발한다는 것입니다 (적어도 안드로이드 2.1의 경우). 만 지정 orientation하면 에뮬레이터가 때때로 OnCreate그리고 onConfigurationChanged때로는 OnCreate다른 시간에 호출 됩니다 .

장치에서 실패를 보지 못했지만 에뮬레이터가 다른 사람들에게 실패하는 것에 대해 들었습니다. 따라서 문서화 할 가치가 있습니다.


14
주의 : Android 3.2 (API 레벨 13)부터는 기기가 세로 방향과 가로 방향으로 전환 될 때 "화면 크기"도 변경됩니다. 따라서 API 레벨 13 이상을 개발할 때 방향 변경으로 인한 런타임 재시작을 방지하려면 android : configChanges = "orientation | keyboardHidden | screenSize"
Geltrude

예, 에뮬레이터는 시간이 많이 걸립니다. 구성 변경 사항을 정확하게보고하기 위해이를 사용할 수 없습니다.
IgorGanapolsky

android : configChanges 추가 는 최후의 수단으로 만 사용해야합니다 . 사용을 고려 Fragments하고 setRetainInstance대신.
Simon Forsberg

38

방향 변경에 따라 데이터를 유지하는 Android 플랫폼의 방법을 사용하는 것도 고려할 수 있습니다 : onRetainNonConfigurationInstance()getLastNonConfigurationInstance().

이를 통해 서버 가져 오기에서 얻은 정보 또는 그 onCreate이후 로 계산 된 정보와 같은 구성 변경 사항에 걸쳐 데이터를 유지할 수 있으며 Android Activity에서 xml 파일을 사용하여 현재 사용중인 방향 으로 다시 레이아웃 할 수 있습니다 .

여기 또는 여기를 참조 하십시오 .

이 방법은 이제 더 이상 사용되지 않으며 (위의 솔루션 대부분이 제안하는 것처럼 방향을 처리하는 것보다 훨씬 유연하지만 자신 이 유지하려는 각 스위치로 전환 Fragments하고 대신 사용할 것을 권장 합니다).setRetainInstance(true)Fragment


3
나는 Fragments와 setRetainInstance가 이것을 수행하는 가장 좋은 방법 (그리고 Google이 권장하는 방법)이라고 생각합니다. +1은 다른 사람에게는 -1입니다. 안드로이드 추가 : configChanges는 최후의 수단으로 만 사용해야합니다
사이먼 포스 버그

32

이 방법은 유용하지만 조각을 사용할 때는 불완전합니다.

조각은 일반적으로 구성 변경시 다시 만들어집니다. 이런 일이 일어나지 않게하려면

setRetainInstance(true); Fragment의 생성자에서

이로 인해 구성 변경 중에 프래그먼트가 유지됩니다.

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)


7
동의했다. 최신 Android API를 사용하면 Fragments가이를 처리하는 올바른 방법 인 것 같습니다. 아직 직접 시도하지는 않았지만 이 페이지를 읽으면서 수집 한 것에서 기본적으로 Activity에서 구현하는 데 사용한 것의 99 %를 Fragment의 하위 클래스로 옮긴 다음 해당 Fragment를 Activity에 추가합니다. 액티비티는 여전히 화면 회전시 파괴되고 다시 생성되지만, @Abdo 메소드를 사용하여 안드로이드 가 프래그먼트를 파괴 하지 않도록 구체적으로 지시 할 수 있습니다 setRetainInstance().
brianmearns

25

난 그냥 추가

     android:configChanges="keyboard|keyboardHidden|orientation"

매니페스트 파일에 추가 하지 않았습니다.onConfigurationChanged 내 활동 방법.

따라서 키보드가 미끄러지거나 아무 일도 일어나지 않을 때마다 .


에 추가되었으며 <application ...android:configChanges="keyboard|keyboardHidden|orientation">작동 중입니다. build.gradle의 내 설정 :minSdkVersion 15, compileSdkVersion 23, buildToolsVersion "23.0.2"
Junior Mayhé

19

onCreate당신은을 변경할 때 방법은 여전히 심지어라고 orientation안드로이드의. 따라서 모든 무거운 기능을이 방법으로 옮기는 것이 도움이되지 않습니다



17
 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

매니페스트의 어떤 부분에 "전화하지 마십시오 onCreate()"라고 표시되어 있습니까?

또한 Google 문서 android:configChanges는 최후의 수단을 제외하고는 사용하지 말라고 말합니다 .하지만 대체 방법은 모든 DO 사용 을 제안합니다 android:configChanges.

에뮬레이터가 항상 onCreate()회전을 요구하는 것은 내 경험 이었습니다.
그러나 동일한 코드를 실행하는 1-2 개의 장치는 ... (왜 차이가 있는지 잘 모르겠습니다.)


16

다음 단계를 수행하는 것이 매우 간단합니다.

<activity
    android:name=".Test"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="landscape" >
</activity>

이것은 나를 위해 작동합니다 :

참고 : 오리엔테이션은 요구 사항에 따라 다릅니다.


15

Android 매니페스트에서 변경되는 내용은 다음과 같습니다.

android:configChanges="keyboardHidden|orientation" 

활동 내에서 추가 할 사항은 다음과 같습니다.

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

15

이 줄을 매니페스트에 추가하십시오.

android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"

활동에 대한이 발췌 문장 :-

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

14

이를 수행하는 몇 가지 방법이 있습니다.

활동 상태 저장

에 활동 상태를 저장할 수 있습니다 onSaveInstanceState.

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

를 사용 bundle하여 상태를 복원하십시오.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

직접 방향 변경 처리

다른 대안은 방향 변경을 직접 처리하는 것입니다. 그러나 이것은 좋은 습관으로 간주되지 않습니다.

이것을 매니페스트 파일에 추가하십시오.

android:configChanges="keyboardHidden|orientation"

Android 3.2 이상의 경우 :

android:configChanges="keyboardHidden|orientation|screenSize"

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

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

회전 제한

회전을 피하기 위해 활동을 세로 또는 가로 모드로 제한 할 수도 있습니다.

이것을 매니페스트 파일의 활동 태그에 추가하십시오.

        android:screenOrientation="portrait"

또는 활동에서 프로그래밍 방식으로 구현하십시오.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

11

내가 찾은 방법은 onRestoreInstanceStateonSaveInstanceState이벤트를 사용하여 무언가를 저장하는 것입니다 Bundle(저장 된 변수가 필요하지 않더라도 거기에 무언가를 넣으면 Bundle비어 있지 않습니다). 그런 다음 onCreate메소드에서 Bundle가 비어 있는지 확인하고 비어 있으면 초기화하고 그렇지 않은 경우 초기화하십시오.


11

"Android 방식"이 아니더라도 방향 변경을 직접 처리하고보기 내에서 위젯을 재배치하여 변경된 방향을 고려하여 매우 좋은 결과를 얻었습니다. 뷰를 저장하고 복원 할 필요가 없기 때문에 다른 방법보다 빠릅니다. 또한 재배치 된 위젯은 정확히 동일한 위젯이며 이동 및 / 또는 크기 조정되기 때문에 사용자에게보다 원활한 환경을 제공합니다. 이러한 방식으로 모델 상태뿐만 아니라 뷰 상태도 보존 할 수 있습니다.

RelativeLayout때때로 자체적으로 방향을 바꿔야하는보기에 적합한 선택 일 수 있습니다. 각 하위 위젯에 대해 세로 레이아웃 매개 변수 세트와 가로 레이아웃 매개 변수 세트를 각각 다른 상대 위치 지정 규칙과 함께 제공하면됩니다. 그런 다음, onConfigurationChanged()방법 setLayoutParams()에 따라 각 자녀 의 전화에 적절한 것을 전달합니다 . 자식 컨트롤 자체가 내부적으로 방향을 바꿔야하는 경우에는 해당 자식에 대한 메서드를 호출하여 방향을 바꾸십시오. 그 아이는 유사의 메소드 호출 등 내부 방향 전환을해야하고, 자식 컨트롤을.


나는 이것의 일부 샘플 코드를보고 싶습니다. 화려한 것 같습니다!
Henrique de Sousa

8

화면이 회전 할 때마다 열린 활동이 완료되고 onCreate ()가 다시 호출됩니다.

1 . 화면이 회전 할 때 활동 상태를 저장하여 한 가지 작업을 수행 할 수 있으므로 활동의 onCreate ()가 다시 호출 될 때 모든 오래된 항목을 복구 할 수 있습니다. 이것을 참조하십시오 링크를

2. 활동이 다시 시작되지 않게하려면 manifest.xml 파일에 다음 행을 넣으십시오.

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

7

onSavedInstanceState 메소드를 사용하여 모든 값을 매개 변수에 저장해야합니다.

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

사용

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

화면 회전을 처리 할 개체를 볼 수있는 값을 검색하고 설정


이 API 레벨 22를 필요로
모하마드 Afrashteh에게

6

참고 : 미래의 누군가가 나와 같은 문제에 직면하면이 답변을 게시합니다. 나에게 다음 줄은 충분하지 않았다.

android:configChanges="orientation"

화면을 회전 시켰을 때`onConfigurationChanged (Configuration newConfig) 메소드가 호출되지 않았습니다.

해결책 : 문제가 방향과 관련이 있어도 "screenSize"를 추가해야했습니다. 따라서 AndroidManifest.xml-파일에서 다음을 추가하십시오.

android:configChanges="keyboardHidden|orientation|screenSize"

그런 다음 메소드를 구현하십시오. onConfigurationChanged(Configuration newConfig)




4

사람들은 당신이 사용해야한다고 말하고 있습니다

android:configChanges="keyboardHidden|orientation"

그러나 Android에서 회전을 처리하는 가장 전문적이고 가장 좋은 방법은 Loader 클래스를 사용하는 것입니다. 유명한 클래스는 아니지만 (왜 그런지 모르겠습니다) AsyncTask보다 낫습니다. 자세한 내용은 Udacity의 Android 과정에서 제공되는 Android 자습서를 읽을 수 있습니다.

물론 다른 방법으로 onSaveInstanceState로 값 또는 뷰를 저장하고 onRestoreInstanceState로 값을 읽을 수 있습니다. 정말 당신에게 달려 있습니다.


예, "전문적인"것처럼 보이도록 여분의 코드를 추가해 봅시다. 또는 configurationChanges 속성으로 빠르고 쉽고 진실하며 시도한 방법을 고수하는 것이 어떻습니까?
AndroidDev

3

시행 착오를 거친 후, 나는 대부분의 상황에서 내 요구에 맞는 솔루션을 찾았습니다. 코드는 다음과 같습니다.

매니페스트 구성 :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.pepperonas.myapplication">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

주요 활동:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private Fragment mFragment;

    private int mSelected = -1;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate  " + "");

        // null check not realy needed - but just in case...
        if (savedInstanceState == null) {

            initUi();

            // get an instance of FragmentTransaction from your Activity
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            /*IMPORTANT: Do the INITIAL(!) transaction only once!
            * If we call this everytime the layout changes orientation,
            * we will end with a messy, half-working UI.
            * */
            mFragment = FragmentOne.newInstance(mSelected = 0);
            fragmentTransaction.add(R.id.frame, mFragment);
            fragmentTransaction.commit();
        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged  " +
                   (newConfig.orientation
                    == Configuration.ORIENTATION_LANDSCAPE
                    ? "landscape" : "portrait"));

        initUi();

        Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
        makeFragmentTransaction(mSelected);
    }


    /**
     * Called from {@link #onCreate} and {@link #onConfigurationChanged}
     */
    private void initUi() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
        Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
        Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
        btnFragmentOne.setOnClickListener(this);
        btnFragmentTwo.setOnClickListener(this);
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume  " + "");
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause  " + "");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy  " + "");
    }


    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btn_fragment_one:
                Log.d(TAG, "onClick btn_fragment_one " + "");
                makeFragmentTransaction(0);
                break;

            case R.id.btn_fragment_two:
                Log.d(TAG, "onClick btn_fragment_two " + "");
                makeFragmentTransaction(1);
                break;

            default:
                Log.d(TAG, "onClick  null - wtf?!" + "");
        }
    }


    /**
     * We replace the current Fragment with the selected one.
     * Note: It's called from {@link #onConfigurationChanged} as well.
     */
    private void makeFragmentTransaction(int selection) {

        switch (selection) {
            case 0:
                mFragment = FragmentOne.newInstance(mSelected = 0);
                break;
            case 1:
                mFragment = FragmentTwo.newInstance(mSelected = 1);
                break;
        }

        // Create new transaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.frame, mFragment);

        /*This would add the Fragment to the backstack...
        * But right now we comment it out.*/
        //        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

}

샘플 조각 :

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Martin Pfeffer (pepperonas)
 */
public class FragmentOne extends Fragment {

    private static final String TAG = "FragmentOne";


    public static Fragment newInstance(int i) {
        Fragment fragment = new FragmentOne();
        Bundle args = new Bundle();
        args.putInt("the_id", i);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView  " + "");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }

}

github 에서 찾을 수 있습니다 .


3

orientation리스너를 사용 하여 다른 방향으로 다른 작업을 수행 하십시오 .

@Override
public void onConfigurationChanged(Configuration myConfig) 
{
    super.onConfigurationChanged(myConfig);
    int orient = getResources().getConfiguration().orientation; 
    switch(orient) 
    {
       case Configuration.ORIENTATION_LANDSCAPE:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
       case Configuration.ORIENTATION_PORTRAIT:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
       default:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
}

3

당신의 코드 아래에이를 넣고 Activity에서 Android Manifest.

android:configChanges="orientation"

방향을 변경할 때 활동이 다시 시작되지 않습니다.


2
@Mavamaarten 아마도 다른 사람들이 지적했듯이 나쁜 연습이며 다른 10 개의 답변이 이미 이것을 다루었습니다.
MikkoP

3

화면 방향 (가로 또는 세로)을 AndroidManifest.xml

android:screenOrientation="portrait" 또는 android:screenOrientation="landscape"

이를 위해 onResume()메소드가 호출되지 않습니다.


5
도대체 어떻게 무언가를 고치는가? 장치를 사용하여 사용자를 잠그면 장치가 회전 할 수있는 이유는 무엇입니까?
Reinherd

3

구글이 도입 한 안드로이드 아키텍쳐의 최고의 구성 요소 중 하나는 ViewModel이라는 모든 요구 사항을 충족시킬 것입니다.

이는 UI 관련 데이터를 라이프 사이클 방식으로 저장 및 관리하고 화면이 회전 할 때 데이터가 생존 할 수 있도록 설계되었습니다.

class MyViewModel : ViewModel() {

이것을 참조하십시오 : https://developer.android.com/topic/libraries/architecture/viewmodel


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.