회전 처리Handling Rotation

이 항목에서는 Xamarin.Android에서 장치 방향 변경 내용을 처리 하는 방법을 설명 합니다. 이 변경 방향을 프로그래밍 방식으로 처리 하는 방법으로 특정 장치 방향에 대 한 리소스를 자동으로 로드 하려면 Android 리소스 시스템을 사용 하는 방법에 설명 합니다.This topic describes how to handle device orientation changes in Xamarin.Android. It covers how to work with the Android resource system to automatically load resources for a particular device orientation as well as how to programmatically handle orientation changes.

개요Overview

모바일 장치를 쉽게 회전 하기 때문에 기본 제공 회전 모바일 Os의 표준 기능입니다.Because mobile devices are easily rotated, built-in rotation is a standard feature in mobile OSes. Android는 XML 또는 프로그래밍 방식으로 코드에서 사용자 인터페이스를 선언적으로 만든 있는지 여부를 응용 프로그램의 경우에서 회전을 처리 하기 위한 복잡 한 프레임 워크를 제공 합니다.Android provides a sophisticated framework for dealing with rotation within applications, whether the user interface is created declaratively in XML or programmatically in code. 회전 된 장치에서 선언적 레이아웃 변경 내용을 자동으로 처리 하는 경우 응용 프로그램은 Android 리소스 시스템과 긴밀 한 통합에서 이용할 수 있습니다.When automatically handling declarative layout changes on a rotated device, an application can benefit from the tight integration with the Android resource system. 프로그래밍 방식으로 레이아웃에 대 한 변경 내용은 수동으로 처리 되어야 합니다.For programmatic layout, changes must be handled manually. 따라서 보다 세부적으로 제어 더 많은 작업이 런타임에 짧아지며 개발자.This allows finer control at runtime, but at the expense of more work for the developer. 응용 프로그램 방향 변경 내용의 수동 컨트롤을 작업 다시 시작을 건너뛰도록 선택할 수도 있습니다.An application can also choose to opt out of the Activity restart and take manual control of orientation changes.

이 가이드에는 다음 방향 항목 검사:This guide examines the following orientation topics:

  • 선언적 레이아웃 회전 – 레이아웃 및 특정 방향에 대 한 드로어 블을 로드 하는 방법을 비롯 한 방향 인식 응용 프로그램을 빌드하는 Android 리소스 시스템을 사용 하는 방법입니다.Declarative Layout Rotation – How to use the Android resource system to build orientation-aware applications, including how to load both layouts and drawables for particular orientations.

  • 프로그래밍 방식으로 레이아웃 회전 – 방향 변경 내용을 수동으로 처리 하는 방법 뿐만 아니라 컨트롤을 프로그래밍 방식으로 추가 하는 방법입니다.Programmatic Layout Rotation – How to add controls programmatically as well as how to handle orientation changes manually.

레이아웃을 사용 하 여 선언적으로 회전 처리Handling Rotation Declaratively with Layouts

파일 명명 규칙을 따르는 폴더에 넣어 Android 자동으로 파일을 로드 적절 한 방향을 변경 하는 경우.By including files in folders that follow naming conventions, Android automatically loads the appropriate files when the orientation changes. 에 대 한 지원이 포함 됩니다.This includes support for:

  • 레이아웃 리소스 – 각 방향에 대해 팽창 된 레이아웃 파일을 지정 합니다.Layout Resources – Specifying which layout files are inflated for each orientation.

  • 드로어 블 리소스 – 각 방향에 대해 로드 되는 드로어 블을 지정 합니다.Drawable Resources – Specifying which drawables are loaded for each orientation.

레이아웃 리소스Layout Resources

기본적으로 Android XML (AXML) 파일에 포함 된 리소스/레이아웃 폴더 활동에 대 한 뷰 렌더링에 사용 됩니다.By default, Android XML (AXML) files included in the Resources/layout folder are used for rendering views for an Activity. 이 폴더의이 리소스는 환경에 대 한 추가적인 레이아웃 리소스가 제공 되는 경우 가로 및 세로 방향에 사용 됩니다.This folder's resources are used for both portrait and landscape orientation if no additional layout resources are provided specifically for landscape. 기본 프로젝트 템플릿에서 만든 프로젝트 구조를 고려 합니다.Consider the project structure created by the default project template:

기본 프로젝트 템플릿 구조Default project template structure

이 프로젝트 하나를 만듭니다 Main.axml 파일을 리소스/레이아웃 폴더입니다.This project creates a single Main.axml file in the Resources/layout folder. 때 활동의 OnCreate 메서드가 호출 되 면에서 정의 된 뷰를 확장 Main.axml, 선언 하는 단추 아래 XML에 표시 된 대로:When the Activity's OnCreate method is called, it inflates the view defined in Main.axml, which declares a button as shown in the XML below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
<Button  
  android:id="@+id/myButton"
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:text="@string/hello"/>
</LinearLayout>

가로 방향으로, 작업의 장치를 회전 하는 경우 OnCreate 메서드를 다시 호출 및 동일한 Main.axml 아래 스크린샷에 표시 된 것 처럼 파일 팽창 됩니다.If the device is rotated to landscape orientation, the Activity's OnCreate method is called again and the same Main.axml file is inflated, as shown in the screenshot below:

동일 하지만 화면 가로 방향Same screen but in landscape orientation

레이아웃 방향 별Orientation-Specific Layouts

레이아웃 폴더 외에도 (세로 기본값으로 하며 명시적으로 명명 수도 있습니다 레이아웃 포트 라는 폴더를 포함 하 여 layout-land), 응용 프로그램 코드 없이 환경에서 작업 하는 경우 필요한 뷰를 정의할 수 있습니다 변경 내용입니다.In addition to the layout folder (which defaults to portrait and can also be explicitly named layout-port by including a folder named layout-land), an application can define the views it needs when in landscape without any code changes.

가정 합니다 Main.axml 파일 같은 XML이 포함 합니다.Suppose the Main.axml file contained the following XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:text="This is portrait"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent" />
</RelativeLayout>

폴더 이름이 추가 포함 하는 레이아웃 랜드 Main.axml 파일을 프로젝트에 추가 됩니다 새로 추가 된 로드 하는 Android에서 이제 하면 환경에서 작업 하는 경우 레이아웃 값 Main.axml 합니다.If a folder named layout-land that contains an additional Main.axml file is added to the project, inflating the layout when in landscape will now result in Android loading the newly added Main.axml. 가로 버전의 Main.axml 다음 코드를 포함 하는 파일 (간단히 하기 위해이 XML은 코드의 기본 세로 버전와 유사 하지만 다른 문자열을 사용 하 여는 TextView):Consider the landscape version of the Main.axml file that contains the following code (for simplicity, this XML is similar to the default portrait version of the code, but uses a different string in the TextView):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:text="This is landscape"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent" />
</RelativeLayout>

이 코드를 실행 하 고 세로에서 가로로 장치 회전 아래와 같이 새 XML 로드를 보여 줍니다.Running this code and rotating the device from portrait to landscape demonstrates the new XML loading, as shown below:

세로 모드로 인쇄 하는 세로 및 가로 스크린 샷Portrait and landscape screenshots printing the portrait mode

드로어 블 리소스Drawable Resources

회전 하는 동안 Android 처리 드로어 블 리소스 마찬가지로 레이아웃 리소스 합니다.During rotation, Android treats drawable resources similarly to layout resources. 이 경우 시스템에서 드로어 블을 가져옵니다 합니다 리소스/drawable 하 고 리소스/drawable land 폴더 각각.In this case, the system gets the drawables from the Resources/drawable and Resources/drawable-land folders, respectively.

예를 들어, 프로젝트에서 Monkey.png 라는 이미지를 포함 합니다 리소스/drawable 폴더에 위치를 그릴 수 있는에서 참조 되는 ImageView 다음과 같은 xml:For example, say the project includes an image named Monkey.png in the Resources/drawable folder, where the drawable is referenced from an ImageView in XML like this:

<ImageView
  android:layout_height="wrap_content"
  android:layout_width="wrap_content"
  android:src="@drawable/monkey"
  android:layout_centerVertical="true"
  android:layout_centerHorizontal="true" />

추가로 가정 하는 다른 버전의 Monkey.png 아래에 포함 됩니다 리소스/drawable land합니다.Let's further assume that a different version of Monkey.png is included under Resources/drawable-land. 레이아웃 파일의 장치가 있을 때 처럼 회전, 지정 된 방향에 대 한 드로어 블 변경을 아래와 같이:Just like with the layout files, when the device is rotated, the drawable changes for the given orientation, as shown below:

다른 버전의 가로 및 세로 모드에 표시 된 Monkey.pngDifferent version of Monkey.png shown in portrait and landscape modes

회전을 프로그래밍 방식으로 처리Handling Rotation Programmatically

경우에 따라 코드에서 레이아웃 정의합니다.Sometimes we define layouts in code. 이 다양 한 기술적 제한 사항을, 개발자 환경 설정 등의 이유로 발생할 수 있습니다. 컨트롤에 프로그래밍 방식으로 추가 하는 경우 응용 프로그램 XML 리소스를 사용할 때 자동으로 처리 하는 장치 방향에 대해 수동으로 고려해 야 합니다.This can happen for a variety of reasons, including technical limitations, developer preference, etc. When we add controls programmatically, an application must manually account for device orientation, which is handled automatically when we use XML resources.

코드에서 컨트롤 추가Adding Controls in Code

컨트롤에 프로그래밍 방식으로 추가 하려면 응용 프로그램에서는 다음 단계를 수행 해야 합니다.To add controls programmatically, an application needs to perform the following steps:

  • 레이아웃을 만듭니다.Create a layout.
  • 레이아웃 매개 변수를 설정 합니다.Set layout parameters.
  • 컨트롤을 만듭니다.Create controls.
  • 컨트롤 레이아웃 매개 변수를 설정 합니다.Set control layout parameters.
  • 레이아웃 컨트롤을 추가 합니다.Add controls to the layout.
  • 콘텐츠 보기 레이아웃을 설정 합니다.Set the layout as the content view.

예를 들어, 단일 구성 된 사용자 인터페이스는 것이 좋습니다 TextView 에 추가 된 컨트롤을 RelativeLayout다음 코드에 표시 된 것 처럼 합니다.For example, consider a user interface consisting of a single TextView control added to a RelativeLayout, as shown in the following code.

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);
                        
  // create a layout
  var rl = new RelativeLayout (this);

  // set layout parameters
  var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
  rl.LayoutParameters = layoutParams;
        
  // create TextView control
  var tv = new TextView (this);

  // set TextView's LayoutParameters
  tv.LayoutParameters = layoutParams;
  tv.Text = "Programmatic layout";

  // add TextView to the layout
  rl.AddView (tv);
        
  // set the layout as the content view
  SetContentView (rl);
}

이 코드의 인스턴스를 만듭니다는 RelativeLayout 클래스 집합과 해당 LayoutParameters 속성입니다.This code creates an instance of a RelativeLayout class and sets its LayoutParameters property. LayoutParams 클래스는 다시 사용할 수 있는 방식으로 컨트롤 배치 되는 방식을 캡슐화 하는 Android의 방법입니다.The LayoutParams class is Android's way of encapsulating how controls are positioned in a reusable way. 레이아웃의 인스턴스를 만든 후 컨트롤을 생성 하 고 추가할 수 있습니다.Once an instance of a layout is created, controls can be created and added to it. 컨트롤 LayoutParameters와 같은 TextView 이 예제입니다.Controls also have LayoutParameters, such as the TextView in this example. 후는 TextView 만들어지면 추가 하는 RelativeLayout 설정 합니다 RelativeLayout 콘텐츠 보기 결과를 표시 하는 응용 프로그램으로는 TextView 표시 된 것 처럼:After the TextView is created, adding it to the RelativeLayout and setting the RelativeLayout as the content view results in the application displaying the TextView as shown:

세로 및 가로 모드로 표시 하는 증분 카운터 단추Increment counter button shown in both portrait and landscape modes

코드에서 검색 방향Detecting Orientation in Code

응용 프로그램을 각 방향에 대 한 다른 사용자 인터페이스를 로드 하려고 하는 경우 때 OnCreate 호출 됩니다 (이 일이 발생 될 때마다 장치 회전) 방향에 감지 하 고 원하는 사용자 인터페이스 코드를 다음 로드 합니다.If an application tries to load a different user interface for each orientation when OnCreate is called (this will happen each time a device is rotated), it must detect the orientation, and then load the desired user interface code. Android 라는 클래스에는 WindowManager, 확인을 통해 현재 장치 회전에 사용할 수 있는 WindowManager.DefaultDisplay.Rotation 속성을 아래와 같이:Android has a class called the WindowManager, which can be used to determine the current device rotation via the WindowManager.DefaultDisplay.Rotation property, as shown below:

protected override void OnCreate (Bundle bundle)
{
  base.OnCreate (bundle);
                        
  // create a layout
  var rl = new RelativeLayout (this);

  // set layout parameters
  var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
  rl.LayoutParameters = layoutParams;
                        
  // get the initial orientation
  var surfaceOrientation = WindowManager.DefaultDisplay.Rotation;
  // create layout based upon orientation
  RelativeLayout.LayoutParams tvLayoutParams;
                
  if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
    tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
  } else {
    tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
    tvLayoutParams.LeftMargin = 100;
    tvLayoutParams.TopMargin = 100;
  }
                        
  // create TextView control
  var tv = new TextView (this);
  tv.LayoutParameters = tvLayoutParams;
  tv.Text = "Programmatic layout";
        
  // add TextView to the layout
  rl.AddView (tv);
        
  // set the layout as the content view
  SetContentView (rl);
}

설정 하는이 코드는 TextView 다음과 같이 가로로 회전 하는 경우 자동으로 새 레이아웃에 애니메이션, 화면의 왼쪽 상단에서의 픽셀 위치 지정된 100 되도록 합니다.This code sets the TextView to be positioned 100 pixels from the top left of the screen, automatically animating to the new layout, when rotated to landscape, as shown here:

가로 및 세로 모드에서 뷰 상태 유지View state is preserved across portrait and landscape modes

작업 다시 시작 방지Preventing Activity Restart

모든 항목을 처리 하는 것 외에도 OnCreate, 응용 프로그램에서 설정 하 여 방향을 변경 하는 경우 다시 시작 작업을 방해할 수 있습니다 ConfigurationChangesActivityAttribute 다음과 같습니다:In addition to handling everything in OnCreate, an application can also prevent an Activity from being restarted when the orientation changes by setting ConfigurationChanges in the ActivityAttribute as follows:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]

이제 장치를 회전할 때 작업 다시 시작 되지 않습니다.Now when the device is rotated, the Activity is not restarted. 수동으로 처리 하기 위해 방향 변경이 경우 작업을 재정의할 수는 OnConfigurationChanged 메서드에서 방향을 결정 하 고는 Configuration 예: 아래 활동의 새 구현에서는 전달 되는 개체:In order to manually handle the orientation change in this case, an Activity can override the OnConfigurationChanged method and determine the orientation from the Configuration object that is passed in, as in the new implementation of the Activity below:

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
public class CodeLayoutActivity : Activity
{
  TextView _tv;
  RelativeLayout.LayoutParams _layoutParamsPortrait;
  RelativeLayout.LayoutParams _layoutParamsLandscape;
                
  protected override void OnCreate (Bundle bundle)
  {
    // create a layout
    // set layout parameters
    // get the initial orientation

    // create portrait and landscape layout for the TextView
    _layoutParamsPortrait = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
                
    _layoutParamsLandscape = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
    _layoutParamsLandscape.LeftMargin = 100;
    _layoutParamsLandscape.TopMargin = 100;
                        
    _tv = new TextView (this);
                        
    if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
      _tv.LayoutParameters = _layoutParamsPortrait;
    } else {
      _tv.LayoutParameters = _layoutParamsLandscape;
    }
                        
    _tv.Text = "Programmatic layout";
    rl.AddView (_tv);
    SetContentView (rl);
  }
                
  public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
  {
    base.OnConfigurationChanged (newConfig);
                        
    if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait) {
      _tv.LayoutParameters = _layoutParamsPortrait;
      _tv.Text = "Changed to portrait";
    } else if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
      _tv.LayoutParameters = _layoutParamsLandscape;
      _tv.Text = "Changed to landscape";
    }
  }
}

여기서는 TextView's 가로 및 세로 레이아웃 매개 변수가 초기화 됩니다.Here the TextView's layout parameters are initialized for both landscape and portrait. 클래스 변수와 함께 매개 변수를 보유할는 TextView 자체 활동 다시 만들어지지 것입니다 방향이 변경 되 면 때문입니다.Class variables hold the parameters, along with the TextView itself, since the Activity will not be re-created when orientation changes. 코드를 사용 하 여 계속 합니다 surfaceOrientartionOnCreate 에 대 한 초기 레이아웃을 설정 하는 TextView합니다.The code still uses the surfaceOrientartion in OnCreate to set the initial layout for the TextView. 그 후 OnConfigurationChanged 모든 후속 레이아웃 변경 내용을 처리 합니다.After that, OnConfigurationChanged handles all subsequent layout changes.

응용 프로그램을 실행 하는 경우 Android 장치 회전 발생 하 고 작업을 다시 시작 되지 않으면 변경 하는 사용자 인터페이스를 로드 합니다.When we run the application, Android loads the user interface changes as device rotation occurs, and does not restart the Activity.

선언적 레이아웃에 대 한 작업 다시 시작 방지Preventing Activity Restart for Declarative Layouts

작업 다시 시작 장치 회전과 인해 xml에서 레이아웃 정의 하는 경우에 방지할 수 있습니다.Activity restarts caused by device rotation can also be prevented if we define the layout in XML. 예를 들어, 작업 다시 시작을 방지 하려는 경우이 방법을 사용할 수 있습니다 (성능상의 이유로 아마도) 다른 방향에 대 한 새 리소스를 로드할 필요가 없습니다.For example, we can use this approach if we want to prevent an Activity restart (for performance reasons, perhaps) and we don't need to load new resources for different orientations.

이 위해 프로그래밍 방식으로 레이아웃으로 사용 하는 동일한 절차를 따릅니다.To do this, we follow the same procedure that we use with a programmatic layout. 설정 하기만 하면 됩니다 ConfigurationChangesActivityAttribute에서 수행한 것 처럼는 CodeLayoutActivity 이전 합니다.Simply set ConfigurationChanges in the ActivityAttribute, as we did in the CodeLayoutActivity earlier. 방향 변경에서 구현할 수 있습니다 다시 실행 해야 하는 모든 코드는 OnConfigurationChanged 메서드.Any code that does need to run for the orientation change can again be implemented in the OnConfigurationChanged method.

방향 변경 하는 동안 상태를 유지합니다.Maintaining State During Orientation Changes

선언적으로 또는 프로그래밍 방식으로 회전 처리 여부를 모든 Android 응용 프로그램에는 장치 방향 변경 될 때 상태를 관리 하기 위한 동일한 기술을 구현 해야 합니다.Whether handling rotation declaratively or programmatically, all Android applications should implement the same techniques for managing state when device orientation changes. Android 장치를 회전할 때 시스템이 실행 중인 작업을 다시 시작 때문에 상태를 관리 하는 것이 중요 합니다.Managing state is important because the system restarts a running Activity when an Android device is rotated. Android는 레이아웃 등 특정 방향에 맞게 설계 된 드로어 블 대체 리소스를 로드할 수 있도록 하려면이 작업을 수행 합니다.Android does this to make it easy to load alternate resources, such as layouts and drawables that are designed specifically for a particular orientation. 다시 시작 될 때 로컬 클래스 변수에 저장 한 있습니다 일시적인 상태 활동에 손실 됩니다.When it restarts, the Activity loses any transient state it may have stored in local class variables. 따라서 의존 하는 상태 활동을 사용 하는 경우 응용 프로그램 수준 상태를 유지 해야 것입니다.Therefore, if an Activity is state reliant, it must persist its state at the application level. 응용 프로그램 처리 해야 하는 경우 저장 및 방향 변경 내용 전체를 유지 하고자 하는 응용 프로그램 상태를 복원 합니다.An application needs to handle saving and restoring any application state that it wants to preserve across orientation changes.

Android에서 지속 상태에 대 한 자세한 내용은 참조는 작업 수명 주기 가이드입니다.For more information on persisting state in Android, refer to the Activity Lifecycle guide.

요약Summary

이 문서에서는 Android의 기본 제공 기능을 사용 하 여 회전을 사용 하는 방법을 설명 합니다.This article covered how to use Android's built-in capabilities to work with rotation. 먼저 Android 리소스 시스템을 사용 하 여 방향 인식 응용 프로그램을 만드는 방법을 설명 했습니다.First, it explained how to use the Android resource system to create orientation aware applications. 다음 화면 방향이 변경을 수동으로 처리 하는 방법 뿐만 아니라 코드에서 컨트롤을 추가 하는 방법을 제공 합니다.Then it presented how to add controls in code as well as how to handle orientation changes manually.