Home > drag and drop, skinning > Drag and Drop Skinning in Spark

Drag and Drop Skinning in Spark

January 18th, 2010 Leave a comment Go to comments

dndlistskinning

Customize the ItemRenderer‘s “dragging” state.  The drag indicator is the image that the user sees when they select and item and drag it away from the source container. By default the Spark List creates a drag indicator by duplicating all the ItemRenderers for the items being dragged. Therefore a natural way to customize the drag indicator is by customizing the ItemRenderer skin. Spark makes that easy by introducing the  optional “dragging” state.
Customize the List‘s optional “dropIndicator” skin part.  The drop indicator is the image that the user sees as an indicator of where the dragged items are going to be inserted in the destination container.  By default, the Spark List displays a horizontal/vertical line along the gap between the at the insertion point.  Spark makes that easy by automatically managing the “dropIndicator” optional dynamic skin part.

Customize the Drag Indicator

I’ll set up a custom ItemRenderer and I’ll flesh out the optional “dragging” state.
CustomDraggingItemRenderer.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer focusEnabled="false" 
				xmlns:fx="http://ns.adobe.com/mxml/2009" 
				xmlns:s="library://ns.adobe.com/flex/spark">
 
	<s:states>
		<s:State name="normal" />            
		<s:State name="hovered" />
		<s:State name="selected" />
		<s:State name="normalAndShowsCaret"/>
		<s:State name="hoveredAndShowsCaret"/>
		<s:State name="selectedAndShowsCaret"/>
		<s:State name="dragging"/>
	</s:states>
 
	<s:Rect left="0" right="0" top="0" bottom="-1" includeIn="dragging">
		<s:stroke>
			<s:SolidColorStroke color="0xDDBBCC" weight="1"/>
		</s:stroke>
		<s:fill>
			<s:SolidColor color="0x5010CC" alpha="0.3"/>
		</s:fill>
	</s:Rect>
	<s:Label id="labelDisplay" verticalCenter="0" 
			 left="3" right="3" top="6" bottom="4" 
			 fontWeight.dragging="bold"/>
 
</s:ItemRenderer>

When the Spark List creates the duplicate ItemRenderes for the drag indicator, it will set them to their “dragging” state. Note that at that point the List’s data item will be rendered by two ItemRender instances – one to display the item in the List itself and one to display the item in the drag indicator.

Customize the Drop Indicator

I’ll set up a custom List skin. I’ll replace the “dropIndicator” skin part. Note that since the part is a dynamic part (created only during drag-and-drop operation) it’s placed inside the <fx:Declarations/> tag.
CustomDropIndicatorListSkin.mxml:

 <fx:Declarations>
    <!--- 
          Defines the appearance of the the List's drop indicator.
          To customize the drop indicator appearance, create a custom ListSkin class.
          The List's layout takes care to size and position the dropIndicator.
          The size of the <code>dropIndicator</code> is typically set to the size of the 
          gaps between the items.
          The minimum and maximum settings are typically respected only in the direction
          along the major axis (the gap axis).  For example a VerticalLayout ignores the 
          <code>minWidth</code> and <code>maxWidth</code> settings, 
          but respect <code>minHeight</code> and <code>maxHeight</code>. 
 
          @copy spark.components.List#dropIndicator
    -->
    <fx:Component id="dropIndicator">
        <s:Group minWidth="3" minHeight="3" maxWidth="3" maxHeight="3">
			<s:Line width="20" left="3" verticalCenter="2">
				<s:stroke>
					<s:SolidColorStroke color="0xFF0000"/>
				</s:stroke>
			</s:Line>
 
			<s:Path left="50" verticalCenter="-2" scaleX="-1" 
					data="M 0 5 L 30 5 26 0 40 8 26 16 30 11 0 11 Z">
				<s:stroke>
					<s:LinearGradientStroke rotation="5" weight="1">
						<s:GradientEntry color="0xD8D8D8"/>
						<s:GradientEntry color="0x000000"/>
					</s:LinearGradientStroke>
				</s:stroke>
				<s:fill>
					<s:LinearGradient rotation="90">
						<s:GradientEntry color="0xD8D8D8" />
						<s:GradientEntry color="0x888888" />
					</s:LinearGradient>
				</s:fill>
			</s:Path>
        </s:Group>
    </fx:Component>
</fx:Declarations>

Click on the image at the top of the page to see the example in action. The sources are available here. The example was compiled with the Gumbo Flex SDK build 13553.

  1. Jochen Szostek
    January 19th, 2010 at 01:42 | #1

    Hi Evtim,

    Thanks for the nice example!

    How did you create the “M 0 5 L 30 5 26 0 40 8 26 16 30 11 0 11 Z” path data?
    Looks like something Catalyst generates…

    Kind regards,

    Jochen

  2. January 19th, 2010 at 02:09 | #2

    Jochen – It looks like Catalyst data (and could well be) but it also looks like SVG data, like what you could extract from Fireworks or Illustrator file exports. So even without Catalyst you can still generate the shape data – draw the shape in Illustrator / Fireworks, export as an SVG file, and copy the path data from that file!

    • Evtim
      January 20th, 2010 at 01:14 | #3

      Hey Guys,

      I actually created the data by hand, just plotted some line coordinates to outline an arrow (that took some tweaking). But yeah, definitely exporting from some of the CS apps or Catalyst makes more sense 🙂

      -Evtim

  3. Jochen Szostek
    January 19th, 2010 at 02:41 | #4

    Aha. That indeed makes a lot of sense.
    Will download this example and try to replace the path data with some other SVG data.

    Thanks for sharing this info James!

    @Evtim: I think you accidently typed “dragIndicator” instead of “dropIndicator” in the sentence: “I’ll set up a custom List skin. I’ll replace the “dragIndicator” skin part.”

    • Evtim
      January 20th, 2010 at 01:10 | #5

      Thanks Jochen,
      Yep good catch about the mistype, I corrected it now.

      -Evtim

  4. Markus
    January 25th, 2010 at 03:50 | #6

    Could you share the source code? View Source is enabled but I get a 404.
    Thanks.

    Markus

    • Evtim
      January 26th, 2010 at 00:24 | #7

      Hi Markus,
      Sorry about that, I’ll have it fixed when I get a little bit of extra time. In the mean time you can use the source code link at the bottom of the post – you should be able to download the zipped sources. Let me know if that doesn’t work for you.

      -Evtim

  5. daniel
    June 11th, 2010 at 15:55 | #8

    I’ve been trying this with the Tree control and it seems to work a bit differently… the dragging state for example isn’t set by the tree control from what I understand… though its certainly possible to do so from the tree’s dragStarted event.

  6. July 28th, 2010 at 08:19 | #9

    Thanks for that! It’s so easy as I see..

  7. Stephen
    August 18th, 2010 at 10:47 | #10

    I can’t get the dragging states of custom spark ItemRenderers to display in my application. I even tried using the ItemRenderer above and it does not work for me. Yes, drag and drop is working, but the display of the drag image is not.

    In my project, the display hierarchy for my component is something like s:TitleWindow > mx:Accordion > s:NavigatorContent > s:List > s:ItemRenderer.

  8. Stephen
    August 18th, 2010 at 14:40 | #11

    @Stephen
    Problem solved. This was being caused by setting the enabled property of another component based upon mx:VBox to true, which for some reason would subsequently disallow any dragImage from displaying anywhere in the application. I suppose I should change that component over to spark.

    Now if I could only get Image children in custom a spark ItemRender to display in the dragging state.

    • Evtim
      September 18th, 2010 at 11:52 | #12

      Hi Stephen,
      Image children don’t display in the dragging state? What does your ItemRenderer look like?

  9. June 21st, 2019 at 19:07 | #13

    An intriguing discussion is worth comment. I think that you
    need to write more on this subject, it might not be a taboo subject but typically folks don’t talk about these topics.
    To the next! All the best!!

  1. January 19th, 2010 at 01:51 | #1
  2. January 19th, 2010 at 02:12 | #2
  3. January 20th, 2010 at 03:01 | #3
  4. April 14th, 2010 at 13:16 | #4
  5. September 6th, 2018 at 19:59 | #5