views:

4150

answers:

5

Hi

I am using a HorizontalList component to display a list of images, you can drag images from another component to join the list, this all works fine.

If I do list.showDropFeedback(event) I get an unsightly black bar at the top of images in the HorizontalList - what I really want is a line to the left/right of the image, where the new one will actually sit.

I guess I need to define a custom DropFeedback to override the default. Does anyone know if there there is a way to achieve this?

Thanks!

+1  A: 

There is a style property called dropIndicatorSkin that controls the look of the line that is shown when you drag over a list based component. From the adobe docs:

dropIndicatorSkin

The skin to use to indicate where a dragged item can be dropped. When a ListBase-derived component is a potential drop target in a drag-and-drop operation, a call to the showDropFeedback() method makes an instance of this class and positions it one pixel above the itemRenderer for the item where, if the drop occurs, is the item after the dropped item. The default value is mx.controls.listClasses.ListDropIndicator.

All of the functionality is built into the HorizontalList to do what you're asking, but there seems to be a bug in the HorizontalList in which it does not set its direction property to horizontal.

All you need to do is put direction="horizontal" in the mxml declaration and it will rotate the dropIndicatorSkin 90 degrees and poistion it in between the items instead of above them:

<mx:HorizontalList ... direction="horizontal" ... />
Matt Guest
A: 

Thanks, this seems to rotate the dropIndicator as expected but produces other very unexpected behaviour. The horizontal scroll bar on the list suddenly disappears and dragging an item onto the list makes it skip straight to the end.... Feel's like I'm almost there, but not quite!

My AS3 code....

// in constructor... (extends HorizontalList)
this.direction = "horizontal";

this.addEventListener(DragEvent.DRAG_ENTER, onDragEnter);
this.addEventListener(DragEvent.DRAG_OVER, onDragOver);
this.addEventListener(DragEvent.DRAG_EXIT, onDragExit);
this.addEventListener(DragEvent.DRAG_DROP, onDragDrop);

private function onDragEnter(event:DragEvent):void {
    event.preventDefault();
    if (event.dragSource.hasFormat("treeItems") || event.dragSource.hasFormat("items")) {
        DragManager.acceptDragDrop(event.target as UIComponent);
    }
    this.showDropFeedback(event);
}

public function onDragOver(event:DragEvent):void {
    event.preventDefault();
    this.showDropFeedback(event);
}

public function onDragExit(event:DragEvent):void {
    event.preventDefault();
    this.showDropFeedback(event);
}

private function onDragDrop(event:DragEvent):void {
    event.preventDefault();
    this.hideDropFeedback(event);
    //....
}
adam
do you have a specific reason for calling preventDefault() and doing the showDropFeedback() and hideDropFeedback() yourself, or is this left over from your trying to draw the indicator manually?
Matt Guest
Removing them seems to help a little. But now my HorizontalList seems to arrange itself more like a TileList, ie. 3 rows of 3 instead of 1 row of 9 - Getting there, slowly....
adam
+2  A: 

I solved this eventually by adding the following in my Application style..

HorizontalList {
 dropIndicatorSkin: ClassReference("com.package.HorizontalListDropIndicator");
}

And creating my custom skin..

package com.package {

 import flash.display.Graphics;
 import mx.skins.ProgrammaticSkin;

 public class HorizontalListDropIndicator extends ProgrammaticSkin {

  public function HorizontalListDropIndicator() {
   super();
  }

  override protected function updateDisplayList(w:Number, h:Number):void {  
   super.updateDisplayList(w, h);

   var g:Graphics = graphics;

   g.clear();
   g.lineStyle(2, 0xFF0000);

   g.moveTo(0, 0);
   g.lineTo(0, 250);

  }
 }
}
adam
+3  A: 

Yuo can sove it by overriding showDropFeedback() method. My code below:

    import mx.controls.HorizontalList;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.mx_internal;
import mx.events.DragEvent;

use namespace mx_internal;

public class HList extends HorizontalList
{
 public function HList()
 {
  super();      
 } 


        override public function showDropFeedback(event:DragEvent):void
        {

           super.showDropFeedback(event);

            dropIndicator.setActualSize(rowHeight - 4, 4);
            DisplayObject(dropIndicator).rotation = 90;

        }



}
I don't have enough rep to edit your post, but notice that the first two import statements aren't included in the code block. You should fix that.
Adam Tuttle
+2  A: 

It looks like this is a bug in the Flex Framework:

Flex Builder 3/sdks/3.3.0/frameworks/projects/framework/src/mx/controls/HorizontalList.as (lines 95-105)

public function HorizontalList()
{
 super();

 _horizontalScrollPolicy = ScrollPolicy.AUTO;
 _verticalScrollPolicy = ScrollPolicy.OFF;

 direction = TileBaseDirection.VERTICAL;
 maxRows = 1;
 defaultRowCount = 1;
}

Notice that the constructor for HorizontalList is initializing the direction value to Vertical.

A quick and easy work-around is to simply specify direction="horizontal" in your MXML:

<mx:HorizontalList id="fooLst" direction="horizontal" dataProvider="{foo}" />

I would be surprised if this bug hasn't already been fixed (and waiting for the next release), but I will check the Flex SDK bug database and submit a report if it's not documented.

Adam Tuttle
I couldn't find a bug report for this issue, so I entered a new one: http://bugs.adobe.com/jira/browse/SDK-21268
Adam Tuttle