0

希望有flex经验的人能够就此提供建议:

所以我有一个小的 flex 4 应用程序,它有自定义标题的边框容器,我希望能够在容器之间拖放它们但是......当你处理 flex 组件时 d&d 很简单,但是这个自定义标题的容器是由几个部分,例如:标签,边框容器,所以...当我尝试拖放该标题容器时,我无法抓取整个标题容器,而只能抓取其中一个部分(标签或边框框),当我这样做时drop 然后 flex 抛出元素不在同一组中的错误。

我知道这可能不是对问题的最简单解释,但也许有人已经遇到过这个问题或对此有一些经验,任何帮助表示赞赏。

嗨,我已经编辑了我的问题,以便更好地理解问题,所以我有这样的自定义标题容器的布局:

----Group A --------------------------------
|                                           |
|   --- Sub Group A --------------------    |
|   |                                   |   |
|   |   --- Item A1 --   --Item A2---   |   |
|   |   |         |     |            |  |   |
|   |   |         |     |            |  |   |
|   |   |-------------   ------------   |   |
|   |                                   |   |
|   |-----------------------------------    |
|                                           |
|-------------------------------------------

----Group B --------------------------------
|                                           |
|   --- Sub Group B --------------------    |
|   |                                   |   |
|   |   --- Item B1 --   --Item B2---   |   |
|   |   |         |      |           |  |   |
|   |   |         |      |           |  |   |
|   |   |-------------   ------------   |   |
|   |                                   |   |
|   |-----------------------------------    |
|                                           |
|-------------------------------------------

II 希望能够将 A 组与 B 组交换,并且 A 组和 B 组(子组 A 和 B)的子组必须能够相互交换,最后是子组 A 的子组& B 也必须是可交换的。现在我已经设法让子组的孩子可以交换,并且子组可以相互交换,但是......有时当我将子组 A 与 B 交换时,子组 A 落在子组 B 内. 这是一个工作进展,我正在发布可运行的代码和我的设置,虽然 TitledContainer 不包括在内,如果你需要这个组件,请告诉我:

    <?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" xmlns:titledContainer="titledContainer.*"
               >
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            import mx.core.DragSource;
            import mx.core.IUIComponent;
            import mx.core.IVisualElement;
            import mx.events.DragEvent;
            import mx.managers.DragManager;

            import spark.components.SkinnableContainer;         


            //-------------------------------------------------------------------
            // ITEM BOXES DRAG FUNCTIONS
            //--------------------------------------------------------------------

            private function handleStartDrag( evt:MouseEvent ):void
            {
                // grab the item renderer and relevant data
                var dragItem:IUIComponent = evt.target as IUIComponent;
                var dragSource:DragSource = new DragSource();
                dragSource.addData( dragItem, "item" );
                DragManager.doDrag( dragItem, dragSource, evt );

            }

            protected function handleDragEnter( evt:DragEvent ):void
            {
                if( evt.dragSource.hasFormat( "item" ) )
                    DragManager.acceptDragDrop( evt.target as IUIComponent );

            }

            protected function handleDragDrop( evt:DragEvent ):void
            {
                var dragItem:Object = evt.dragSource.dataForFormat( "item" );
                var dragItemOwner:SkinnableContainer = ( dragItem.owner as
                    SkinnableContainer );
                dragItemOwner.removeElement( dragItem as IVisualElement );
                var targetOwner:SkinnableContainer = ( evt.target as
                    SkinnableContainer );
                targetOwner.addElement( dragItem as IVisualElement );
            }

            //-------------------------------------------------------------------
            // SUB GROUPS CONTAINERS DRAG FUNCTIONS
            //--------------------------------------------------------------------


            private function handleStartDragSub( evt:MouseEvent ):void
            {
                // grab the item renderer and relevant data
                var dragItem:IUIComponent = evt.target as IUIComponent;
                var dragSource:DragSource = new DragSource();
                dragSource.addData( dragItem, "item" );
                DragManager.doDrag( dragItem, dragSource, evt );

            }

            protected function handleDragEnterSub( evt:DragEvent ):void
            {
                if( evt.dragSource.hasFormat( "item" ) )
                    DragManager.acceptDragDrop( evt.target as IUIComponent );

            }

            protected function handleDragDropSub( evt:DragEvent ):void
            {
                var dragItem:Object = evt.dragSource.dataForFormat( "item" );
                var dragItemOwner:SkinnableContainer = ( dragItem.owner as
                    SkinnableContainer );
                dragItemOwner.removeElement( dragItem as IVisualElement );
                var targetOwner:SkinnableContainer = ( evt.target as
                    SkinnableContainer );
                targetOwner.addElement( dragItem as IVisualElement );
            }

        ]]>
    </fx:Script>

    <!-- MAIN CONTAINER ~~~~~~~~~~~~~~~~~~~~~~-->
    <s:SkinnableContainer x="50" y="50" width="100%" height="100%" >
        <s:layout>
            <s:VerticalLayout />
        </s:layout>


        <!-- FIRST ROW ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->

        <s:SkinnableContainer width="100%" >
            <s:layout>
                <s:HorizontalLayout />
            </s:layout>

            <!-- First Group --> 
            <titledContainer:TitledContainer  label="Group A" width="50%" dragEnter="handleDragEnterSub(event)" dragDrop="handleDragDropSub(event)">
                <titledContainer:layout>
                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                </titledContainer:layout>

                <s:Group width="100%"  mouseDown="handleStartDragSub(event);"  >
                    <s:layout>
                        <s:HorizontalLayout />
                    </s:layout>

                    <titledContainer:TitledContainer  label="Sub Group A" width="500" dragEnter="handleDragEnter(event)" dragDrop="handleDragDrop(event)">
                        <titledContainer:layout>
                            <s:HorizontalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                        </titledContainer:layout>

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item A 1"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 1 end-->

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item A 2"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 2 end-->

                    </titledContainer:TitledContainer><!-- Front cover 2 end-->

                </s:Group>

                <s:Group width="100%"  mouseDown="handleStartDragSub(event);"  >
                    <s:layout>
                        <s:HorizontalLayout />
                    </s:layout>

                    <titledContainer:TitledContainer  label="Sub Group B" width="500" dragEnter="handleDragEnter(event)" dragDrop="handleDragDrop(event)">
                        <titledContainer:layout>
                            <s:HorizontalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                        </titledContainer:layout>

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item B3"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 3 end-->

                        <s:Group mouseDown="handleStartDrag(event);">

                            <titledContainer:TitledContainer  label="Item B4"  >
                                <titledContainer:layout>
                                    <s:VerticalLayout paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" gap="10"/>
                                </titledContainer:layout>
                            </titledContainer:TitledContainer>

                        </s:Group> <!-- Item 4 end-->

                    </titledContainer:TitledContainer><!-- Front cover 3 end-->



                </s:Group> 

            </titledContainer:TitledContainer><!-- Front cover 1 end-->

        </s:SkinnableContainer> <!-- first row end-->


    </s:SkinnableContainer>

</s:Application>

请注意,我是 Flex 和 AS3 初学者,所以请对我温柔一点,

问题是:

  1. 能够相互交换组、子组和项目(保持层次结构)并禁止错误放置,即:子组 B 内的子组 A 等。

  2. 单击自定义标题容器时,用户应该能够拖动整个组件而不是标题、边框容器或标题容器内的任何其他内容。

请对初学者温柔一点,我不是要求您为我编写代码,而是如何正确执行代码的指导,但欢迎提供代码示例,谢谢大家。

4

1 回答 1

1

纠正显示对象问题

将父自定义容器传递给 startDrag 而不是其元素。为此,您必须像往常一样通过监听来检测拖动

MOUSE_DOWN, MOUSE_MOVE, 

事件。

我想你已经这样做了,但是,按照你可能写的例子

e.target.startDrag(false, new Rectangle(bla, bla));

而不是写

myCustomContainer.startDrag(false, new Rectangle(bla,bla));

为此,有两个先决条件:

1)如果鼠标在子控件上跳舞,则找到发生拖动的正确容器。这可以相对容易,如果您的控件是直接 displayObject 后代,在显示列表父树上向上移动,只需检查容器类就足够了。用于检测父母的一个非常基本的代码示例如下:

public function detectMyContainer(t: DisplayObject){

while((t)&&(t !== root)){
    if(t is YourCustomContainer){
         return(t);
    }    
    t = DisplayObject(t).parent;
}
return(null);
}

2)您不应该在容器的子控件中阻止鼠标按下和鼠标移动事件传播,因为这会使容器失聪...

现在这将部分解决您的问题,这意味着到目前为止,您正在设法找到正确的父级并移动它,而不是子控件。

纠正组问题

当您开始拖动一个 displayObject 时,您应该将它放到同一个父级上。

如果不是,正如你已经看到的那样,as3 会冲你大喊大叫……

如果你想在不同的父对象之间移动显示对象,你应该覆盖这个行为,你已经按照我将在下面伪代码的步骤操作:

首先,您应该决定您的最终父 DisplayObjectContainer ,其中包含您将移动孩子的不同父母,通常这是舞台,但我们称之为arena

让我们将被拖动的对象称为拖动。(是的,我此时缺乏创造力):)。

1)正确检测阻力

 look detectMyContainer.

2) 将拖动坐标映射到stage

 use localToGlobal.

3)如果arena不是舞台地图,则坐标为arena

 use globalToLocal

4)从其父级中删除拖动并添加到arena

 use arena.addChild(drag)

5) 将drag.x 和drag.y 设置为竞技场映射坐标。现在你在同一个地方拖了一个更深的父母......

6) 在拖动时开始监听 MOUSE_UP

7) 开始拖动

 use drag.startDrag(...)

8)当鼠标上升时,看看drag的放置目标......现在有

 first stopDrag()

9) 适当地检测 dropTarget,它可能不是你猜到的,所以看看它的类和父母等,以确定是否有一个有效的和哪个。

10)如果 dropTarget 不存在,将拖动添加回原始父级并设置其原始坐标......(当你习惯了事情时,我打赌你会对此进行动画处理)。

11) 现在将拖动的竞技场坐标映射到dropTarget

 if arena is not stage make a localToGlobal for drag in arena

 make a globalToLocal for drag global to dropTarget local

12)从arena移除拖动并将其添加到其新的父级 dropTarget

 use dropTarget.addChild(drag)

13) 将drag.x 和drag.y 设置为dropTarget 映射坐标。

就是这样,当你编码时它会更短,不要害怕......

祝你好运。

于 2013-04-26T20:56:08.597 回答