При разработке мобильных приложений со сложным дизайном нередки ситуации, когда при изменении ориентации экрана все выглядит совсем не так, как Вам хотелось бы. В таких случаях выходом из ситуации может стать использование различных шаблонов для книжной и альбомной ориентации устройства. При этом переключение между шаблонами может осуществляться в автоматическом или динамическом (ручном) режиме.
Первый способ очень прост. Вы создаете различные версии файла шаблонов для случая альбомной и книжной ориентации и помещаете их в папки res/layout-land для книжной и res/layout-port для портретной ориентации.
Если вы хотите управлять сменой шаблона вручную, Вам необходимо воспользоваться методами, предоставляемыми классом Configuration. Объект этого класса передается в качестве параметра в метод onConfigurationChanged, который вызывается при изменении одного из параметров, определенного атрибутами Activity в файле AndroidManifest.xml. Чтобы перехватывать смену ориентации Вам нужно задать атрибут android:configChanges в знаение orientation в файле манифеста. Если этого не сделать, то метод onConfigurationChanged не будет вызываться при смене ориентации устройства.
Иногда нам требуется запретить смену ориентации. Например, для длинного списка предпочтительной является книжная ориентация, поскольку в этом случае на экране уместится большее количество информации. Вы можете ограничить ориентацию эерана для своей activity с помощью атрибута android:screenOrientation. Этот атрибут можно указать в AndroidManifest.xml. android:screenOrientation="landscape" - альбомная ориентация, android:screenOrientation="portrait" - книжная ориентация. Если Вы ограничиваете свое приложение одной ориентацией, то шаблон должен располагаться в папке res/layout.
Давайте создадим проект, в котором продемонстрируем различные способы изменения шаюлона экрана при смене ориентации. Приложение судет состоять из трех кнопок, при нажатии на которые будет открываться activity, в которой будет реализован тот или иной способ работы с ориентацией. Внутри шаблона приложения с помощью атрибута android:onClick объявим методы, которые будут вызываться при нажатии на кнопки.
Шаблон нашего приложения имеет вид:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btAutomatic" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/bt_automatic_orientation" android:onClick="autoOrientationDetection" tools:context=".MainActivity" /> <Button android:id="@+id/btDynamic" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/bt_dynamic_orientation" android:onClick="dynamicOrientationDetection" tools:context=".MainActivity" /> <Button android:id="@+id/btRestricted" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/bt_restricted_orientation" android:onClick="restrictedOrientation" tools:context=".MainActivity" /> </LinearLayout>
Внутри класса MainActivity определим эти методы.
package com.code4reference.orientationspecificlayout; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; publicclass MainActivityextends Activity{ @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /** * Запускаем activity в которой реализована * автоматическая смена шаблона. * @param view */ public void autoOrientationDetection(View view){ Intent intent=new Intent(this, AutomaticOrientation.class); startActivity(intent); } /** * Запускаем activity в которой реализована * динамическая смена шаблона. * @param view */ public void dynamicOrientationDetection(View view){ Intent intent=new Intent(this, DynamicOrientationDetection.class); startActivity(intent); } /** * Запускаем activity в которой реализована * блокировка смены шаблона. * @param view */ public void restrictedOrientation(View view){ Intent intent=new Intent(this, RestrictedOrientation.class); startActivity(intent); } }
Создайте файл шаблона activity_automatic.xml в папке res/layout-land. Этот файл определяет вид экрана при альбомной ориентации.
layout-land/activity_automatic.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:padding="@dimen/padding_medium" android:text="@string/landscape_orientation" android:textColor="#000808" android:textSize="20dp" android:textStyle="bold|italic" tools:context=".AutomaticOrientation"/> </RelativeLayout>
Аналогичный файл для книжной ориентации создадим в папке res/layout-port. Обратите внимание, что TextView имеет разные цвета.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> layout-port/activity_automatic.xml <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:padding="@dimen/padding_medium" android:text="@string/portrait_orientation" android:textColor="#FA00FA" android:textSize="20dp" android:textStyle="bold|italic" tools:context=".MainActivity"/> </RelativeLayout>
Для реализации автоматического изменения шаблона создадим класс AutomationOrientation. Внутри класса мы просто связываем с activity xml файл.
AutomaticOrientation.java
package com.code4reference.orientationspecificlayout; import android.app.Activity; import android.os.Bundle; publicclass AutomaticOrientationextends Activity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_automatic); } }
Давайте теперь создадим Activity, внетри которого смена ориентации экрана будет происходить динамически. Создадим в папке layout два файла activity_dynamic_land.xml и activity_dynamic_port.xml, имеющих следующее содержание
layout/activity_dynamic_land.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:padding="@dimen/padding_medium" android:text="@string/landscape_orientation" <b>android:textColor="#000808"</b> android:textSize="20dp" android:textStyle="bold|italic" tools:context=".MainActivity"/> </RelativeLayout> layout/activity_dynamic_port.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:padding="@dimen/padding_medium" android:text="@string/portrait_orientation" <b>android:textColor="#FA00FA"</b> android:textSize="20dp" android:textStyle="bold|italic" tools:context=".MainActivity"/> </RelativeLayout>
Теперь создадим класс DynamicOrientationDetection, в котором будем определять текущую ориентацию экрана и выбор подходящего шаблона. В этом классе мы переопределяем метод onConfigurationChanged. В файл AndroidManifest.xml добавим поле android:configChanges="orientation". Это обеспечит вызов метода onConfigurationChanged при изменении ориентации экрана. Код AndroidManifest.xml приведен в самом конце статьи.
DynamicOrientationDetection.java
package com.code4reference.orientationspecificlayout; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; publicclass DynamicOrientationDetectionextends Activity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); //Код ниже обеспечивать текущую ориентацию экрана. setSpecificLayout(this.getResources().getConfiguration().orientation); } @Override public void onConfigurationChanged(Configuration newConfig){ super.onConfigurationChanged(newConfig); setSpecificLayout(newConfig.orientation); } /** * Выбираем шаблон в зависимости от ориентации. * @param orientation */ public void setSpecificLayout(int orientation){ if(orientation== Configuration.ORIENTATION_LANDSCAPE){ setContentView(R.layout.activity_dynamic_land); } elseif(orientation== Configuration.ORIENTATION_PORTRAIT){ setContentView(R.layout.activity_dynamic_port); } } }
Наконец займемся Activity, в которой запрещено реагировать на изменение ориентации устройства. Сделаем так, чтобы в приложении всегда использовалась альбомная ориентация. Зададим в AnroidManifest.xml атрибут android:screenOrientation="landscape" и создадим файл шаблона в папке res/layout
layout/activity_restricted.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:padding="@dimen/padding_medium" android:text="@string/restricted_orientation" android:textColor="#000808" android:textSize="20dp" android:textStyle="bold|italic" tools:context=".RestrictedOrientation"/> </RelativeLayout>
Класс RestrictedOrientation имеет вид
package com.code4reference.orientationspecificlayout; import android.app.Activity; import android.os.Bundle; publicclass RestrictedOrientationextends Activity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_restricted); } }
После добавления всех actiity в файл AndroidManifest.xml он должен иметь вид
AnroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.code4reference.orientationspecificlayout" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/title_activity_main"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".AutomaticOrientation" android:configChanges="orientation" android:label="@string/title_activity_automatic"> <intent-filter> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".DynamicOrientationDetection" <b>android:configChanges="orientation"</b> android:label="@string/title_activity_dynamic"> <intent-filter> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".RestrictedOrientation" <b> android:screenOrientation="landscape"</b> android:label="@string/title_acivity_restricted"> <intent-filter> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
Исходный файл проекта можно скачать из репозиторияgithub/Code4Reference.
Оригинал:Orientation specific layouts
Перевод:Александр Ледков