<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0">

<channel>

<title>Just Developer Blog, заметки с тегом: change iPad layout programmatically</title>
<link>http://bibobo.ru/tags/change-ipad-layout-programmatica/</link>
<description></description>
<generator>E2 (v3254; Aegea)</generator>

<item>
<title>Динамическое изменение лэйаута для прортретной и ландшафтной ориентации на iPad</title>
<guid isPermaLink="true">http://bibobo.ru/all/dinamicheskoe-izmenenie-leyauta-dlya-prortretnoy-i-landshaftnoy/</guid>
<link>http://bibobo.ru/all/dinamicheskoe-izmenenie-leyauta-dlya-prortretnoy-i-landshaftnoy/</link>
<comments>http://bibobo.ru/all/dinamicheskoe-izmenenie-leyauta-dlya-prortretnoy-i-landshaftnoy/</comments>
<description>&lt;p&gt;Хороший интерфейс пользователя должен быть адаптивным и изменяться в зависимости от размера и соотношения сторон экрана. Всем известно, что компания Apple обладает своим собственным подходом к построению интерфейса. В отличии от Android, для того чтобы нарисовать интерфейс для iOS не достаточно описать его с помощью декларативного языка. На iOS придется работать в Interface Builder, рисовать контролы ручками и описывать их взаимоотношения при помощи “ограничений” (Auto Layout Constraints).&lt;/p&gt;
&lt;p&gt;&lt;input id="button_ios_ipad_layout" type="button" onclick="toggle(cut_ios_ipad_layout, button_ios_ipad_layout)" value="Читать дальше" hiddenText="Свернуть" visibleText="Читать дальше"&gt;&lt;/p&gt;
&lt;div id="cut_ios_ipad_layout" style="display: none;" displayOld=""&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Точно так же Apple обладает своим собственным видением того, как реагировать на изменение размера и соотношений сторон экрана. Для того, чтобы правильно отображать интерфейс для различных экранов Apple предлагает разработчику инструмент под названием Size Classes. Если кратко — то всего существует 2 сайз класса (один для горизонтали, второй для вертикали), каждый из которых может иметь одно из двух значений (Regular — обычный и Compact — компактный). При этом в зависимости от типа устройства и его ориентации эти сайз классы изменяют свои значения.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Например для iPhone 5 в портретной ориентации горизонтальный сайз класс будет иметь значение Compact, а вертикальный — Regular. Если iPhone развернуть в ландшафт — то сайз классы поменяются местами (горизонталь станет Regular, вертикаль — Compact).&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Таким образом начиная с iOS 7 на Size classes завязано все изменение лэйаутов в Interface Builder. При этом нельзя нарисовать два лэйаута для разных наборов сайз классов — нам необходимо включать или выключать констрейнты (Auto Layout Constraints) в зависимости от значения сайз класса. Уже на устройстве система сама поймет какие сайз классы в данный момент активны и автоматически отключит или включит соответствующие констрейнты, интерфейс будет выглядеть по разному в ландшафте или портрете.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;В случае iPad картина выглядит иначе. &lt;b&gt;Планшет обладает одинаковым значением сайз классов для горизонтали и вертикали в любой ориентации.&lt;/b&gt; Такое поведение системы добавляет некоторые сложности, когда нам нужно для портрета и ландшафта иметь различные лэйауты, например так:&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="570" data-ratio="0.96446700507614"&gt;
&lt;img src="http://bibobo.ru/pictures/1_1.png" width="570" height="591" alt="" /&gt;
&lt;img src="http://bibobo.ru/pictures/2_1.png" width="766" height="393" alt="" /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Но существует способ обойти такое поведение системы, для этого необходимо выполнить следующее:&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Добавить отдельные констрейнты для ландшафта и портрета&lt;/li&gt;
&lt;li&gt;Вывести две &lt;i&gt;IBOutlet Collection&lt;/i&gt; (одну для портрета, вторую для ландшафта) и привязать соответствующие констрейнты к соответствующему аутлету&lt;/li&gt;
&lt;li&gt;В коде подписаться обзервером на событие &lt;i&gt;UIDeviceOrientationDidChangeNotification&lt;/i&gt;. По событию проверять идиому интерфейса пользователя и по ориентации статус бара понимать как развернуто устройство, и активировать соответствующий набор констрейнтов&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Пройдемся краткой по основным этапам.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2&gt;Добавить отдельные констрейнты для ландшафта и портрета&lt;/h2&gt;
&lt;p&gt;Чтобы правильно добавить необходимые констрейнты необходимо действовать в следующем порядке:&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;1. Для начала нарисовать лэйаут под портретную ориентацию&lt;br/&gt;
2. Понять какие констрейнты будут общими, а какие будут относиться только к портрету&lt;br/&gt;
3. Для каждого &lt;b&gt;не общего&lt;/b&gt; констрейнта добавить его вариант для любой ширины и Regular высоты (Any Width &amp; Regular Height)&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="http://bibobo.ru/pictures/3_1.png" width="401" height="343" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;4. Далее выключить этот констрейнт в версии без указания сайз классов&lt;br/&gt;
5. Повторить пункты 3 и 4 для всех констрейнтов, которые будут уникальными для портретной ориентации&lt;br/&gt;
6. Теперь необходимо на том же экране добавить констрейнты для ландшафтной ориентации&lt;br/&gt;
7. Для всех констрейнтов, уникальных для ландшафтной ориентации добавить их варианты для любой ширины и компактной высоты (Any Width &amp; Compact Height)&lt;br/&gt;
8. Далее выключить этот констрейнт в версии без указания сайз классов&lt;br/&gt;
9. Повторить пункты 7 и 8 для всех констрейнтов, которые будут уникальными для ландшафтной ориентации
&lt;/p&gt;
&lt;h2&gt;Вывести две IBOutlet Collection (одну для портрета, вторую для ландшафта) и привязать соответствующие констрейнты к соответствующему аутлету&lt;/h2&gt;
&lt;p&gt;Например начнем с портретных констрейнтов, откроем Assistant Editor, найдем в левом пане наш констрейнт (он сейчас должен быть выключен) и перетянем его (&lt;b&gt;с зажатым Ctrl&lt;/b&gt;) в пан с кодом (Assistant Editor)&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="http://bibobo.ru/pictures/4_1.png" width="1253" height="485" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;В окне задания свойств аутлета необходимо ввести его имя и обязательно выбрать в поле Connection значение &lt;b&gt;Outlet Collection&lt;/b&gt;.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="http://bibobo.ru/pictures/5_1.png" width="337" height="141" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Далее нажать Connect — наш новый аутлет свяжется с констрейнтом.
Далее необходимо осуществить хитрость — не достаточно просто повторить предыдущие шаги с оставшимися констрейнтами для портретной ориентации. Оставшиеся коснтрейнты необходимо соединять с нашим аутлетом через окно инспектора соединений (Connections Inspector). Для этого необходимо выделить констрейнт, открыть его инспектор соединений и из поля Referencing Outlet Collections вытянуть соединение с нашим аутлетом.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="http://bibobo.ru/pictures/6.png" width="620" height="471" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;На этом работа в Interface Builder закончена.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2&gt;В коде подписаться обзервером на событие “UIDeviceOrientationDidChangeNotification”&lt;/h2&gt;
&lt;p&gt;В коде нашего контроллера в методе &lt;i&gt;viewDidLoad&lt;/i&gt; необходимо подписаться на событие обзервера &lt;i&gt;UIDeviceOrientationDidChangeNotification&lt;/i&gt;. Оно будет вызываться всякий раз, когда ориентация устройства изменяется.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;NSNotificationCenter.DefaultCenter.AddObserver(new NSString(&amp;quot;UIDeviceOrientationDidChangeNotification&amp;quot;), (notification) =&amp;gt;
{
	UpdateControlsFrames();
});&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Далее необходимо реализовать метод &lt;i&gt;UpdateControlsFrames()&lt;/i&gt; и внутри него по идиоме интерфейса и положению статус бара активировать констрейнты либо портрета, либо ландшафта.&lt;/p&gt;
&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code&gt;void UpdateControlsFrames()
{
	if ((new UIDevice()).UserInterfaceIdiom != UIUserInterfaceIdiom.Pad)
	{
		return;
	}

	bool isPortraint = true;
	if (UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft
		|| UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight)
	{
		isPortraint = false;
	}

	if (isPortraint)
	{
		NSLayoutConstraint.DeactivateConstraints(landscapeLayoutConstraints);
		NSLayoutConstraint.ActivateConstraints(portraintLayoutConstraints);
	}
	else
	{
		NSLayoutConstraint.DeactivateConstraints(portraintLayoutConstraints);
		NSLayoutConstraint.ActivateConstraints(landscapeLayoutConstraints);
	}

	View.SetNeedsLayout();
	View.LayoutSubviews();
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;Стоит сказать о том, что после активации констрейнтов необходимо вызвать &lt;i&gt;SetNeedsLayout()&lt;/i&gt; и &lt;i&gt;LayoutSubviews()&lt;/i&gt; у корневой &lt;i&gt;View&lt;/i&gt;, чтобы она перерисовалась с учетом последних изменений.&lt;/p&gt;
&lt;/div&gt;</description>
<pubDate>Mon, 23 Nov 2015 21:59:09 +0300</pubDate>
</item>


</channel>
</rss>