diff options
Diffstat (limited to 'docs/html-intl/ru/training/multiscreen')
-rw-r--r-- | docs/html-intl/ru/training/multiscreen/adaptui.jd | 212 | ||||
-rw-r--r-- | docs/html-intl/ru/training/multiscreen/index.jd | 64 | ||||
-rw-r--r-- | docs/html-intl/ru/training/multiscreen/screendensities.jd | 100 | ||||
-rw-r--r-- | docs/html-intl/ru/training/multiscreen/screensizes.jd | 279 |
4 files changed, 655 insertions, 0 deletions
diff --git a/docs/html-intl/ru/training/multiscreen/adaptui.jd b/docs/html-intl/ru/training/multiscreen/adaptui.jd new file mode 100644 index 0000000..490a64a --- /dev/null +++ b/docs/html-intl/ru/training/multiscreen/adaptui.jd @@ -0,0 +1,212 @@ +page.title=Implementing Adaptative UI Flows +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Screen Densities +previous.link=screendensities.html + +@jd:body + + +<!-- This is the training bar --> +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Содержание урока</h2> + +<ol> + <li><a href="#TaskDetermineCurLayout">Определение текущего макета</a></li> + <li><a href="#TaskReactToLayout">Дальнейшие действия в зависимости от текущего макета</a></li> + <li><a href="#TaskReuseFrag">Повторное использование фрагментов в других активностях</a></li> + <li><a href="#TaskHandleConfigChanges">Обработка изменений конфигурации экрана</a></li> +</ol> + +<h2>Дополнительные материалы</h2> + +<ul> + <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Поддержка планшетных ПК и мобильных телефонов</a></li> +</ul> + +<h2>Упражнение</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Загрузить учебное приложение</a> +<p class="filename">NewsReader.zip</p> +</div> + + +</div> +</div> + +<p>Алгоритм пользовательского интерфейса зависит от макета, который в данный момент отображается. Например, если приложение работает в двухпанельном режиме, то при нажатии на элемент в левой панели содержание отобразится в правой. В однопанельном режиме содержание откроется отдельно (в другой активности).</p> + + +<h2 id="TaskDetermineCurLayout">Определение текущего макета</h2> + +<p>Так как в реализации макетов существуют отличия, первое, что необходимо сделать, – определить, какой макет отображается в данный момент. Например, работает ли приложение в однопанельном или двухпанельном режиме. Для этого создадим запрос о том, существует ли данное представление и отображается ли оно в настоящий момент:</p> + +<pre class="prettyprint"> +public class NewsReaderActivity extends FragmentActivity { + boolean mIsDualPane; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main_layout); + + View articleView = findViewById(R.id.article); + mIsDualPane = articleView != null && + articleView.getVisibility() == View.VISIBLE; + } +} +</pre> + +<p>Обратите внимание: представленный выше код содержит запрос о том, доступна ли панель article, поскольку это удобнее, чем писать отдельные запросы для каждого макета.</p> + +<p>Кроме того, для работы с учетом существующих компонентов можно также проверять их доступность, прежде чем выполнять с ними какие-либо операции. Например, в учебном приложении News Reader есть кнопка, которая служит для доступа в меню, однако она отображается только в операционных системах Android версии ниже, чем 3.0, потому что в последующих версиях ее функцию выполняет элемент <PH>{@link android.app.ActionBar}</PH> на уровне API 11 и выше. Чтобы проверить наличие этой кнопки, добавим прослушиватель событий с помощью следующего кода:</p> + +<pre class="prettyprint"> +Button catButton = (Button) findViewById(R.id.categorybutton); +OnClickListener listener = /* create your listener here */; +if (catButton != null) { + catButton.setOnClickListener(listener); +} +</pre> + + +<h2 id="TaskReactToLayout">Дальнейшие действия в зависимости от текущего макета</h2> + +<p>Результаты некоторых операций зависят от текущего макета. Например, если в приложении News Reader в двухпанельном режиме нажать на заголовок в списке, то статья откроется в правой панели. Если же интерфейс работает в однопанельном режиме, будет запущена отдельная активность:</p> + +<pre> +@Override +public void onHeadlineSelected(int index) { + mArtIndex = index; + if (mIsDualPane) { + /* display article on the right pane */ + mArticleFragment.displayArticle(mCurrentCat.getArticle(index)); + } else { + /* start a separate activity */ + Intent intent = new Intent(this, ArticleActivity.class); + intent.putExtra("catIndex", mCatIndex); + intent.putExtra("artIndex", index); + startActivity(intent); + } +} +</pre> + +<p>Аналогично, в двухпанельном режиме должна отображаться панель действий с навигационными вкладками, а в однопанельном навигация должна быть реализована с помощью раскрывающегося списка. Приложение должно проверять, какой из этих вариантов следует использовать:</p> + +<pre> +final String CATEGORIES[] = { "Лучшие статьи", "Политика", "Экономика", "Новости технологий" }; + +public void onCreate(Bundle savedInstanceState) { + .... + if (mIsDualPane) { + /* use tabs for navigation */ + actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS); + int i; + for (i = 0; i < CATEGORIES.length; i++) { + actionBar.addTab(actionBar.newTab().setText( + CATEGORIES[i]).setTabListener(handler)); + } + actionBar.setSelectedNavigationItem(selTab); + } + else { + /* use list navigation (spinner) */ + actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST); + SpinnerAdapter adap = new ArrayAdapter<String>(this, + R.layout.headline_item, CATEGORIES); + actionBar.setListNavigationCallbacks(adap, handler); + } +} +</pre> + + +<h2 id="TaskReuseFrag">Повторное использование фрагментов в других активностях</h2> + +<p>Одним из примеров повторяющегося фрагмента является реализация части интерфейса как панели в одних конфигурациях и как отдельной активности в других. Например, если приложение News Reader работает на достаточно большом экране, текст новостной статьи отображается в правой панели, а если на маленьком, то он открывается в отдельной активности.</p> + +<p>В таких случаях следует повторно использовать подкласс <PH>{@link android.app.Fragment}</PH> в нескольких активностях. Например, в двухпанельном макете используется подкласс <code>ArticleFragment</code>:</p> + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +<p>Он же (без макета) используется при работе на маленьком экране (активность <code>ArticleActivity</code>):</p> + +<pre> +ArticleFragment frag = new ArticleFragment(); +getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit(); +</pre> + +<p>Результат будет таким же, как если бы мы объявили фрагмент в макете XML, однако в этом случае макет XML не требуется, так как фрагмент article является единственным компонентом этой активности.</p> + +<p>При создании фрагментов важно не привязывать их строго к конкретной активности. Для этого можно определить интерфейс с абстрактным описанием всех необходимых способов взаимодействия фрагмента с активностью, в которой он содержится. Затем этот интерфейс нужно реализовать в самой активности.</p> + +<p>Например, именно так работает фрагмент <code>HeadlinesFragment</code> в приложении News Reader:</p> + +<pre> +public class HeadlinesFragment extends ListFragment { + ... + OnHeadlineSelectedListener mHeadlineSelectedListener = null; + + /* Must be implemented by host activity */ + public interface OnHeadlineSelectedListener { + public void onHeadlineSelected(int index); + } + ... + + public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) { + mHeadlineSelectedListener = listener; + } +} +</pre> + +<p>Затем, когда пользователь выбирает заголовок, фрагмент оповещает об этом не указанную в коде активность, а заданный ею прослушиватель:</p> + +<pre> +public class HeadlinesFragment extends ListFragment { + ... + @Override + public void onItemClick(AdapterView<?> parent, + View view, int position, long id) { + if (null != mHeadlineSelectedListener) { + mHeadlineSelectedListener.onHeadlineSelected(position); + } + } + ... +} +</pre> + +<p>Этот метод рассматривается подробнее в разделе <a +href="{@docRoot}guide/practices/tablets-and-handsets.html">Поддержка планшетных ПК и мобильных телефонов</a>.</p> + + +<h2 id="TaskHandleConfigChanges">Обработка изменений конфигурации экрана</h2> + +<p>При реализации отдельных частей интерфейса с помощью разных активностей нужно учитывать, что интерфейс должен уметь реагировать на определенные изменения конфигурации, такие как поворот экрана.</p> + +<p>Например, на типичном планшетном ПК с размером экрана 7 дюймов под управлением ОС Android 3.0 или более поздней версии при вертикальной ориентации статья в приложении News Reader открывается с помощью отдельной активности, а при горизонтальной используется двухпанельный макет.</p> + +<p>Это означает, что если пользователь держит планшетный ПК вертикально и на экране запущена активность для просмотра статьи, приложение должно уметь определить, что ориентация была изменена на горизонтальную. Затем оно должно соответствующим образом отреагировать на изменение, то есть завершить эту активность и вернуться к основной активности, чтобы содержание отобразилось в двухпанельном макете:</p> + +<pre> +public class ArticleActivity extends FragmentActivity { + int mCatIndex, mArtIndex; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mCatIndex = getIntent().getExtras().getInt("catIndex", 0); + mArtIndex = getIntent().getExtras().getInt("artIndex", 0); + + // If should be in two-pane mode, finish to return to main activity + if (getResources().getBoolean(R.bool.has_two_panes)) { + finish(); + return; + } + ... +} +</pre> + + diff --git a/docs/html-intl/ru/training/multiscreen/index.jd b/docs/html-intl/ru/training/multiscreen/index.jd new file mode 100644 index 0000000..023eaec --- /dev/null +++ b/docs/html-intl/ru/training/multiscreen/index.jd @@ -0,0 +1,64 @@ +page.title=Designing for Multiple Screens + +trainingnavtop=true +startpage=true +next.title=Supporting Different Screen Sizes +next.link=screensizes.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Требования</h2> + +<ul> + <li>Android 1.6 или более поздней версии (для запуска учебного приложения требуется версия 2.1 или более поздняя)</li> + <li>Начальные знания о компонентах <a +href="http://developer.android.com/guide/components/activities.html">Activity</a> (активность) и <a href="http://developer.android.com/guide/components/fragments.html">Fragment</a> (фрагмент)</li> + <li>Опыт создания <a +href="http://developer.android.com/guide/topics/ui/index.html">пользовательских интерфейсов</a> для Android</li> + <li>Некоторые функции требуют использования <a +href="{@docRoot}tools/extras/support-library.html">вспомогательной библиотеки</a></li> +</ul> + +<h2>Дополнительные материалы</h2> + +<ul> + <li><a href="{@docRoot}guide/practices/screens_support.html">Поддержка нескольких экранов</a></li> +</ul> + +<h2>Упражнение</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Загрузить учебное приложение</a> +<p class="filename">NewsReader.zip</p> +</div> + +</div> +</div> + +<p>На платформе Android работают устройства с самыми разными размерами экрана: от телефонов до телевизоров. Чтобы с вашим приложением могли работать как можно больше пользователей, оно должно корректно отображаться на всех этих устройствах.</p> + +<p>Однако совместимость с разными типами устройств – это еще не все. От размера экрана зависит, какие возможности будет иметь пользователь при работе с приложением. Чтобы пользователи действительно остались довольны вашим приложением, оно должно не просто <em>поддерживать</em> разные экраны, но и быть <em>оптимизировано</em> для каждого из них.</p> + +<p>Этот модуль посвящен реализации пользовательского интерфейса, оптимизированного для разных конфигураций экрана.</p> + +<p>Код, приведенный в каждом уроке, взят из учебного приложения, в котором демонстрируются способы оптимизации для разных экранов. Вы можете загрузить его (в правой части экрана) и использовать части кода в собственном приложении.</p> + +<p class="note"><strong>Примечание</strong>. В этом модуле и в учебном приложении используется <a +href="{@docRoot}tools/extras/support-library.html">вспомогательная библиотека</a>, позволяющая работать с API <PH>{@link android.app.Fragment}</PH> в версиях до Android 3.0. Чтобы иметь возможность использовать все необходимые API, загрузите библиотеку и добавьте ее в свое приложение.</p> + + +<h2>Уроки</h2> + +<dl> + <dt><b><a href="screensizes.html">Поддержка разных размеров экрана</a></b></dt> + <dd>В этом уроке рассказывается, как создать макет, который адаптируется к разным размерам экрана, используя масштабируемые представления, объекты <PH>{@link android.widget.RelativeLayout}</PH>, квалификаторы размера и ориентации, фильтры псевдонимов и растровые изображений формата nine-patch.</dd> + + <dt><b><a href="screendensities.html">Поддержка разных разрешений экрана</a></b></dt> + <dd>В этом уроке рассказывается, как работать с экранами разного разрешения с помощью не зависящих от разрешения пикселей и как подготовить растровые изображения для каждого из них.</dd> + + <dt><b><a href="adaptui.html">Реализация адаптируемых алгоритмов работы пользовательского интерфейса</a></b></dt> + <dd>В этом уроке рассказывается, как реализовать алгоритм работы интерфейса, адаптирующийся к размеру и разрешению экрана, то есть способный определять активный макет во время выполнения приложения, выбирать дальнейшие действия на основе текущего макета и обрабатывать изменения конфигурации экрана.</dd> +</dl> diff --git a/docs/html-intl/ru/training/multiscreen/screendensities.jd b/docs/html-intl/ru/training/multiscreen/screendensities.jd new file mode 100644 index 0000000..cfd4724 --- /dev/null +++ b/docs/html-intl/ru/training/multiscreen/screendensities.jd @@ -0,0 +1,100 @@ +page.title=Supporting Different Densities +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Screen Sizes +previous.link=screensizes.html +next.title=Implementing Adaptative UI Flows +next.link=adaptui.html + +@jd:body + + +<!-- This is the training bar --> +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Содержание урока</h2> +<ol> + <li><a href="#TaskUseDP">Использование пикселей, не зависящих от разрешения</a></li> + <li><a href="#TaskProvideAltBmp">Предоставление альтернативных растровых изображений</a></li> +</ol> + +<h2>Дополнительные материалы</h2> + +<ul> + <li><a href="{@docRoot}guide/practices/screens_support.html">Поддержка нескольких экранов</a></li> + <li><a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Рекомендации по созданию значков</a></li> +</ul> + +<h2>Упражнение</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Загрузить учебное приложение</a> +<p class="filename">NewsReader.zip</p> +</div> + + +</div> +</div> + +<p>В этом уроке рассказывается, как создать интерфейс, поддерживающий разные разрешения экрана, за счет использования разных ресурсов и не зависящих от разрешения единиц измерения.</p> + +<h2 id="TaskUseDP">Использование пикселей, не зависящих от разрешения</h2> + +<p>Разработчики часто допускают одну и ту же ошибку при создании макетов – указывают размеры и расстояния с помощью абсолютных значений в пикселях. Задавать размеры в пикселях не рекомендуется, поскольку из-за различной плотности пикселей на экранах разных устройств фактический размер макета будет неодинаков. Всегда задавайте размеры в единицах <code>dp</code> или <code>sp</code>. <code>dp</code> – это не зависящий от разрешения пиксель, равный физическому пикселю на экране с плотностью 160 точек/дюйм. <code>sp</code> является аналогичной единицей измерения, но масштабируется на основе выбранного пользователем размера текста, поэтому ее следует применять для указания величины шрифта, но не размера макета.</p> + +<p>Например, если вы задаете расстояние между двумя представлениями, рекомендуется использовать <code>dp</code>, а не <code>px</code>:</p> + +<pre> +<Button android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/clickme" + android:layout_marginTop="20dp" /> +</pre> + +<p>Для определения размера шрифта всегда используйте <code>sp</code>:</p> + +<pre> +<TextView android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textSize="20sp" /> +</pre> + + +<h2 id="TaskProvideAltBmp">Предоставление альтернативных растровых изображений</h2> + +<p>Так как платформа Android предназначена для устройств с разными разрешениями экрана, необходимо позаботиться о наличии растровых изображений для каждого из четырех обобщенных типов разрешения: низкого, среднего, высокого и очень высокого. Это обеспечит оптимальное сочетание качества графики и производительности на всех устройствах.</p> + +<p>На основе исходного векторного рисунка создайте растровые изображения для каждого из указанных разрешений согласно следующей шкале размеров:</p> + +<p><ul> + <li><code>xhdpi</code>: 2,0 + <li><code>hdpi</code>: 1,5 + <li><code>mdpi</code>: 1,0 (стандартный размер) + <li><code>ldpi</code>: 0,75 +</ul></p> + +<p>Это означает, что изображение, которое на устройствах с разрешением экрана <code>xhdpi</code> имеет размер 200 x 200, на устройствах <code>hdpi</code> должно иметь размер 150 x 150, на устройствах <code>mdpi</code> – 100 x 100, а на устройствах <code>ldpi</code> – 75 x 75.</p> + +<p>Поместите файлы изображений в соответствующие подкаталоги в папке <code>res/</code>, и система автоматически выберет подходящий в зависимости от разрешения экрана устройства, на котором выполняется приложение:</p> + +<pre class="classic no-pretty-print"> +MyProject/ + res/ + drawable-xhdpi/ + awesomeimage.png + drawable-hdpi/ + awesomeimage.png + drawable-mdpi/ + awesomeimage.png + drawable-ldpi/ + awesomeimage.png +</pre> + +<p>При каждом обращении к файлу <code>@drawable/awesomeimage</code> система будет выбирать изображение, отвечающее разрешению экрана.</p> + +<p>Дополнительную информацию и советы можно найти в разделе <a +href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Рекомендации по созданию значков</a>.</p> + diff --git a/docs/html-intl/ru/training/multiscreen/screensizes.jd b/docs/html-intl/ru/training/multiscreen/screensizes.jd new file mode 100644 index 0000000..9684d77 --- /dev/null +++ b/docs/html-intl/ru/training/multiscreen/screensizes.jd @@ -0,0 +1,279 @@ +page.title=Supporting Different Screen Sizes +parent.title=Designing for Multiple Screens +parent.link=index.html + +trainingnavtop=true +next.title=Supporting Different Screen Densities +next.link=screendensities.html + +@jd:body + + +<!-- This is the training bar --> +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Содержание урока</h2> +<ol> + <li><a href="#TaskUseWrapMatchPar">Использование параметров wrap_content и match_parent</a></li> + <li><a href="#TaskUseRelativeLayout">Использование объекта RelativeLayout</a></li> + <li><a href="#TaskUseSizeQuali">Использование квалификаторов размера</a></li> + <li><a href="#TaskUseSWQuali">Использование квалификатора Smallest-width</a></li> + <li><a href="#TaskUseAliasFilters">Использование псевдонимов макетов</a></li> + <li><a href="#TaskUseOriQuali">Использование квалификаторов ориентации</a></li> + <li><a href="#TaskUse9Patch">Использование растровых изображений nine-patch</a></li> +</ol> + +<h2>Дополнительные материалы</h2> + +<ul> + <li><a href="{@docRoot}guide/practices/screens_support.html">Поддержка нескольких экранов</a></li> +</ul> + +<h2>Упражнение</h2> + +<div class="download-box"> +<a href="http://developer.android.com/shareables/training/NewsReader.zip" class="button">Загрузить учебное приложение</a> +<p class="filename">NewsReader.zip</p> +</div> + +</div> +</div> + +<p>В этом уроке описаны следующие аспекты обеспечения совместимости интерфейса с разными экранами:</p> +<ul> + <li>обеспечение способности макета адаптироваться к размеру экрана;</li> + <li>выбор макета интерфейса, отвечающего конфигурации экрана;</li> + <li>контроль правильности применяемого макета;</li> + <li>использование масштабируемых растровых изображений.</li> +</ul> + + +<h2 id="TaskUseWrapMatchPar">Использование параметров wrap_content и match_parent</h2> + +<p>Чтобы создать масштабируемый макет, способный адаптироваться к разным экранам, используйте в качестве значений ширины и высоты отдельных компонентов представления параметры <code>"wrap_content"</code> и <code>"match_parent"</code>. Если используется <code>"wrap_content"</code>, для ширины или высоты представления устанавливается минимальное значение, позволяющее уместить содержание на экран, а параметр <code>"match_parent"</code> (известный как <code>"fill_parent"</code> в API до 8 уровня) служит для растягивания компонента по размеру родительского представления.</p> + +<p>Если указать параметры <code>"wrap_content"</code> и <code>"match_parent"</code> вместо строго заданных размеров, в представлениях будет использоваться минимально необходимое место или они будут растягиваться на всю доступную длину и ширину соответственно. Например:</p> + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +<p>Обратите внимание на то, что в коде учебного приложения размеры компонентов заданы с помощью параметров <code>"wrap_content"</code> и <code>"match_parent"</code>. В результате макет правильно отображается на экранах разных размеров при разных ориентациях.</p> + +<p>Например, вот так он выглядит в вертикальной и горизонтальной ориентациях. Обратите внимание на то, как размеры компонентов автоматически адаптируются к длине и ширине:</p> + +<img src="{@docRoot}images/training/layout-hvga.png" /> +<p class="img-caption"><strong>Рисунок 1</strong>. Приложение News Reader при вертикальной (слева) и горизонтальной (справа) ориентации.</p> + + +<h2 id="TaskUseRelativeLayout">Использование объекта RelativeLayout</h2> + +<p>С помощью вложенных экземпляров объекта <PH>{@link android.widget.LinearLayout}</PH> и параметров <code>"wrap_content"</code> и <code>"match_parent"</code> можно создавать достаточно сложные макеты. Однако <PH>{@link android.widget.LinearLayout}</PH> не дает возможности точно управлять взаимным расположением дочерних представлений: в <PH>{@link android.widget.LinearLayout}</PH> они просто помещаются в ряд друг за другом. Если необходимо расположить дочерние представления иным образом, используйте объект <PH>{@link android.widget.RelativeLayout}</PH>, позволяющий задать относительные позиции компонентов. Например, одно дочернее представление можно выровнять по левому краю экрана, а другое – по правому.</p> + +<p>Например:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <TextView + android:id="@+id/label" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Type here:"/> + <EditText + android:id="@+id/entry" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/label"/> + <Button + android:id="@+id/ok" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@id/entry" + android:layout_alignParentRight="true" + android:layout_marginLeft="10dp" + android:text="OK" /> + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toLeftOf="@id/ok" + android:layout_alignTop="@id/ok" + android:text="Cancel" /> +</RelativeLayout> +</pre> + +<p>На рис. 2 показано, как этот макет выглядит на экране QVGA.</p> + +<img src="{@docRoot}images/training/relativelayout1.png" /> +<p class="img-caption"><strong>Рисунок 2</strong>. Скриншот экрана QVGA (маленького размера).</p> + +<p>На рис. 3 показано, как он выглядит на экране с большей диагональю.</p> + +<img src="{@docRoot}images/training/relativelayout2.png" /> +<p class="img-caption"><strong>Рисунок 3</strong>. Скриншот экрана WSVGA (большего размера).</p> + +<p>Обратите внимание: несмотря на изменение размера компонентов их взаимное расположение остается прежним, так как оно задано объектом <PH>{@link android.widget.RelativeLayout.LayoutParams}</PH>.</p> + + +<h2 id="TaskUseSizeQuali">Использование квалификаторов размера</h2> + +<p>Масштабируемые или относительные макеты, один из которых продемонстрирован выше, имеют свои ограничения. Хотя они позволяют создать интерфейс, способный адаптироваться к разным экранам за счет растягивания пространства внутри и вокруг компонентов, пользователю может оказаться не слишком удобно работать с таким интерфейсом. Поэтому в приложении должен использоваться не один масштабируемый макет, а несколько альтернативных вариантов для разных конфигураций экрана. Их можно создать с помощью <a href="http://developer.android.com/guide/practices/screens_support.html#qualifiers">квалификаторов конфигураций</a>, которые позволяют оперативно выбирать ресурсы, отвечающие текущим параметрам экрана (например, разные варианты макетов для экранов разных размеров).</p> + +<p>Многие приложения отображаются на больших экранах в двухпанельном режиме, при котором список элементов расположен в одной панели, а их содержание открывается в другой. Такой режим просмотра удобен на достаточно больших экранах планшетных ПК и телевизоров, однако на экране телефона эти панели следует отображать по отдельности. Для каждого режима просмотра нужно создать отдельный файл.</p> + +<ul> + <li><code>res/layout/main.xml</code>, однопанельный макет (по умолчанию): + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +</li> + <li><code>res/layout-large/main.xml</code>, двухпанельный макет: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +</li> +</ul> + +<p>Обратите внимание, что во втором случае в названии каталога использован квалификатор <code>large</code>. Этот макет будет выбран на устройствах, экраны которых считаются большими (например, 7 дюймов и более). Первый макет (без квалификаторов) будет выбран для устройств с маленьким экраном.</p> + + +<h2 id="TaskUseSWQuali">Использование квалификатора Smallest-width</h2> + +<p>Одной из проблем, с которой сталкивались разработчики приложений для устройств Android версий до 3.2, было слишком общее определение "большого" экрана. Это касалось устройств Dell Streak, первой модели Galaxy Tab и планшетных ПК с экраном размером 7 дюймов. Многие приложения требовалось по-разному отображать на разных устройствах (например, с 5- и 7-дюймовыми экранами), хотя они и относились к одной категории "больших" экранов. В Android версии 3.2 и более поздних доступен квалификатор Smallest-width.</p> + +<p>Он позволяет определять экраны с заданной минимальной шириной в dp. Например, типичный планшетный ПК с экраном 7 дюймов имеет минимальную ширину 600 dp, и если вы хотите, чтобы приложение работало на нем в двухпанельном режиме (а на меньших экранах в однопанельном), используйте два макета из предыдущего раздела, но вместо квалификатора размера <code>large</code> укажите <code>sw600dp</code>. В таком случае на экранах, минимальная ширина которых составляет 600 dp, будет использоваться двухпанельный макет.</p> + +<ul> + <li><code>res/layout/main.xml</code>, однопанельный макет (по умолчанию): + +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} +</li> + <li><code>res/layout-sw600dp/main.xml</code>, двухпанельный макет: + +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} +</li> +</ul> + +<p>Это означает, что на устройствах, минимальная ширина экрана которых не меньше 600 dp, будет выбран <code>layout-sw600dp/main.xml</code> (двухпанельный макет), а на экранах меньшего размера – <code>layout/main.xml</code> (однопанельный макет).</p> + +<p>Следует учесть, что на Android-устройствах до версии 3.2 квалификатор <code>sw600dp</code> не будет работать, поэтому для них по-прежнему нужно использовать <code>large</code>. Таким образом, вам потребуется еще один файл с названием <code>res/layout-large/main.xml</code>, идентичный файлу <code>res/layout-sw600dp/main.xml</code>. В следующем разделе вы познакомитесь с методом, который позволяет избежать дублирования таких файлов макета.</p> + + +<h2 id="TaskUseAliasFilters">Использование псевдонимов макетов</h2> + +<p>Квалификатор Smallest-width работает только на устройствах Android 3.2 или более поздних версий. Для совместимости с более ранними устройствами по-прежнему следует использовать абстрактные размеры (small, normal, large и xlarge). Например, чтобы интерфейс открывался в однопанельном режиме на телефонах и в многопанельном на планшетных ПК с 7-дюймовым экраном, телевизорах и других крупных устройствах, подготовьте следующие файлы:</p> + +<p><ul> +<li><code>res/layout/main.xml:</code> однопанельный макет;</li> +<li><code>res/layout-large:</code> многопанельный макет;</li> +<li><code>res/layout-sw600dp:</code> многопанельный макет.</li> +</ul></p> + +<p>Последние два файла идентичны: один из них предназначен для устройств Android 3.2 и новее, а второй для более старых планшетных ПК и телевизоров на платформе Android.</p> + +<p>Чтобы не создавать дубликаты файлов и упростить процесс поддержки приложения, используйте псевдонимы. Например, можно определить следующие макеты:</p> + +<ul> +<li><code>res/layout/main.xml</code> (однопанельный макет);</li> +<li><code>res/layout/main_twopanes.xml</code> (двухпанельный макет).</li> +</ul> + +<p>Затем добавьте следующие два файла:</p> + +<p><ul> +<li><code>res/values-large/layout.xml</code>: +<pre> +<resources> + <item name="main" type="layout">@layout/main_twopanes</item> +</resources> +</pre> +</li> + +<li><code>res/values-sw600dp/layout.xml</code>: +<pre> +<resources> + <item name="main" type="layout">@layout/main_twopanes</item> +</resources> +</pre> + +</li> +</ul></p> + +<p>Содержание последних двух файлов одинаково, но сами по себе они не определяют макет. Они служат для того, чтобы назначить файл <PH>{@code main}</PH> в качестве псевдонима <PH>{@code main_twopanes}</PH>. Так как в них используются селекторы <code>large</code> и <code>sw600dp</code>, они применяются к планшетным ПК и телевизорам на платформе Android независимо от версии (для версий до 3.2 используется +<PH>{@code large}</PH>, а для более новых – <code>sw600dp</code>).</p> + + +<h2 id="TaskUseOriQuali">Использование квалификаторов ориентации</h2> + +<p>Хотя некоторые макеты одинаково хорошо смотрятся в вертикальной и горизонтальной ориентациях, в большинстве случаев интерфейс все же приходится адаптировать. Ниже показано, как изменяется макет в приложении News Reader в зависимости от размера и ориентации экрана.</p> + +<p><ul> +<li><b>Маленький экран, вертикальная ориентация</b>: однопанельный вид с логотипом.</li> +<li><b>Маленький экран, горизонтальная ориентация</b>: однопанельный вид с логотипом.</li> +<li><b>Планшетный ПК с 7-дюймовым экраном, вертикальная ориентация</b>: однопанельный вид с панелью действий.</li> +<li><b>Планшетный ПК с 7-дюймовым экраном, горизонтальная ориентация</b>: двухпанельный вид с панелью действий.</li> +<li><b>Планшетный ПК с 10-дюймовым экраном, вертикальная ориентация</b>: двухпанельный вид (узкий вариант) с панелью действий.</li> +<li><b>Планшетный ПК с 10-дюймовым экраном, горизонтальная ориентация</b>: двухпанельный вид (широкий вариант) с панелью действий.</li> +<li><b>Телевизор, горизонтальная ориентация</b>: двухпанельный вид с панелью действий.</li> +</ul></p> + +<p>Каждый из этих макетов определен в XML-файле в каталоге <code>res/layout/</code>. Чтобы сопоставить их с определенными конфигурациями экрана, в приложении используются псевдонимы:</p> + +<p><code>res/layout/onepane.xml:</code></p> +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane.xml all} + +<p><code>res/layout/onepane_with_bar.xml:</code></p> +{@sample development/samples/training/multiscreen/newsreader/res/layout/onepane_with_bar.xml all} + +<p><code>res/layout/twopanes.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} + +<p><code>res/layout/twopanes_narrow.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes_narrow.xml all} + +<p>После того как все возможные макеты определены, остается сопоставить каждый из них с подходящей конфигурацией, используя квалификаторы конфигураций. Воспользуемся псевдонимами макетов:</p> + +<p><code>res/values/layouts.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/values/layouts.xml all} + +<p><code>res/values-sw600dp-land/layouts.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-land/layouts.xml +all} + +<p><code>res/values-sw600dp-port/layouts.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/values-sw600dp-port/layouts.xml +all} + +<p><code>res/values-large-land/layouts.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/values-large-land/layouts.xml all} + +<p><code>res/values-large-port/layouts.xml</code>:</p> +{@sample development/samples/training/multiscreen/newsreader/res/values-large-port/layouts.xml all} + + + +<h2 id="TaskUse9Patch">Использование растровых изображений nine-patch</h2> + +<p>Чтобы интерфейс был совместим с экранами разных размеров, используемые в нем графические элементы также должны быть адаптированы соответствующим образом. Например, фон кнопки должен одинаково хорошо выглядеть независимо от ее формы.</p> + +<p>Если использовать для компонентов, размеры которых меняются, обычные изображения, то они будут равномерно сжиматься и растягиваться, и результат будет далек от идеального. Решением являются растровые изображения формата nine-patch – специальные PNG-файлы, содержащие информацию о том, какие области можно растягивать, а какие нет.</p> + +<p>Создавая растровые изображения для масштабируемых компонентов, обязательно используйте формат nine-patch. На рис. 4 показано обычное растровое изображение (увеличенное в 4 раза для наглядности), которое мы переведем в формат nine-patch.</p> + +<img src="{@docRoot}images/training/button.png" /> +<p class="img-caption"><strong>Рисунок 4</strong>. <code>button.png</code></p> + +<p>Откройте его с помощью утилиты <ode +href="{@docRoot}tools/help/draw9patch.html"><code>draw9patch</code></a>, входящей в комплект разработчика (в каталоге <code>tools/</code>). Установите метки на левом и верхнем краях, чтобы ограничить области, которые можно растягивать. Можно также провести линию вдоль правого и нижнего краев, как показано на рис. 5, чтобы отметить области, в которых содержание должно быть зафиксировано.</p> + +<img src="{@docRoot}images/training/button_with_marks.png" /> +<p class="img-caption"><strong>Рисунок 5</strong>. <code>button.9.png</code></p> + +<p>Обратите внимание на черные пиксели по краям. Метки у верхней и левой границ обозначают те области, которые можно растягивать, а метки у правой и нижней границ – те, куда должно быть помещено содержание.</p> + +<p>Также обратите внимание на расширение <code>.9.png</code>. Оно должно быть задано именно в таком виде, чтобы система могла определить, что это формат nine-patch, а не обычный PNG-файл.</p> + +<p>При применении этого фона к компоненту (с помощью <code>android:background="@drawable/button"</code>) изображение будет растянуто по размеру кнопки, как показано на рис. 6.</p> + +<img src="{@docRoot}images/training/buttons_stretched.png" /> +<p class="img-caption"><strong>Рисунок 6</strong>. Кнопки разных размеров с файлом фона <code>button.9.png</code> в формате nine-patch.</p> + |