Просмотр полной версии : Вопросы по реализации менюшки
Привет всем, это опять я, с новичковыми вопросами )
Нужно реализвать менюшку как в приложении используй байндинг, кастом рендерер и скинирование.
Я так понял, что рабочую область нужно разбить на два компонента и разместить их друг под другом.
Собственно первый вопрос: как правильно их друг под другом разместить не задавая жестко координаты? Сейчас в качестве контейнера воспользовался VBox'ом, интересует, насколько это адекватное решение.
Далее я так понял, что нижняя часть менюшки представляет собой Panel c Label и TextInput, а вот что собой представляет верхушка? Panel? DataGrid?
Байндинг, насколько я успел понять необходи для того, чтобы связать между собой картинки/цены c переменными.
Кастомный АйтемРендерер по видимости используется для вставки картинок в компоненты.
Что собой представляет скинирование так и не смог усвоить, если кто-нибудь даст краткое определение в контексте флекса, был бы очень признателен.
Astraport
04.04.2012, 16:18
Верхушку лучше сделать TileGroup без горизонтального скролла. Ну и итемрендерер - это каждая ячейка с картинкой, рамкой и всем прочим. Ну и очень много скинирования предстоит.
Я бы создал компонент наследника Canvas/Group (смотря что используете), в нем Image, 2 Label'а и еще компонент, который выводит цену, и добавлял бы в V/H Group
Вобщем короче паника ) Пока что слепил вот такого монстра
<s:Panel title = 'Магазин' width ='410' height = '410' horizontalCenter="0" verticalCenter="0">
<s:Group>
<s:TileGroup requestedRowCount = '5' requestedColumnCount = '2' verticalGap = '1' horizontalGap = '1'>
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
<s:BorderContainer width = '200' />
</s:TileGroup>
</s:Group>
</s:Panel>
Вобщем еще ряд вопросов появился. Во первых я смотрю, что с четвертой версии флекса убрали выравнивание внутри основного контейнера приложаения, но в документации не написано куда его переложили. Собственно отсюда вопрос номер раз: где теперь нужно искать (хотя бы в каком пространстве имен) выравнивание элементов внутри приложения?
Дальше, вот собственно в коде засовываю я в панельку Бордер контейнеры, лезут они за его края, а панельке и хоть бы хны, лезут, да и пускай лезут. Есть ли свойство, которое ограничивало бы показ элементов в панельке аналогичным maxWidth/maxHeight?
Еще один вопрос который меня крайне беспокоит — почему БордерКонтейнеру нельзя назначить ширину/высоту в зависимости от размеров родителя? Мне находится это влечайшей гнусностью да и вообще просто воплощением несправедливости )
Еще один вопрос, ответ на который е смог сыскать в документации как назначить порядок в котором будут складываться элементы в ТайлГроуп? То есть ведь должна же быть штука позволяющая мне выбирать будт ли элементы заполняться слева направо или сверху вниз.
sstotenkopf
04.04.2012, 20:23
Почитайте про list и itemrenderer, я же давал вам ссылки
Дошел до такого состояния:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize = 'initData()'>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection
[Bindable]
private var dp:ArrayCollection
[Embed(source = '../images/ok.png')]
public var okImg:Class;
[Embed(source = '../images/cancel.png')]
public var cancelImg:Class;
private function initData():void
{
dp = new ArrayCollection([
{image:new okImg(), title:'Its Okay', autor:'Me'},
{image:new cancelImg(), title:'CANCEL IT!', autor:'Someone Else'}
]);
}
]]>
</fx:Script>
<s:List width="410" height="100" dataProvider = '{dp}'>
<s:itemRenderer>
<fx:Component>
<s:ItemRenderer>
<s:HGroup>
<s:Label text = 'Название книги: {data.title} Автор: {data.autor}'/>
<s:Image source = '{data.image}'/>
</s:HGroup>
</s:ItemRenderer>
</fx:Component>
</s:itemRenderer>
</s:List>
</s:WindowedApplication>
Работает, складывается.
Вопрос следующий — как разместить в листе на две колонки? как потом их перелистывать кнопками? Как организовать поиск по подстроке?
djyamato
06.04.2012, 05:37
Специально сделал для Вас
К сожалению, почему-то не выделяется первый элемент во время поиска, спать уже хочу - не вижу причину
Листаются страницы, ищется фраза в каждом айтеме и первый нашедшийся выделяется
Лист сам перематывается к выделенному айтему (ensureIndexIsVisible)
Обратите внимание как при помощи байндинга выводится надпись PAGE 1/3 (выше в коде переменные _pageIndex и _totalPages в тэге [Bindable])
С точки зрения архитектуры код ужасный, но я преследовал цель показать как можно это сделать, не более
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="350"
height="420"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Declarations>
<s:ArrayCollection id="myData">
<s:source>
<fx:Object label="Привет всем" image=""/>
<fx:Object label="это опять я" image=""/>
<fx:Object label="Нужно реализвать" image=""/>
<fx:Object label="менюшку как в" image=""/>
<fx:Object label="приложении" image=""/>
<fx:Object label="используй байндинг" image=""/>
<fx:Object label="кастом рендерер" image=""/>
<fx:Object label="и скинирование" image=""/>
<fx:Object label="Я так понял" image=""/>
<fx:Object label="что рабочую область" image=""/>
<fx:Object label="нужно разбить на два компонента" image=""/>
<fx:Object label="и разместить их друг под другом" image=""/>
<fx:Object label="item13" image=""/>
<fx:Object label="item14" image=""/>
<fx:Object label="item15" image=""/>
<fx:Object label="item16" image=""/>
<fx:Object label="item17" image=""/>
<fx:Object label="item22" image=""/>
<fx:Object label="item34" image=""/>
<fx:Object label="item3dsbdsbn" image=""/>
<fx:Object label="sdb" image=""/>
<fx:Object label="dsfbndsn" image=""/>
<fx:Object label="dsgndsfgn" image=""/>
<fx:Object label="gjn rtgn" image=""/>
<fx:Object label="retjh" image=""/>
<fx:Object label="dsfn d" image=""/>
<fx:Object label="dsfgnsdf n" image=""/>
<fx:Object label="tgjhnrtjn" image=""/>
<fx:Object label="stgjhnert" image=""/>
<fx:Object label="y,l" image=""/>
<fx:Object label="fghmked" image=""/>
<fx:Object label="sdghn" image=""/>
<fx:Object label="sdn" image=""/>
<fx:Object label="FINAL" image=""/>
</s:source>
</s:ArrayCollection>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.events.TextOperationEvent;
[Bindable]
protected var _pageIndex:int=0;
[Bindable]
protected var _totalPages:int;
protected function button1_clickHandler(event:MouseEvent):void
{
//back
_pageIndex-=1;
if(_pageIndex<0)
{
_pageIndex=0;
}
itemsList.scroller.viewport.horizontalScrollPosition=350*_pageIndex;
}
protected function button2_clickHandler(event:MouseEvent):void
{
// forw
_pageIndex+=1;
if(_pageIndex>_totalPages-1)
{
_pageIndex=_totalPages-1;
}
itemsList.scroller.viewport.horizontalScrollPosition=350*_pageIndex;
}
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
// расчет количества страниц с округлением в болшую сторону
_totalPages=Math.round(myData.length/12);
}
protected function serchTextInput_changeHandler(event:TextOperationEvent):void
{
var firstFoundItemIndex:int=getFirstFoundItemIndex();
// почему-то не выделяется первый item :(
if(firstFoundItemIndex)
{
itemsList.selectedIndex=firstFoundItemIndex;
itemsList.ensureIndexIsVisible(firstFoundItemIndex);
}
else
{
itemsList.selectedIndex=-1;
itemsList.ensureIndexIsVisible(0);
}
}
// поиск первого совпадения
protected function getFirstFoundItemIndex():int
{
var total:int=myData.length;
var i:int;
var index:int;
for(i=0;i<total;i++)
{
if(String(myData.getItemAt(i).label).search(serchTextInput.text)!=-1)
{
index=i;
break
}
}
return index;
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout horizontalAlign="center"/>
</s:layout>
<s:List id="itemsList"
width="100%"
height="350"
horizontalScrollPolicy="off"
verticalScrollPolicy="off"
borderVisible="false"
itemRenderer="components.itemRenderers.CustomItemRenderer"
dataProvider="{myData}">
<s:layout>
<s:TileLayout requestedRowCount="7" horizontalGap="0" verticalGap="0" orientation="columns"/>
</s:layout>
</s:List>
<s:Group width="80%">
<s:Button left="5" label="prev" click="button1_clickHandler(event)"/>
<s:HGroup width="100%"
height="100%"
horizontalAlign="center"
verticalAlign="middle">
<s:Label text="PAGE {(_pageIndex+1)+'/'+_totalPages} "/>
</s:HGroup>
<s:Button right="5" label="next" click="button2_clickHandler(event)"/>
</s:Group>
<s:TextInput id="serchTextInput"
width="80%"
change="serchTextInput_changeHandler(event)"/>
</s:Application>
itemRenderer
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="false"
width="175"
height="50"
mouseEnabled="false">
<s:states>
<s:State name="normal"/>
<s:State name="selected"/>
</s:states>
<s:Group width="100%" height="100%">
<s:Rect left="2"
right="2"
top="2"
bottom="2">
<s:stroke>
<s:SolidColorStroke color.normal="0xcccccc" color.selected="0xff0000"/>
</s:stroke>
<s:fill>
<s:SolidColor color="0xcccccc" alpha=".3"/>
</s:fill>
</s:Rect>
</s:Group>
<s:HGroup width="100%"
height="100%"
horizontalAlign="center"
verticalAlign="middle">
<s:Label text="{data.label}" textAlign="center" width="175"/>
</s:HGroup>
</s:ItemRenderer>
О, большущее спасибо, только сегодня с утра наконец-то прочитал про ТайлЛэйаут )
Поиск по подстроке пофиксил. Проблема была в том, что нужно было проверять на значение пришедшего индекса, а не на его существование, так как когда туда приходил нулевой индекс, функция считала, что ничего не найдено.
Итоговый вид функции такой
protected function serchTextInput_changeHandler(event:TextOperationEvent):void
{
var firstFoundItemIndex:int=getFirstFoundItemIndex();
trace(firstFoundItemIndex);
if(firstFoundItemIndex > -1)
{
//Выделяем эелемент с полученным индексом и листаемся до него
itemsList.selectedIndex=firstFoundItemIndex;
itemsList.ensureIndexIsVisible(firstFoundItemIndex);
}
else
{
//Ни один элемент не выбирается
itemsList.selectedIndex = -1;
//Переходим к элементу под индексом 0
itemsList.ensureIndexIsVisible(0);
}
}
//поиск первого совпадения
protected function getFirstFoundItemIndex():int
{
var total:int=myData.length; //Записываем длину
var i:int; //Создаем счетчик
//Начинаем перебирать...
for(i = 0; i < total; i++)
{
//Если в лэйбле айтема найден введенный текст (метод search не вернул -1)
if(String(myData.getItemAt(i).label).search(serchTextInput.text) != -1 && serchTextInput.text.length > 0)
{
return i;
}
}
//Возвращаем значение
return -1;
}
Пока что просмотрел только Мейн, сейчас буду изучать айтемРендерер.
Еще раз огромное спасибо, мне это дало значительный шаг вперед )
djyamato
07.04.2012, 00:25
не
не так
а вот так
protected function serchTextInput_changeHandler(event:TextOperationEvent):void
{
if(serchTextInput.text.length!=0)
{
var firstFoundItemIndex:Object=getFirstFoundItemIndex();
if(firstFoundItemIndex!=-1)
{
trace("exists");
itemsList.selectedIndex=int(firstFoundItemIndex);
itemsList.ensureIndexIsVisible(int(firstFoundItemIndex));
}
else
{
unselect();
}
}
else
{
unselect();
}
}
protected function unselect():void
{
itemsList.selectedIndex=-1;
itemsList.ensureIndexIsVisible(0);
}
// поиск первого совпадения
protected function getFirstFoundItemIndex():int
{
var total:int=myData.length;
var i:int;
var index:int=0;
for(i=0;i<total;i++)
{
if(String(myData.getItemAt(i).label).indexOf(serchTextInput.text)!=-1)
{
index=i;
break
}
}
return index;
}
Да, так пожалуй в самом деле будет аккуратнее )
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.