Posts Tagged ‘custom accordion’

Flexible Accordion

Acordeonul din Flex este o unealta excelenta ce poate fi folosita cand se doreste combinarea unei liste cu detaliile aferente fiecarui element. Accordion are o structua facil de inteles si poate fi definit relativ simplu. Fie ca folosim ActionScript sau MXML definirea se face usor. MXML-ul exista pentru a reduce numarul de linii de cod de aceea il voi folosi si eu in urmatorul exemplu:

	[Bindable] private var cities:ArrayCollection = new ArrayCollection();

	private function initComp():void
	{
		cities.addItem({id:0, label:"Bucuresti"});
		cities.addItem({id:1, label:"Slobozia"});
		cities.addItem({id:2, label:"Urziceni"});
		cities.addItem({id:3, label:"Iasi"});
		cities.addItem({id:4, label:"Suceava"});
	}
	
		
			
			
		
	

unde CityRenderer poate contine orice fel de informatie legata de un anumit oras


	
	

Nu stiu daca si-a pus cineva problema sortarii item-urilor. Din toate cautarile mele pe net nu a rezultat ca s-ar fi gandit cineva la asa ceva. Poate pentru ca nu a fost considerat pana acum util sau poate pentru ca este inutil. Poate fi si datorita faptului ca nici acordeonul nu ofera suport pentru drag and drop in sensul ca headerele nu au predefinite handlere pentru drag and drop. Aici intra in scena DragManager cu ajutorul caruia poti determina cam orice obiect dintr-o aplicatie flex poate sa se miste sau sa fie pusa peste alta.

Avand in vedere ce am spus mai devreme despre headerele acordeonului pentru a putea gestiona evenimentele aparute in cadrul unei actiuni de tip drag and drop ar trebui sa definim o componenta custom pe care o vom numi DraggabelAccordion. Singura proprietate a acestei componente este ca defineste un renderer special pentru headere in cadrul caruia vom gestiona evenimentele de tip drag and drop.

	
	

CustomHeaderRenderer extinde componenta Button si contine handlere pentru mouseMove, dragEnter, dragExit precum si pentru dragDrop denumite intr-un mod usor de inteles. Pentru fiecare de handler voi prezenta codul precum si explicatiile aferente.

mouseMovehandler:

	private function mouseMoveHandler(event:MouseEvent):void
	{
		var dragInitiator:Button = Button(event.currentTarget);
		var ds:DragSource = new DragSource();
		DragManager.doDrag(dragInitiator, ds, event);
	}

In momentul in care mouse-ul se afla asupra render-ului, DragManager este informat ca initiatorul drag-ului este un element de tip buton, respectiv cel asupra caruia se afla cursorul precum si ca acest element suporta actiunea drag.

dragEnterHandler:

	public function dragEnterHandler(event:MouseEvent):void
	{
		var dropTarget:Button=Button(event.currentTarget);
		DragManager.acceptDragDrop(dropTarget);
		var accordion:DraggableAccordion = dropTarget.document as DraggableAccordion;
		dropTarget.graphics.lineStyle(4, 0x000000, 1);
		dropTarget.graphics.beginFill(0x00FF00);
		dropTarget.graphics.moveTo(5, dropTarget.height-2);
		dropTarget.graphics.lineTo(dropTarget.width-5, dropTarget.height-2);
	}

Avand in vedere ca drop se poate face doar asupra unui element de tip Button si mai presus de toate se poate face asupra oricarui element DragManager este informat ca elementul asupra caruia pluteste header-ul tras accepta drop. De asemenea o linie neagra este trasata la baza destinatiei pentru a informa utilizatorul unde urmeaza sa fie plasat elementul tras.

dragExitHandler:

	public function dragExitHandler(event:MouseEvent):void
	{
		var dropTarget:Button=Button(event.currentTarget);
		dropTarget.graphics.lineStyle(4, 0xffffff, 1);
		dropTarget.graphics.beginFill(0xFFFFFF);
		dropTarget.graphics.moveTo(5, dropTarget.height-2);
		dropTarget.graphics.lineTo(dropTarget.width-5, dropTarget.height-2);
	}

Functia aceasta este apelata in momentul in care butonul tras iese din aria de acoperire a tintei si nu face decat sa stearga linia de la baza tintei, in acest mod informand utilizatorul ca nu se va face drop in acest punct.

dragDropHandler:

	public function dragDropHandler(event:DragEvent):void
	{
		var sourceLabel:String = CustomHeaderRenderer(event.dragInitiator).label;
		var targetLabel:String = this.label;
		var dataSource:ArrayCollection = this.data.repeater.dataProvider;
		var key:Object;
		var source:Object;
		var sourcePosition:int = 0;
		var targetPosition:int = 0;
		for (key in dataSource)
		{
			if (dataSource[key].label == sourceLabel)
				{
					source = dataSource[key];
					sourcePosition = int(key);
				}
		}
		dataSource.removeItemAt(sourcePosition);
		for (key in dataSource)
		{
			if (dataSource[key].label == targetLabel)
				{
					targetPosition = int(key);
				}
		}
		if (targetPosition==dataSource.length-1)
		{
			dataSource.addItem(source);
		}
		else
		{
			var tempArray:Array = dataSource.source.slice(targetPosition+1,dataSource.source.length);
			var tempCollection:ArrayCollection = new ArrayCollection(tempArray);
			var i:int = dataSource.length - 1;
			for (i = dataSource.length - 1;i>targetPosition;i--)
			{
				dataSource.removeItemAt(i);
			}
			dataSource.addItem(source);
			var obj:Object;
			for each (obj in tempCollection)
			{
				dataSource.addItem(obj);
			}
		}
	}

Functia de mai sus modifica dataProvider-ul din repeater-ul acordeonului pentru a se obtine efectul dorit. Daca destinatia este chiar ultimul element din accordion aceasta este pur si simplu stearsa si readaugata la sfarsitul sirului. In celelalte cazuri se sterge elementul sursa, se copiaza elementele ce-l preced intr-un ArrayCollection temporar si se reface dataProvider-ul in forma dorita.

Pe masura ce timpul va trece si pe masura ce aplicatia pentru care a fost necesara o astfel de componenta se va dezvolta probabil voi include si alte facilitati.

Tags: , , , , ,

6 Comments



SetPageWidth