如何在两个组件周围绘制连接边框?

发布于 2024-10-22 02:33:45 字数 1299 浏览 5 评论 0原文

在我自己解决这个问题之前,我认为我选择了 SO 社区的想法。

假设我有一个使用按钮的Image。默认情况下,图像周围没有边框。单击此图像将导致另一个组件显示在其下方或旁边。当显示第二个组件时,我想在 Image 和第二个组件周围绘制一个连接边框。

默认情况下,第二个组件不可见。只有使用 popupManagerPopUpAnchor 单击 Image 后才可见,设置 visible 属性, 点击前的示例

+--------------------------------+
|                                |
|   XXX  <-- My Image            |
|   XXX                          |
|                                |
|                                |
|                                |
|                                |
|                                |
|                                |
|                                |
+--------------------------------+

点击后的示例:

+--------------------------------+
|  +---+                         |
|  |XXX|  <-- My Image           |
|  |XXX|_______________          |
|  |                   |         |
|  |   My Second       |         |
|  |   Component       |         |
|  |                   |         |
|  |                   |         |
|  +-------------------+         |
|                                |
+--------------------------------+

创建这样的东西有多困难?

Before I tackled this myself, I thought I pick the minds of the SO community.

Let's assume I have an Image that's used a button. By default, the image has no border around it. Clicking on this Image will cause another component be displayed beneath it or next to it. When the second component is displayed, I want to draw a joined border around the Image and the second component.

The second component would not be visible by default. It would only be visible after clicking on the Image by using the popupManager, PopUpAnchor, setting the visible property, etc.

Example before clicking:

+--------------------------------+
|                                |
|   XXX  <-- My Image            |
|   XXX                          |
|                                |
|                                |
|                                |
|                                |
|                                |
|                                |
|                                |
+--------------------------------+

Example after clicking:

+--------------------------------+
|  +---+                         |
|  |XXX|  <-- My Image           |
|  |XXX|_______________          |
|  |                   |         |
|  |   My Second       |         |
|  |   Component       |         |
|  |                   |         |
|  |                   |         |
|  +-------------------+         |
|                                |
+--------------------------------+

How difficult would it be to create something like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧故 2024-10-29 02:33:45

如果你使用的是flex4/spark,那么你应该考虑换肤(无论如何,borderSides样式仅在Halo中可用)。

这是一个小示例,用于实现图像中显示的行为:

collapsed state
expanded state

它使用具有两种状态(折叠和展开)的自定义组件。
文本仅在展开状态下附加,边框皮肤也是如此。
为此,您需要两个皮肤类,它们将应用于图像组件和文本组件的父组件。

应用程序

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:my="*">
    <s:VGroup width="100%" height="100%" paddingLeft="20" paddingTop="20">
        <my:ExpandableImage id="component" width="300" />
        <s:Button label="{component.currentState}" click="component.changeState(event);" />
    </s:VGroup>
</s:WindowedApplication>

ExpandableImage.mxml //具有两种状态的自定义组件

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    verticalScrollPolicy="off" horizontalScrollPolicy="off"
    verticalGap="0" width="100%"
    currentState="collapsedState">
    <fx:Script>
        <![CDATA[

            public function changeState(event:MouseEvent):void
            {
                if (currentState == 'collapsedState')
                    currentState = 'expandedState';
                else
                    currentState = 'collapsedState';
            }

        ]]>
    </fx:Script>
    <mx:VBox id="imgHolder" borderSkin="MyImageSkin" 
        width="50" height="50" includeIn="collapsedState, expandedState" cornerRadius="5"
        backgroundAlpha="1" borderAlpha="0" backgroundColor="#FFFFFF" borderColor="#000000">
        <mx:Image id="img" source="{IMyConstants.MYLOGO}" 
            width="48" height="48"
            mouseEnabled="true" click="changeState(event)" />
    </mx:VBox>
    <mx:VBox id="txtHolder" borderSkin="MyDetailsSkin" 
        width="100%" height="100%" includeIn="expandedState" cornerRadius="5"
        backgroundAlpha="1" borderAlpha=".5" backgroundColor="#FFFFFF" borderColor="#000000">
        <mx:Text id="txt" text="{IMyConstants.LOREMIPSUM}" 
            width="100%" />
    </mx:VBox>
    <mx:states>
        <s:State name="collapsedState" />
        <s:State name="expandedState" />
    </mx:states>
    <mx:transitions>
        <mx:Transition fromState="collapsedState" toState="expandedState">
            <s:Parallel duration="500">
                <mx:Resize target="{this}" />
                <mx:SetStyleAction target="{imgHolder}" 
                    name="borderAlpha" value=".5" />
            </s:Parallel>
        </mx:Transition>
        <mx:Transition fromState="expandedState" toState="collapsedState">
            <s:Parallel duration="500">
                <mx:Resize target="{this}" />
                <mx:SetStyleAction target="{imgHolder}" 
                    name="borderAlpha" value="0" />
            </s:Parallel>
        </mx:Transition>
    </mx:transitions>
</mx:VBox>

MyImageSkin.as //要应用于图像组件父级的皮肤

public class MyImageSkin extends RectangularBorder 
{
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        var cornerRadius:Number = getStyle("cornerRadius");
        var borderColor:int = getStyle("borderColor");
        var borderAlpha:Number = getStyle("borderAlpha");
        var backgroundColor:int = getStyle("backgroundColor");
        var backgroundAlpha:Number = getStyle("backgroundAlpha");
        graphics.clear();
        //border
        drawRoundRect(0, 0, unscaledWidth, unscaledHeight, 
            {tl: cornerRadius, tr:cornerRadius, bl: 0, br: 0}, 
            borderColor, borderAlpha);
        //content
        drawRoundRect(1, 1, unscaledWidth-2, unscaledHeight-1, 
            {tl: cornerRadius, tr:cornerRadius, bl: 0, br: 0}, 
            backgroundColor, backgroundAlpha);
    }
}

MyDetailsS​​kin.as //要应用于文本父级的皮肤

public class MyDetailsSkin extends RectangularBorder 
{
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        var cornerRadius:Number = getStyle("cornerRadius");
        var borderColor:int = getStyle("borderColor");
        var borderAlpha:Number = getStyle("borderAlpha");
        var backgroundColor:int = getStyle("backgroundColor");
        var backgroundAlpha:Number = getStyle("backgroundAlpha");
        graphics.clear();
        //border
        drawRoundRect(0, 0, unscaledWidth, unscaledHeight, 
            {tl: 0, tr:cornerRadius, bl: cornerRadius, br: cornerRadius}, 
            borderColor, borderAlpha);
        //content
        drawRoundRect(1, 1, unscaledWidth-2, unscaledHeight-2, 
            {tl: 0, tr:cornerRadius, bl: cornerRadius, br: cornerRadius}, 
            backgroundColor, backgroundAlpha);
        //clear separator
        drawRoundRect(1, 0, 49, 1, {tl: 0, tr:1, bl: 1, br: 1}, backgroundColor, 1);
    }
}

我真的希望这有帮助

If you are using flex4 / spark, then you should consider skinning (anyway, the borderSides style is available only in Halo).

here is a small sample to achieve the behavior shown at the images:

collapsed state
expanded state

It uses a custom component with two states (collapsed and expanded).
The text is only attached in the expanded state, and so are the border skins.
For this you'll need two skin classes that will be applied to the image- and to the text component's parent.

The Application:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:my="*">
    <s:VGroup width="100%" height="100%" paddingLeft="20" paddingTop="20">
        <my:ExpandableImage id="component" width="300" />
        <s:Button label="{component.currentState}" click="component.changeState(event);" />
    </s:VGroup>
</s:WindowedApplication>

ExpandableImage.mxml //the custom component with two states

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    verticalScrollPolicy="off" horizontalScrollPolicy="off"
    verticalGap="0" width="100%"
    currentState="collapsedState">
    <fx:Script>
        <![CDATA[

            public function changeState(event:MouseEvent):void
            {
                if (currentState == 'collapsedState')
                    currentState = 'expandedState';
                else
                    currentState = 'collapsedState';
            }

        ]]>
    </fx:Script>
    <mx:VBox id="imgHolder" borderSkin="MyImageSkin" 
        width="50" height="50" includeIn="collapsedState, expandedState" cornerRadius="5"
        backgroundAlpha="1" borderAlpha="0" backgroundColor="#FFFFFF" borderColor="#000000">
        <mx:Image id="img" source="{IMyConstants.MYLOGO}" 
            width="48" height="48"
            mouseEnabled="true" click="changeState(event)" />
    </mx:VBox>
    <mx:VBox id="txtHolder" borderSkin="MyDetailsSkin" 
        width="100%" height="100%" includeIn="expandedState" cornerRadius="5"
        backgroundAlpha="1" borderAlpha=".5" backgroundColor="#FFFFFF" borderColor="#000000">
        <mx:Text id="txt" text="{IMyConstants.LOREMIPSUM}" 
            width="100%" />
    </mx:VBox>
    <mx:states>
        <s:State name="collapsedState" />
        <s:State name="expandedState" />
    </mx:states>
    <mx:transitions>
        <mx:Transition fromState="collapsedState" toState="expandedState">
            <s:Parallel duration="500">
                <mx:Resize target="{this}" />
                <mx:SetStyleAction target="{imgHolder}" 
                    name="borderAlpha" value=".5" />
            </s:Parallel>
        </mx:Transition>
        <mx:Transition fromState="expandedState" toState="collapsedState">
            <s:Parallel duration="500">
                <mx:Resize target="{this}" />
                <mx:SetStyleAction target="{imgHolder}" 
                    name="borderAlpha" value="0" />
            </s:Parallel>
        </mx:Transition>
    </mx:transitions>
</mx:VBox>

MyImageSkin.as //the skin to be applied on the image component's parent

public class MyImageSkin extends RectangularBorder 
{
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        var cornerRadius:Number = getStyle("cornerRadius");
        var borderColor:int = getStyle("borderColor");
        var borderAlpha:Number = getStyle("borderAlpha");
        var backgroundColor:int = getStyle("backgroundColor");
        var backgroundAlpha:Number = getStyle("backgroundAlpha");
        graphics.clear();
        //border
        drawRoundRect(0, 0, unscaledWidth, unscaledHeight, 
            {tl: cornerRadius, tr:cornerRadius, bl: 0, br: 0}, 
            borderColor, borderAlpha);
        //content
        drawRoundRect(1, 1, unscaledWidth-2, unscaledHeight-1, 
            {tl: cornerRadius, tr:cornerRadius, bl: 0, br: 0}, 
            backgroundColor, backgroundAlpha);
    }
}

MyDetailsSkin.as //the skin to be applied on the text's parent

public class MyDetailsSkin extends RectangularBorder 
{
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void 
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        var cornerRadius:Number = getStyle("cornerRadius");
        var borderColor:int = getStyle("borderColor");
        var borderAlpha:Number = getStyle("borderAlpha");
        var backgroundColor:int = getStyle("backgroundColor");
        var backgroundAlpha:Number = getStyle("backgroundAlpha");
        graphics.clear();
        //border
        drawRoundRect(0, 0, unscaledWidth, unscaledHeight, 
            {tl: 0, tr:cornerRadius, bl: cornerRadius, br: cornerRadius}, 
            borderColor, borderAlpha);
        //content
        drawRoundRect(1, 1, unscaledWidth-2, unscaledHeight-2, 
            {tl: 0, tr:cornerRadius, bl: cornerRadius, br: cornerRadius}, 
            backgroundColor, backgroundAlpha);
        //clear separator
        drawRoundRect(1, 0, 49, 1, {tl: 0, tr:1, bl: 1, br: 1}, backgroundColor, 1);
    }
}

i really hope this helps

好多鱼好多余 2024-10-29 02:33:45

很确定你可以使用样式来做到这一点
添加第三个容器,我用 ****
标记
关闭我的新容器的顶部和右侧边框(
***)
关闭图像容器的底部边框
关闭第二个组件的顶部边框

+--------------------------------+
|  +---+****************         |
|  |XXX|  <-- My Image *         |
|  |XXX|_______________*         |
|  |                   |         |
|  |   My Second       |         |
|  |   Component       |         |
|  |                   |         |
|  |                   |         |
|  +-------------------+         |
|                                |
+--------------------------------+

Pretty sure you can do this with styles
Add a third container i marked with ****
turn the top and right borders off on my new container(
***)
turn the bottom border off on your image container
turn the top border off on your second component

+--------------------------------+
|  +---+****************         |
|  |XXX|  <-- My Image *         |
|  |XXX|_______________*         |
|  |                   |         |
|  |   My Second       |         |
|  |   Component       |         |
|  |                   |         |
|  |                   |         |
|  +-------------------+         |
|                                |
+--------------------------------+
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文