| « Star Wars: сравнение AS2 и AS3 в наглядных примерах | Кончились праздники » |
Скроллинг в контейнерах: решение
Многие, думаю, сталкивались с необходимостью компоновки приложения с помощью Box-контейнеров. Понятно, что чаще всего приложение может иметь любой размер по горизонтали и вертикали (зависит от размера окна браузера). И, соответственно, чаще всего приходится оперировать размером контейнеров в процентах. И вот тут возникает проблема: если в одном из контейнеров контент больше по размерам, чем отводимый родительскому Box’у, то скроллинг появляется совсем не там, где мы бы хотели. Например, для такого приложения:
XML:
<?xml version="1.0" encoding="utf-8"?> | |
<mx:Application | |
xmlns:mx="http://www.adobe.com/2006/mxml" | |
layout="vertical"> | |
<mx:Style> | |
Box | |
{ | |
border-style:solid; | |
border-color:#000000; | |
} | |
Text | |
{ | |
font-size: 20; | |
} | |
</mx:Style> | |
<mx:Box | |
width="100%" | |
height="100%" /> | |
<mx:Box | |
width="100%" | |
height="100%"> | |
<mx:Text | |
width="100%"> | |
<mx:text> | |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam | |
nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat | |
volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation | |
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. | |
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse | |
molestie consequat, vel illum dolore eu feugiat nulla facilisis at | |
vero eros et accumsan et iusto odio dignissim qui blandit praesent | |
luptatum zzril delenit augue duis dolore te feugait nulla facilisi. | |
</mx:text> | |
</mx:Text> | |
</mx:Box> | |
<mx:Box | |
width="100%" | |
height="100%" /> | |
</mx:Application> |
Получим следующее:
Если мы комнем глубже, то обнаружим, что положение можно спасти путем установки фиксированной высоты контейнера:
XML:
<?xml version="1.0" encoding="utf-8"?> | |
<mx:Application | |
xmlns:mx="http://www.adobe.com/2006/mxml" | |
layout="vertical"> | |
<mx:Style> | |
Box | |
{ | |
border-style:solid; | |
border-color:#000000; | |
} | |
Text | |
{ | |
font-size: 20; | |
} | |
</mx:Style> | |
<mx:Box | |
width="100%" | |
height="100%" /> | |
<mx:Box | |
width="100%" | |
height="100"> | |
<mx:Text | |
width="100%"> | |
<mx:text> | |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam | |
nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat | |
volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation | |
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. | |
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse | |
molestie consequat, vel illum dolore eu feugiat nulla facilisis at | |
vero eros et accumsan et iusto odio dignissim qui blandit praesent | |
luptatum zzril delenit augue duis dolore te feugait nulla facilisi. | |
</mx:text> | |
</mx:Text> | |
</mx:Box> | |
<mx:Box | |
width="100%" | |
height="100%" /> | |
</mx:Application> |
Результат:
Но и это не совсем то, что нам нужно. Мы ведь хотим чтобы все три контейнера имели одинаковую высоту!
Ответ лежит внутри класса mx.containers.Box, а точнее mx.containers.utilityClasses.BoxLayout. В случае процентной высоты контейнера он просто устанавливает его высоту в сумму высот всех его детей. Непорядок!
Но теперь мы знаем, где править. Напишем два коротких класса:
- package
- {
- import mx.containers.utilityClasses.BoxLayout;
- import mx.core.Container;
- public class PercentBoxFixedLayout extends BoxLayout
- {
- override public function measure():void
- {
- var target:Container = this.target as Container;
- super.measure();
- if (!isNaN(target.percentWidth))
- {
- target.measuredMinWidth = 0;
- target.measuredWidth = 0;
- }
- if (!isNaN(target.percentHeight))
- {
- target.measuredMinHeight = 0;
- target.measuredHeight = 0;
- }
- }
- }
- }
и
- package
- {
- import mx.containers.Box;
- import mx.core.mx_internal;
- use namespace mx_internal;
- public class PercentBoxFixed extends Box
- {
- public function PercentBoxFixed ()
- {
- super();
- layoutObject = new PercentBoxFixedLayout ();
- layoutObject.target = this;
- }
- }
- }
Теперь наш пример:
XML:
<?xml version="1.0" encoding="utf-8"?> | |
<mx:Application | |
xmlns="*" | |
xmlns:mx="http://www.adobe.com/2006/mxml" | |
layout="vertical"> | |
<mx:Style> | |
Box | |
{ | |
border-style:solid; | |
border-color:#000000; | |
} | |
Text | |
{ | |
font-size: 20; | |
} | |
</mx:Style> | |
<mx:Box | |
width="100%" | |
height="100%" /> | |
<PercentBoxFixed | |
width="100%" | |
height="100%"> | |
<mx:Text | |
width="100%"> | |
<mx:text> | |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam | |
nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat | |
volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation | |
ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. | |
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse | |
molestie consequat, vel illum dolore eu feugiat nulla facilisis at | |
vero eros et accumsan et iusto odio dignissim qui blandit praesent | |
luptatum zzril delenit augue duis dolore te feugait nulla facilisi. | |
</mx:text> | |
</mx:Text> | |
</PercentBoxFixed> | |
<mx:Box | |
width="100%" | |
height="100%" /> | |
</mx:Application> |
Ну и вот желаемый результат:
Это и есть то, что нам нужно. Для VBox и HBox вы можете поступить двояко:
- Явно задавать ориентацию контейнера
direction="vertical|horizontal". - Сделать простейшие подклассы нашего
PercentBoxFixedс явным заданием в нем ориентации.
Много получилось букав ![]()
Трекбек адрес этой записи
URL трекбека (щелкните правой кнопкой мыши и скопируйте ссылку)
5 комментариев
Это и есть то, что нам нужно. Для VBox и HBox вы можете поступить двояко
Я кстати недавно столкнулся с похожей проблемой, сделал я LinkButton который может подерживать много строчность, и теперь думаю как добавить подобный функционал в Button (может быть полезным например в Header к Accordion). есть два способа
Сделать многострочную кнопку, и от нее сделать свой LinkButton, либо сделать два сабкласса - для LinkButton и Button отдельно. Все никак не решу, что лучше =)
P.S. ну как ты понимаешь, Button делать многострочным, это скорее баловство, нежели практическая нужда но обидно что фреймворк не достаточно гибок, либо я недосмотрел пути пока что я переопределяю updateDidplayList и measure.
Тем более можно вспомнить как олдскульные товарищи ругали компоненты Макромедии как раз за то, что, по их мнению, там слишком много функционала, который им не нужен
А включение в уже готовую иерархию переопределенных компонентов - действительно проблема. Понятно, что в каждом случае решается индивидуально, но постараюсь подумать над основными стратегиями...
Для того чтобы сделать Layout контейнеры, с подобным функционалом, мне нужно отдельно расширить
Box(VBox/HBox), Panel, TileWindow, Module и еще какой то компонент вроде есть, подерживающий вертикальный\горизонтальный лэйаут.
Было бы намного удобнее, если бы можно было на лету определеить класс, занимающийся расположением компонентовм.
Имхо это не гибкость, но по сравнению с v2 компонентами, это конечно прорыв =)
Пойми меня правильно, я не ругаю F2F, я скорее ворчу, что нету и этого тоже =).