Flex4 实现拖拽缓动

你有在做类似Google地图这种拖拽缓动效果的应用吗?你还在为写缓动加速算法而头痛吗?如果是那么你看了下面的文章内容后你肯定会大骂一句:“TMD,原来这么简单!”。。。

费话少说,先看一下效果吧(由于是国外服务器,flash和图片加载有点慢,有请耐心等待):

效果怎么样,是不是很流畅呢!

从Demo外表可以看出他是基于Flex的Scroller组件实现的,具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<?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">
	<s:Scroller width="100%" height="100%" interactionMode="touch">
		<s:Group>
			<s:Image source="http://www.beasy.org/wp-content/uploads/2011/10/sh.jpg"/>
		</s:Group>
	</s:Scroller>
</s:Application>

Demo的代码量是非常少的,关键的地方在Scroller的interactionMode样式上,interactionMode的值有两个可选:touch、mouse。interactionMode决定了Scroller的交互方式是鼠标操作还是触屏操作。

强大的Scroller内部已经做好了我们需要的功能,我们只需要设计相关的属性或样式即可。在桌面应用开发时interactionMode的值默认为mouse,在移动项目开发时interactionMode的值默认为touch。

所以我们在Flex移动项目里面使用List组件时发现它的滑动效果和iPhone的一模一样,其实这个都是Scroller大哥的功劳啊!

到此,拖拽缓动demo的功能已经完成了,是不是巨简单呢?但他长的实在太丑了,我们要给他美化一下,也就是给Scroller定制一套皮肤。

关于Flex4皮肤的制作方法这里不细说,我只给出皮肤的原码。

说到Scroller的皮肤,我这里要说一个完整的Scroller皮肤的组成部分:

  1. 首先是一个主skin文件,主skin包含横向和纵向两个滚动条.
  2. 横向和纵向滚动条都各自有自己的skin.
  3. 滚动条双包含:左/上移按钮、右/下移按钮、轨迹轴背景、滑动块这个四个部分.

以上每个部分的每个元素都可以各自去自定义自己的skin,以下是各个部分的skin:

1. 滚动条主体ScrollerSkin.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">
 
    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.Scroller")]
    ]]>
    </fx:Metadata> 
 
    <fx:Script>
    <![CDATA[    
        /**
         *  @private
         */
        override public function beginHighlightBitmapCapture() : Boolean
        {
            var needUpdate:Boolean = super.beginHighlightBitmapCapture();
 
            // Draw an opaque rect that fill our entire skin. Our background
            // is transparent, but we don't want focus/error skins to
            // poke through.  This is safe to do since we don't have any 
            // graphic elements as direct children.
            graphics.beginFill(0);
            graphics.drawRect(0, 0, width, height);
            graphics.endFill();
 
            return needUpdate;
        }
 
        /**
         *  @private
         */
        override public function endHighlightBitmapCapture() : Boolean
        {
            var needUpdate:Boolean = super.endHighlightBitmapCapture();
 
            // Clear the rect we drew in beginBitmapCapture();
            graphics.clear();
            return needUpdate;
        }
    ]]>
    </fx:Script>
    <s:VScrollBar id="verticalScrollBar" visible="false" skinClass="skins.VScrollBarSkin"/>
    <s:HScrollBar id="horizontalScrollBar" visible="false" skinClass="skins.HScrollBarSkin"/>
</s:SparkSkin>

2. 横向滚动条HScrollBarSkin.mxml(因为使用拖动就不需要左右/上下移动的按扭了,所以这里皮肤把那两个按钮去掉了):

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="35" minHeight="15" 
    alpha.disabled="0.5" alpha.inactive="0.5">
    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.HScrollBar")]
    ]]>
    </fx:Metadata> 
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
        <s:State name="inactive" />
    </s:states>
    <s:Button id="track" left="1" right="1" width="10" 
              focusEnabled="false" tabEnabled="false"
              skinClass="skins.ScrollBarTrackSkin" />
    <s:Button id="thumb" 
              focusEnabled="false" visible.inactive="false" tabEnabled="false" mouseEnabled="false"
              skinClass="skins.ScrollBarThumbSkin" />
 
</s:SparkSkin>

3. 纵向的滚动条VScrollerSkin.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="15" minHeight="15" 
    alpha.disabled="0.5" alpha.inactive="0.5" >
    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.VScrollBar")]
    ]]>
    </fx:Metadata> 
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
        <s:State name="inactive" />
    </s:states>
    <s:Button id="track" top="1" bottom="1" width="10" 
			  focusEnabled="false" tabEnabled="false"
			  skinClass="skins.ScrollBarTrackSkin" />
    <s:Button id="thumb" 
			  skinClass="skins.ScrollBarThumbSkin" mouseEnabled="false"
              focusEnabled="false" visible.inactive="false" tabEnabled="false"/>
</s:SparkSkin>

注意这里HScrollerSkin和VScrollerSkin中的trace和thumb按钮使用的都是同一个按扭,这个是因为我横向和纵向的滚动条都是一样的外观。
4. 滚动条的轨迹ScrollerBarTrackSkin.mxml(这里轨迹没有显示任何东西,但是轨迹不能去掉,否则显示会出错,不知道为什么。)

<?xml version="1.0" encoding="utf-8"?>
<s:SparkButtonSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
             xmlns:s="library://ns.adobe.com/flex/spark" 
             xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
             minWidth="10" minHeight="10" 
             alpha.disabled="0.5">
    <fx:Metadata>
        <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.Button")]
        ]]>
    </fx:Metadata>
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
    </s:states>
	<s:Rect top="0" bottom="0" left="0" right="0" minWidth="10" minHeight="10">
	</s:Rect>
</s:SparkButtonSkin>

5. 滑动ScrollerThumbSkin.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkButtonSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
             xmlns:s="library://ns.adobe.com/flex/spark" 
             xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
             minWidth="10" minHeight="10" 
             alpha.disabled="0.5">
    <fx:Metadata>
        <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.Button")]
        ]]>
    </fx:Metadata>
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
    </s:states>
    <s:Rect top="1" left="1" right="1" bottom="1" radiusX="5" radiusY="5">
		<s:fill>
			<s:SolidColor color="0xC0C0C0" alpha="0.8"/>
		</s:fill>
	</s:Rect>
</s:SparkButtonSkin>

最后给Scroller加上skin:

<s:Scroller width="100%" height="100%" interactionMode="touch"
				skinClass="skins.ScrollerSkin">

以下是加上皮肤后的效果:

相关日志

  1. Y.Boy 说道:

    留言以示支持。

  2. xuhui 说道:

    如何让滚动条一直显示在哪里

  3. yilu 说道:

    学习了

  4. yilu 说道:

    flex4中没有找到这个interactionMode属性,问一下在哪

  1. There are no trackbacks for this post yet.

添加评论