Flex 101: Creating a Swipe/Slide Effect With Flex

In this example, we will walk through the creation of a swipe/slide effect inspired by the transitions that you often see in touch-capable devices when you use a finger to swipe from one screen to the next. One piece of content slides off to one side, and another piece of content seamlessly slides in from the opposite side.

Before we get into how this effect is achieved, let's first examine the effect in action... Click on the "Animate!" button below to invoke the effect. You can change the animation direction by changing the selected item in the drop down list.

At first glance you might think "oh, this is easy", and think normal show and hide effects would do the trick. If you are working with content within a mx:ViewStack (as in this example), this is not necessarily the case. Using separate show and hide mx:Move effects would actually lead to a jerky and disjointed animation, which does not at all achieve the desired effect.

In this example, I use an mx:Image to display a *capture* of the currently viewed content, and use a mx:Parallel effect to animate the slide-in of the new content and the slide out of the p_w_picpath. By capturing a snapshot of the currently visible component, you can animate the snapshot while the actual content is hidden (in order to show the new content). The mx:Parallel effect keeps everything in synch, and makes it seamless and completely un-noticeable by the user.

In this case, I have small, static-sized content, which is easy to animate. This approach also scales well to larger objects, however both objects being shown/hidden should be the same size. It also happens to be the same approach used in the one-finger swipe in the Multitouch keynote demo from Adobe Max (in the video below).

 

You can see below that the basic layout code is very simple and straightforward. There is a Panel, which contains content inside of a ViewStack. The only thing that may appear odd is the Image, where visible and includeInLayout are both false. This is the p_w_picpath that will be used to animate the content off of the screen.

 

01.<mx:Panel 
02.  title="Swipe Effect Demo"
03.  horizontalCenter="0"
04.  verticalCenter="0"
05.  width="300"
06.  height="300"
07.  layout="absolute"
08.  horizontalScrollPolicy="off"
09.  verticalScrollPolicy="off">
10.   
11.  <mx:ViewStack 
12.    id="content"
13.     width="100%" height="100%">
14.   
15.    <mx:Canvas 
16.       width="100%" height="100%" 
17.       showEffect="{showEffect}" >
18.   
19.       <mx:DateChooser width="100%" height="100%" />
20.    </mx:Canvas>
21.   
22.    <mx:Canvas 
23.       width="100%" height="100%" 
24.       showEffect="{showEffect}" >
25.   
26.       <mx:TextArea width="100%" height="100%" fontWeight="bold" fontSize="14">
27.         <mx:text>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </mx:text>
28.      </mx:TextArea>
29.    </mx:Canvas>
30.   
31.  </mx:ViewStack>
32.   
33.  <mx:Image 
34.    id="animateImage"
35.    visible="false"
36.     includeInLayout="false" />
37.   
38.  <mx:ControlBar>
39.    <mx:ComboBox 
40.       id="direction" 
41.       width="100%" 
42.       dataProvider="['up','down','left','right']" 
43.      selectedIndex="2"/>
44.    <mx:Button 
45.       label="Animate!" 
46.       width="100%" 
47.       click="animate()" />
48.  </mx:ControlBar>
49.   
50.</mx:Panel>

You may have also noticed that the show effect for the content within the viewstack referred to the showEffect instance. This is a Parallel effect that gets used to animate the new content into the screen, and the captured p_w_picpath off of the screen. One important thing to notice here is that the animateImage instance is hidden on the effectEnd instance. This is done to prevent any errors or visual artifacts.

 

01. <mx:Parallel id="showEffect" >
02.  <mx:Move 
03.     id="contentMove" />
04.  <mx:Move 
05.     id="p_w_picpathMove" 
06.     target="{animateImage}"  />
07.  <mx:effectEnd>
08.    <![CDATA[
09.      animateImage.visible = false;
10.      animateImage.includeInLayout = false;
11.    ]]>
12.  </mx:effectEnd>
13.</mx:Parallel>

Now, let's examine the code that makes it all happen. The animate function sets the size and content of the animateImage instance, and then movement parameters are set on the two mx:Move effects (parameters used for the animation). The toggleVisibility() function just toggles the visible child of the viewstack. When the visibility of the children changes, the showEffect effect instance is triggered, which triggers the smooth and seamless animation of the content.

 

01.<mx:Script>
02.  <![CDATA[
03.     import mx.effects.easing.Exponential;
04.     import mx.graphics.ImageSnapshot;
05.   
06.     private function animate() : void
07.    {
08.      animateImage.width = content.width;
09.      animateImage.height = content.height;
10.       animateImage.source = new Bitmap( ImageSnapshot.captureBitmapData( content ) );
11.      animateImage.visible = true;
12.      animateImage.includeInLayout = true;
13.   
14.       switch ( direction.text )
15.      {
16.         case "up":
17.          contentMove.xFrom = 0;
18.          contentMove.xTo = 0;
19.          contentMove.yFrom = content.height;
20.          contentMove.yTo = 0;
21.   
22.          p_w_picpathMove.xFrom = 0;
23.          p_w_picpathMove.xTo = 0;
24.          p_w_picpathMove.yFrom = 0;
25.          p_w_picpathMove.yTo = - content.height;
26.          break;
27.   
28.         case "down":
29.          contentMove.xFrom = 0;
30.          contentMove.xTo = 0;
31.          contentMove.yFrom = -content.height;
32.          contentMove.yTo = 0;
33.   
34.          p_w_picpathMove.xFrom = 0;
35.          p_w_picpathMove.xTo = 0;
36.          p_w_picpathMove.yFrom = 0;
37.          p_w_picpathMove.yTo = content.height;
38.          break;
39.   
40.         case "left":
41.          contentMove.xFrom = content.width;
42.          contentMove.xTo = 0;
43.          contentMove.yFrom = 0;
44.          contentMove.yTo = 0;
45.   
46.          p_w_picpathMove.xFrom = 0;
47.          p_w_picpathMove.xTo = -content.width;
48.          p_w_picpathMove.yFrom = 0;
49.          p_w_picpathMove.yTo = 0;
50.          break;
51.   
52.        default: //right
53.          contentMove.xFrom = - content.width;
54.          contentMove.xTo = 0;
55.          contentMove.yFrom = 0;
56.          contentMove.yTo = 0;
57.   
58.          p_w_picpathMove.xFrom = 0;
59.          p_w_picpathMove.xTo = content.width;
60.          p_w_picpathMove.yFrom = 0;
61.          p_w_picpathMove.yTo = 0;
62.          break;
63.      }
64.   
65.      toggleVisibility();
66.    }
67.   
68.     private function toggleVisibility() : void
69.    {
70.      content.selectedIndex = (content.selectedIndex+1)%content.numChildren;
71.      contentMove.target = content.selectedChild;
72.    }
73.   
74.  ]]>
75.</mx:Script>

原文地址http://www.developria.com/2009/12/flex-101-creating-an-swipeslid.html