Přejít k navigační liště

Zdroják » Různé » Flex 4: Drag-and-drop

Flex 4: Drag-and-drop

Články Různé

Technika drag-and-drop (česky „táhni-a-pusť“ nebo „přetahování“) patří k užitečným prvkům, které mohou zvýšit použitelnost vaší aplikace a zpříjemnit její užívání. Je samozřejmé, že možnost drag-and-drop nabízí i Adobe Flex. V článku si ukážeme, jak tuto techniku implementovat.

Drag-and-drop (DnD) můžeme ve Flexu aplikovat téměř na cokoliv. Některé komponenty mají nativní podporu pro drag-and-drop a umí si přímo poradit s přetahovaným objektem (List, TileList…), u jiných je alespoň možnost si podporu přidat dle vlastního uvážení.

Při implementaci DnD rozlišujeme 3 objekty:

  • Drag Initiator (zde táhnutí začíná – tj. toto je objekt, v němž původně ležel tažený objekt)
  • Drag Proxy (tažený objekt – to je ten, na němž uživatel stiskl tlačítko myši a začal jej přetahovat)
  • Drop Target (cíl vhození, tedy objekt – kontejner, nad nímž je tažený objekt puštěn)

Jedna komponenta může být současně Drag Initiator i Drop Target, záleží na tom, jak si logiku nastavíme.

Jednoduchý Drag-and-drop

Pojďme se podívat na základní možnosti techniky DnD u komponenty, která tuto techniku přímo podporuje, totiž u komponenty List. Jediné, co je potřeba nastavit, je dragEnabled="true" a dropEnabled="true". Tím je přetahování pro daný objekt povolené, a to jak „táhnutí odsud“, tak i „pouštění sem“.

Vytvoříme si dva seznamy, kde první je zdroj (má nastaveno dragEnabled) a druhý cíl (má dropEnabled).

<s:List dragEnabled="true" dataProvider="{new ArrayCollection(['Photoshop','Illustrator','Flash'])}" />
<s:List dropEnabled="true" />

Pokud chcete přetahovat více položek najednou, použijte allowMultipleSelection="true".

Celá aplikace bude vypadat následovně:

<?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" minWidth="955" minHeight="600">
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
        ]]>
    </fx:Script>
    <s:Label x="10" y="10" text="Nabídka"/>
    <s:Label x="168" y="10" text="Košík"/>
    <s:List dragEnabled="true" dropEnabled="true" allowMultipleSelection="true" dataProvider="{new ArrayCollection(['jablka','hrušky','pomeranče'])}" x="10" y="30" width="150" height="200"/>
    <s:List dragEnabled="true" dropEnabled="true" allowMultipleSelection="true" dataProvider="{new ArrayCollection()}" x="168" y="30" width="150" height="200" ></s:List>
</s:Application>

Můžeme si všimnout, že při přetahování položek z jednoho seznamu na druhý se položky kopírují, což nemusí být vždy žádoucí. Pokud chceme, aby se položky nekopírovaly, ale kompletně celé přesouvaly, použijeme vlastnost dragMoveEnabled="true". Slovo „kompletně“ je zde použito záměrně – v seznamu totiž nemusí být jen primitivní stringy, ale celé komplexní objekty a přetahovaná položka tak může nést mnohem víc informací.

Vlastní Drag-and-drop

Při psaní aplikace ve Flexu může nastat situace, kdy bude potřeba (nebo prostě jen výhodnější) udělat Drag-and-drop podle sebe, na vlastních komponentách. K tomu slouží události Drag třídy UIComponent, ze které dědí všechny standardní komponenty.

Při operacích DnD jsou na různých objektech vyvolány tyto události (samosebou ne v tomto pořadí):

  • u původního kontejneru (drag iniciator): dragStart, dragComplete
  • u cílového kontejneru (drag target): dragEnter, dragOver, dragDrop, dragExit

Význam je zřejmý z názvů – dragStart oznamuje začátek tažení, dragComplete je vyvoláno při dokončení celé operace, dragEnter říká, že objekt byl přetažen nad cílový kontejner, dragOver oznamuje, že se objekt pohybuje nad kontejnerem, dragDrop je vyvoláno při puštění objektu a dragExit oznamuje, že uživatel přetáhl objekt z kontejneru ven, aniž by jej pustil.

V dalším příkladu si názorně ukážeme, jak vybrat ze seznamu libovolný počet prvků a přetáhnout je do textového pole (TextArea). K tomu nám postačí dragEnter a dragDrop.

dragEnter potvrdíme či zamítneme příjem přetahovaných položek – DragManager.acceptDragDrop(cílovýObjekt:UIUComponent. Můžeme navíc například změnit kurzor pomocí  DragManager.showFeedback(DragManager.COPY).

dragDrop zase zpracujeme vhozená data. Po celou dobu – i v dragEnter apod. – máte k přetahovaným datům přístup přes event.dragSource, a to konkrétně pomocí metody dataForFormat. My použijeme ještě hasFormat, abychom se ujistili, že se jedná o formát dat, který jsme schopní zpracovat. Tyto formáty se mohou lišit a můžete si zavést i vlastní formát, pokud budete řešit drag-and-drop kompletně ve vlastní režii.

V tuto chvíli nás bude zajímat formát itemsByIndex, který obsahuje položky z komponenty s:List.

Celý příklad tedy bude ve finále vypadat nějak takhle. Všimněte si, že jsme rozšířili nosnou informaci ze Stringu na objekt obsahující dvě položky – nově i cenu. Pomocí labelField nastavíte, který parametr se má vypisovat. Pokud byste chtěli oba, museli byste použít labelFunction nebo vlastní itemRenderer. Pokud vás zajímá, jak se s nimi pracuje, nahlédněte do dokumentace – itemRenderer je podstatně složitější, ale zato má mnohem víc schopností (práci s ním si ukážeme v některém z dalších dílů).

Flex 4 - drag and drop

<?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" minWidth="955" minHeight="600">
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.core.IUIComponent;
            import mx.events.DragEvent;
            import mx.managers.DragManager;
            protected function textarea1_dragEnterHandler(event:DragEvent):void
            {
                DragManager.acceptDragDrop(IUIComponent(event.target));
                DragManager.showFeedback(DragManager.COPY);
            }
            protected function txt_dragDropHandler(event:DragEvent):void
            {
                if(event.dragSource.hasFormat("itemsByIndex")){
                    var data:Object = event.dragSource.dataForFormat("itemsByIndex");
                    event.target.text = "";
                    for(var i:Object in data){
                        event.target.text += data[i].nazev+": "+data[i].cena+"n";
                    }
                }
            }
        ]]>
    </fx:Script>
    <s:Label x="10" y="10" text="Nabídka"/>
    <s:Label x="168" y="10" text="Košík"/>
    <s:List dragEnabled="true" allowMultipleSelection="true" labelField="nazev" dataProvider="{new ArrayCollection([{nazev:'jablka',cena:10},{nazev:'hrušky',cena:15},{nazev:'pomeranče',cena:20}])}" x="10" y="30" width="150" height="200"/>
    <s:TextArea x="168" y="30" dragEnter="textarea1_dragEnterHandler(event)" dragDrop="txt_dragDropHandler(event)"/>
</s:Application>

Drag-and-drop plně pod kontrolou

Zatím jsme si ukázali drag-and-drop spojený s List komponentou. DragManager však obsahuje metodu doDrag. která umožňuje pracovat s jakoukoliv komponentou (obrázek, tlačítko, video…). Drag-and-drop si tak můžeme upravit od základu podle našich představ. Přestavme si, že chceme tlačítko, které po stisknutí budeme moci přenést a hodit na textové pole. Viz následující příklad:

Flex 4 - drag and drop

Kód není nijak složitý a podstatné informace jsou z něj patrné.

<?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" minWidth="955" minHeight="600">
    <fx:Script>
        <![CDATA[
            import mx.core.DragSource;
            import mx.core.IUIComponent;
            import mx.events.DragEvent;
            import mx.managers.DragManager;
            protected function textinput1_dragEnterHandler(event:DragEvent):void
            {
                DragManager.acceptDragDrop(IUIComponent(event.target));
            }
            protected function textinput1_dragDropHandler(event:DragEvent):void
            {
                event.target.text = event.dragSource.dataForFormat("mujFormat");
            }
            protected function button1_mouseDownHandler(event:MouseEvent):void
            {
                var src:DragSource = new DragSource();
                src.addData(event.target.label,"mujFormat");
                DragManager.doDrag(IUIComponent(event.target),src,event);
            }
        ]]>
    </fx:Script>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:Button x="10" y="10" label="Tlacitko, ktere nese nejake cool informace" mouseDown="button1_mouseDownHandler(event)"/>
    <s:TextInput x="10" y="77" width="245" dragEnter="textinput1_dragEnterHandler(event)" dragDrop="textinput1_dragDropHandler(event)"/>
</s:Application>

Drag-and-drop v AIRu a File Promise

V AIRu má vývojář k dispozici poměrně příjemnou funkci, a tou je interakce se soubory z file-systému na klientském počítači. Uživatel tedy může do aplikace v AIRu přetáhnout soubor ze správce souborů, který aplikace dokáže nějak zpracovat – např. jej nahraje na server. K dispozici jsou víceméně stejné události, pouze se liší prefixem native

nativeDragComplete, nativeDragDrop, nativeDragEnter, nativeDragExit, nativeDragOver, nativeDragStart, nativeDragUpdate

Tuto funkci doporučuji prozkoumat a odzkoušet si její fungování, hodně AIRových aplikací zjednodušuje práci ze soubory právě pomocí tohoto způsobu přetahování objektů z OS, a lze s ním vymyslet spoustu užitečných věcí – zpracování obrázků, zabalení souborů, konverze, upload na server atp.

V AIR 2.0 můžete navíc nyní z aplikace „vytáhnout“ soubor a přenést ho do file-systému (na plochu, do Průzkumníka, …) – této technice se říká File Promise, což je soubor, který ještě neexistuje, ale vy už ho fyzicky držíte myší „v ruce“. O tom, jakým způsobem s File Promise pracovat, píše např. Piotr Walczyszyn: File Promises with Adobe AIR

Flex 4 - drag and drop
(Autorem ilustračního obrázku je Piotr Walczyszyn)

K tomuto dílu je opět připraven soubor ukázkových aplikací ke stažení: Flex 4 – Drag and Drop

Komentáře

Odebírat
Upozornit na
guest
4 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
Zobrazit všechny komentáře
Gebauer

Flash Builder 4 beta 2 u komponenty <s:List hlásí chybu, nezná vlastnosti dragEnabled a dropEnabled. Podobný příklad http://livedocs.adobe.com/flex/3/html/help.html?content=dragdrop_4.html s mx komponentou funguje. Vypadá to že spark knihovna v betaverzi 2 se nějak liší od verze kterou má autor članku, není totiž k dispozici ani <s:TileGroup> a <s:ComboBox> zmíněný v přechozích článcích seriálu

Jack

Také jsem skoušel a mě nešli ani příklady z 2. tutoriálu

Přístupnost není jen o splnění norem: nový pohled na inkluzivní design

Přístupnost a inkluze možná nepatří mezi nejžhavější témata digitálního světa – dokud o nich nezačne mluvit Vitaly Friedman. Na WebExpo 2024 předvedl, že inkluzivní design není jen o splněných checkboxech, ale hlavně o lidech. S energií sobě vlastní obrátil zažité přístupy naruby a ukázal, že skutečně přístupný web je nejen možný, ale i nezbytný.

Efektivnější vývoj UI nebo API: Co si odnést z WebExpo 2025?

Různé
Komentáře: 0
Jak snadno implementovat moderní uživatelské rozhraní? Které funkce brzdí rychlost vašeho webu? A kdy raději sami přibrzdit, abychom využitím AI nepřekročili etické principy? Debatu aktuálních dev témat rozdmýchá sedmnáctý ročník technologické konference WebExpo, která proběhne v Praze od 28. do 30. května. Který talk či workshop si rozhodně nenechat ujít? Toto je náš redakční výběr z vývojářských hroznů.

Zapřáhněte AI jako nikdy předtím. Květnová konference WebExpo přivítá hvězdy technologického světa

Od 28. do 30. května 2025 promění pražský Palác Lucerna na tři dny technologická konference WebExpo. Na programu je více než 80 přednášek a workshopů od expertů z celého světa. WebExpo tradičně propojuje vývojáře, designéry, marketéry i byznysové lídry a nabízí praktické dovednosti, strategické myšlení a přináší nejnovější trendy nejen v oblasti AI.