PDA

Просмотр полной версии : TabBar skin


im4LF
09.09.2010, 12:09
Есть сложность создания скина для закладок.
На картинки показана проблема:
http://lh5.ggpht.com/_266X1AuWjcs/TIiGpgwKABI/AAAAAAAAAj0/YwdFwkDFbXw/tabs.jpg

Подскажите способ реализации подобного.
Пока на ум пришло только перекрывать метод рисования верхнего бордера у NavigatorContent... Может есть более простые способы?

Bond007
09.09.2010, 17:53
На самом деле это не так просто сделать, точнее, объяснить не получится.
У вас шаблон в векторе ?

Можете скинуть свой шаблон, я попытаюсь сделать, это как вариант.

im4LF
09.09.2010, 21:47
Bond007, доброго времни суток.
К сожалению у меня растр.
Скин для табов рисовал с помощью <s:Rect ... radiusX="6">

Может что-то скинуть другое? Проблема стоит довольно остро.
Спасибо.

alatar
09.09.2010, 23:30
В скине проверьте, скорее всего ваш бордер просто перекрывается, либо выложите код скина.

im4LF
10.09.2010, 01:04
Код:
<mx:ViewStack id="myViewStack" width="100%" bottom="0" top="25">
<s:NavigatorContent id="search" label="Search" skinClass="TabSkin" visible="false">
<s:Label text="Search Screen"/>
</s:NavigatorContent>

<s:NavigatorContent id="custInfo" label="Customer Info" skinClass="TabSkin">
<s:Label text="Customer Info"/>
</s:NavigatorContent>
</mx:ViewStack>
<s:TabBar dataProvider="{myViewStack}" skinClass="skins.TestTabBarSkin" styleName="title-level2" height="24" left="0" />

TabBar:
<s:Skin ...>
<!-- host component -->
...
<!-- states -->
...
<s:DataGroup id="dataGroup" width="100%" height="100%">
<s:layout>
<s:ButtonBarHorizontalLayout gap="1"/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<s:ButtonBarButton skinClass="skins.TabBarButtonSkin" />
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
</s:Skin>

TabBarButton:
<s:SparkSkin ...>
<!-- host component -->
...
<!-- states -->
...
<!-- up -->
<s:Rect top="0" left="0" right="0" bottom="0" topLeftRadiusX="6" topRightRadiusX="6" includeIn="up">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#00abed"/>
<s:GradientEntry color="#006abc"/>
</s:LinearGradient>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="#00aef0"/>
</s:stroke>
</s:Rect>

<!-- selected -->
<s:Rect id="selectedStates" top="0" left="0" right="0" bottom="-2" topLeftRadiusX="6" topRightRadiusX="6" includeIn="selectedStates, overStates">
<s:fill>
<s:SolidColor color="#000000" alpha="0.5" />
</s:fill>
</s:Rect>

<s:Label ...>...</s:Label>
</s:SparkSkin>

Tab:
<s:Skin ...>
<!-- host component -->
...
<!-- states -->
...
<!-- полупрозрачный tab -->
<s:Rect left="0" right="0" top="0" bottom="0" radiusX="6" topLeftRadiusX="0">
<s:fill>
<s:SolidColor color="#000000" alpha="0.5" />
</s:fill>
<s:stroke>
<s:SolidColorStroke color="#ff0000" alpha="1" />
</s:stroke>
</s:Rect>

<s:Group ...>...</s:Group>

</s:Skin>

Вся проблема в том что если делать выделенную кнопку полупрозрачной (как это нарисовано на макете) то под этой кнопкой просвечивается бордер самого таба:
http://lh5.ggpht.com/_266X1AuWjcs/TIk6oM9XihI/AAAAAAAAAkI/YJGAaThQMlE/tabs.jpg

alatar
10.09.2010, 01:17
Похоже я вас неправильно понял в первый раз. Если вам нужно сделать так что бы бордюр не был виден, то вариантов всего три.
1. Отказаться от прозрачности, т.е. сделать псевдопрозрачность (фон ставится в скин элементов управления).
2. Отказаться от бордюра, или переписать метод рисования бордюра у контейнера.
3. Имитировать бордюр фильтрами (затратно для процессора, контур вокруг всего элемента управления)

Добавлено через 4 минуты
P.S. Есть еще один вариант, рисовать бордюр отдельно, опираясь на координаты и положения контейнера и табов (под табом я понимаю TabButton)

fljot
10.09.2010, 01:24
Ну или рисовать border с пробелом, или можно его стирать (BlendMode.ERASE у стриающего элемента, BlendMode.LAYER у контейнера, который с border'ом). Муторно, конечно

im4LF
10.09.2010, 08:09
alatar, фон к сожалению делать в скине нельзя, пока сделан градиент от черного к прозрачному который закрывает артефакт - но смотрится конечно плохо.

fljot, в доке написано что "This process requires that the blendMode property of the parent display object be set to flash.display.BlendMode.LAYER" (BlendMode.ERASE (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BlendMode.html?filter_flex=4.1&filter_flashplayer=10.1&filter_air=2#ERASE)) - но viewstack не является parent'ом для TabBar.

Попробовал в скине
Tab:
<s:Rect blendMode="layer" ...

а для TabBarButton:
<!-- selected -->
<s:Rect blendMode="erase" ...

Но эффекта нет (как и ожидалось) - у выделенной кнопки просто пропадает Rect, а бордер у таба не исчезает...

Может что-то надо в коде перестроить?
Или сделать обернуть ViewStack и TabBar в контейнер с тем самым бордером и кнопке делать erase уже... Попробую...

Добавлено через 2 часа 2 минуты
Помог совет fljot, добавить только обший контейнер надо для бордера:
Код:
<s:SkinnableContainer blendMode="layer" ... skinClass="skins.TabBorder">
<mx:ViewStack ...>...</mx:ViewStack>
<s:TabBar ... />
</s:SkinnableContainer>

skins.TabBorder:
<s:Rect left="0" right="0" top="25" bottom="0" radiusX="6" topLeftRadiusX="0">
<s:stroke>
<s:SolidColorStroke color="#ffffff" alpha="0.3" />
</s:stroke>
</s:Rect>

skins.TabBarButtunSkin:
<!-- черная плашка затирающия под собой все -->
<s:Rect blendMode="erase" top="0" left="0" right="0" bottom="-2" topLeftRadiusX="6" topRightRadiusX="6" includeIn="selectedStates, overStates">
<s:fill>
<s:SolidColor color="#000000" />
</s:fill>
</s:Rect>

Все вроде неплохо. Только компонент обрастает лишним контейнером.
И есть еще одна небольшая проблема - у выделенной кнопки должен быть бордер - но только на left, top, right сторонах.

Подскажите как задать s:stroke только на нужных сторонах, или исключить его на bottom?

fljot
10.09.2010, 13:37
Я вообще-то думал эту затиралку добавить во ViewStack) и LAYER задавать ViewStack'у же

im4LF
10.09.2010, 14:31
А какому элементу blendMode="erase" и как определять его ширину?
Небольшой пример, если можно?

fljot
10.09.2010, 14:38
Нарисовать какой-нибудь Shape, добавить его поверх бордера (rawChildren и всё такое), размеры высчитывать после изменения в TabBar'е (возмжно, придётся довольно жёстко связывать TabBar и ViewStack), примеров нет

im4LF
10.09.2010, 15:27
Мне кажется описанный способ с wrapper'ом удобнее.
Но вот как задать s:stroke только на нужных сторонах, или исключить его на bottom?

alatar
14.09.2010, 20:25
Но вот как задать s:stroke только на нужных сторонах, или исключить его на bottom?
Рисовать отдельно для каждой стороны, в вашем случае получится что-то типа:
┌ - ┐
будет два path'а и один line в группе, растягиваться будет только line

im4LF
16.09.2010, 23:47
Пока сделал картинкой и scale9Grid - потому что не охота было искать формулу расчета вспомогательных точек для Безье. Если подскажите - будет очень полезно.

Спасибо.

alatar
17.09.2010, 00:42
Для таких мелких скруглений хватит и кривой с одной контрольной точкой. Например если радиус 4px координаты будут такие:
Начальная точка 0,4
Конечная точка 4,0
Контрольная точка 0,0