Flash Builder 4 and Flex 4 Bible- P11

Chia sẻ: Cong Thanh | Ngày: | Loại File: PDF | Số trang:50

0
59
lượt xem
15
download

Flash Builder 4 and Flex 4 Bible- P11

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Flash Builder 4 and Flex 4 Bible- P11: When Macromedia first released Flash MX in 2002, the product was branded as the new way to build Rich Internet Applications (known by the acronym RIA). The term was invented at Macromedia to describe a new class of applications that would offer the benefits of being connected to the Internet, including access to various types of Web-based services, but would solve many of the nagging issues that had been inherent in browser-based applications since the mid-1990s....

Chủ đề:
Lưu

Nội dung Text: Flash Builder 4 and Flex 4 Bible- P11

  1. Chapter 16: Managing Application Navigation recalculated and rendered anew on each visit to the page. The browser offers caching of image and other assets to speed up this process, but graphical presentation in a Web page is necessarily limited. l HTML and JavaScript aren’t interpreted identically by every Web browser. In fact, one of the most costly and time-consuming aspects of classic Web application develop- ment is testing, because you must test your application on each combination of operating system, browser, and version that you want to support. Some Web application vendors handle this issue by limiting the platforms on which an application is supported. For example, Intuit’s QuickBooks Online, while a powerful and reliable Web application, is supported only on Microsoft Internet Explorer on Windows and Safari on Mac — no Firefox users allowed! Understanding Flex Navigation Navigation in Flex applications is handled at two levels with navigator containers and view states. The difference between these strategies can be described as one of the amount of visual change during a move from one presentation to another: l Navigator containers. Use these when you want to replace a rectangular region of a Flex application (a view) with a completely different visual presentation. l View states. Use these when you want to modify an existing view, by adding or removing visual components or by changing components’ properties, styles, or event listeners. In some cases, either a navigator container or a view state can get the job done, but for the most part the choice is clear: Use a navigator container to move from one view to another, and use a view state to change an existing view. Cross-Reference Detailed information about view states is available in Chapter 13. n Using Navigator Containers You create a stack of views using one of the navigator containers provided in the Flex framework. The ViewStack class is the simplest of these navigator containers. You declare the ViewStack container as a parent container that nests a collection of view components and displays only one of its nested views at any given time. The ViewStack container doesn’t have any user interface controls that enable the user to select a current view, so it’s typically controlled either with ActionScript code or with navigator bar com- ponents that use the ViewStack as a data provider and dynamically generate interactive compo- nents to control navigation. 471
  2. Part II: Designing Flex Applications Declaring a ViewStack in MXML To create a ViewStack in MXML, declare an tag set. Then declare each nested container within the tag set. You can nest either pre-built containers from the Flex framework or your own custom components. The containers you nest within the ViewStack can be either layout or navigator containers. New Feature The ViewStack, TabNavigator, and Accordion navigator containers were originally designed so they could only contain instances of the original MX container classes such as VBox, HBox, and Panel. This rule is enforced via the nested object’s inheritance hierarchy: Each of the components nested directly within a ViewStack must include mx.core.Container as one of its superclasses. If you nest most Spark compo- nents directly in a ViewStack, a type coercion error is generated at runtime when the framework tries to cast the object as Container. To solve this, nest the Spark component inside a new component named NavigatorContent. This container implements a new interface named INavigatorContent, making it compatible with the MX navigator con- tainers. To use Spark containers in a ViewStack (or in its related navigator containers, TabNavigator and Accordion), nest them in an instance of NavigatorContent. n Each container nested within a navigator container, whether implemented as a ViewStack, TabNavigator, or Accordion, should have a label property. The label is an arbitrary String that’s used in many circumstances to describe the container’s purpose to the user. You don’t always need the label property, but if you bind the stack to a navigator container that gen- erates interactive components such as Buttons, or if you use the TabNavigator or Accordion containers, the value of each nested container’s label is displayed on the interactive component that navigates to that child container. This code creates a ViewStack with five views or layers: The first three views are instances of MX containers, the fourth is a Spark Panel wrapped in NavigatorContent, and the last is an instance of a custom component that’s extended from a compatible container component. Using custom components in a navigator container The views nested within a navigator container can be defined as custom components in MXML. As described previously, a custom component that’s nested in a navigator container must extend 472
  3. Chapter 16: Managing Application Navigation either the Spark NavigatorContent component or one of the MX container classes. These include HBox, VBox, Canvas, Panel, Form, and others. The custom component in Listing 16.1 displays a Label control and a DataGrid wrapped in a NavigatorContent container. LISTING 16.1 A custom component suitable for use in a navigator container On the Web The code in Listing 16.1 is available in the Web site files as views/Authors.mxml in the chapter16 proj- ect. View components named Books.mxml and ShoppingCart.mxml are also used in these examples. n Creating a ViewStack in Design mode You can use Flash Builder’s Design mode to visually create a ViewStack and its nested views. As described previously, each of the nested views must be a container, as an instance of either a Flex framework container class or a custom component that includes the Container class in its inher- itance hierarchy. Note Flash Builder’s Design mode refers to the layers of a ViewStack as panes, and the documentation sometimes refers to them as panels. These terms refer to the nested view containers within the ViewStack. n On the Web The steps in this section assume that you’ve downloaded the files from the Web site and imported the chapter16 project. n 473
  4. Part II: Designing Flex Applications Follow these steps to create a ViewStack in Design mode: 1. Open BookStore.mxml from the chapter16 project. Notice that the application already has an instance of a custom Header component and a few layout settings: 2. Run the application. As shown in Figure 16.1, you should see that the Header compo- nent displays an image, some text, and a background image. 3. Return to Flash Builder, and switch to Design mode. FIGURE 16.1 The starting application with a custom Header component 474
  5. Chapter 16: Managing Application Navigation 4. Look in the Components view’s Navigators section, and drag a ViewStack into the application below the header. As shown in Figure 16.2, the ViewStack is represented visually by a rectangular outlined area and a toolbar with + and – buttons to add and remove views, and < and > buttons to navigate from one view to the next. FIGURE 16.2 A starting ViewStack Add view Remove view Previous view Next view The ViewStack 5. Click the + button to add a new view to the ViewStack. As shown in Figure 16.3, the Insert Pane dialog box prompts you to select a component to instantiate as a layer of the ViewStack. The list of available components includes all containers from the Flex framework and all the application’s custom components that are eligible for use in the context of a navigator container. 6. Set the Label of the new pane as Catalog. 475
  6. Part II: Designing Flex Applications 7. Select Books from the list of available containers. 8. Click OK to add the new pane to the ViewStack. 9. Repeat Steps 5 through 8, and add an instance of the Authors container with a label of Authors. FIGURE 16.3 The Insert Pane dialog box 10. Repeat Steps 5 through 8 again, and add an instance of the ShoppingCart container with a label of Shopping Cart. 11. Click the left arrow button three times to return to the first layer of the ViewStack. It should be blank. 12. Click the – button to remove the first layer, leaving only the three you added. 13. Run the application. When the application appears, it should display the Books con- tainer, because it was the first layer declared within the ViewStack. Note The application displays only one layer at this point, because you haven’t added any interactive components to control navigation. n 14. Return to Flash Builder, and switch to Source mode. The generated ViewStack code looks like this: 476
  7. Chapter 16: Managing Application Navigation The Design mode tool for generating ViewStack code makes a great start but has these issues: l The ViewStack is always generated with an initial height and width of 200 pixels each. You can change the ViewStack dimensions in Design mode by dragging the ViewStack handles, or in the Properties view. And of course, you can always change or remove the dimensions completely in Source mode. l Design mode has no mechanism for visually reordering a ViewStack container’s layers. If you want to change the order of the views, you must do so in Source mode by changing the order of the child containers. l All containers’ MXML declarations are generated with tag sets, such as: Particularly when using custom components, the MXML code would be more efficient with empty tag syntax: This is purely a matter of code aesthetics though, and it doesn’t have any negative effect on application functionality or performance. After generating a ViewStack in Design mode, revise the generated code as needed in Source mode. Working with navigator containers in ActionScript When a navigator container is initially constructed and displayed, it displays the currently active view (by default, the first view declared in the stack). You can change the active view at runtime with ActionScript commands that reference one of these ViewStack properties: l selectedIndex:int. The numeric index position of the active container within the stack. l selectedChild:Container. The object reference of the active container within the stack. Using selectedIndex The selectedIndex property returns the index position of the currently active container, as determined by the order of the ViewStack container’s display list. When declaring a ViewStack in MXML, the display list order and the order of MXML declaration are the same. As with all index operations in ActionScript, indexing starts at 0. So the first container with the view stack is at position 0, the second at position 1, and so on. 477
  8. Part II: Designing Flex Applications To change the currently selected view by index, set the stack’s selectedIndex property to the numeric index of the container you want to activate. This code makes the viewstack1 contain- er’s second layer visible and active: Because indexing always begins at 0, this Button would enable the user to navigate to the first layer of a stack: Using numChildren The numChildren property returns the total number of layers in the stack as an int value. Taking into account the 0-based indexing offset, clicking this Button would result in navigating to the last layer of a stack: Navigating forward and backward through view stack layers You can navigate forward and backward through layers of a view stack by incrementing or decre- menting the stack’s selectedIndex property. This Button would enable the user to move to the previous layer of a stack: Note The selectedIndex property of a ViewStack can’t be set to less than 0. If the Button control in the pre- ceding code is clicked when the ViewStack container’s selectedIndex is already set to 0, the command is ignored and there is no runtime error. n You also can navigate forward through a stack, but if you set the selectedIndex to a value greater than the stack’s highest available index, an “array out of bounds” error results. You can pre- vent this by wrapping the code to navigate forward in a conditional clause that checks to be sure that the last container in the stack isn’t already active: private function navForward():void { if (viewstack1.selectedIndex != viewstack1.numChildren-1) { viewstack1.selectedIndex++; } } Alternatively, you can set the Button control’s enabled property to false when selected Index indicates that a forward or backward navigation either wouldn’t work or would result in a runtime error. Binding expressions that evaluate selectedIndex and return a Boolean value to the enabled property can handle this task dynamically. 478
  9. Chapter 16: Managing Application Navigation The following Button control that navigates forward is enabled only when the ViewStack con- tainer’s selectedIndex isn’t already set to the highest index: Managing binding issues In the preceding code example, the binding expression used in the enabled property might be executed upon application startup before the ViewStack container’s numChidren property can be correctly evaluated. If this happens, you might see that the Button controls are incorrectly enabled and disabled upon application startup. To fix this sort of timing issue, call the ViewStack container’s executeBindings() method with a recursive argument of true to reevaluate all its dependent binding expressions. If you call this method upon the ViewStack container’s creationComplete event, it evaluates any bound property values such as numChildren again and the Button control’s enabled states will be correctly calculated: The application in Listing 16.2 implements forward and backward navigation with a ViewStack and Button controls. Each Button control has its enabled property set through a binding expression, and the ViewStack re-executes its bindings upon its creationComplete event. LISTING 16.2 An application using forward and backward navigation continued 479
  10. Part II: Designing Flex Applications LISTING 16.2 (continued) On the Web The code in Listing 16.2 is available in the Web site files as BookStoreIndexNavigation.mxml in the chapter16 project. n Figure 16.4 shows the resulting application, with Previous and Next buttons to handle backward and forward navigation. Using selectedChild The ViewStack container’s selectedChild property accesses the stack’s currently visible view by its object reference. To use this property, each of the stack’s nested containers should be assigned a unique id: To select an active view by the container’s unique id, set the ViewStack container’s selectedChild: Note Notice that there are no quotes around the cartView container’s id when it’s assigned in this way. You’re accessing the id as a variable or component instance id, not a String value. n 480
  11. Chapter 16: Managing Application Navigation FIGURE 16.4 An application with forward and backward navigation Note When navigating with selectedChild set to a container’s unique id, because your navigation will be hard- coded, you typically don’t need to assign a label property to each container. The label property becomes useful when dynamically generating user interface controls for navigation. n The application in Listing 16.3 implements navigation using Button controls for each of the nested containers in a ViewStack. Each Button control explicitly navigates to its container by the container’s unique id. LISTING 16.3 An application using explicit navigation by unique id continued 481
  12. Part II: Designing Flex Applications LISTING 16.3 (continued) On the Web The code in Listing 16.3 is available in the Web site files as BookStoreReferenceNavigation.mxml in the chapter16 project. n Figure 16.5 shows the resulting application, with explicit Button controls to handle navigation to each nested container. Managing creation policy The ViewStack, TabNavigator, and Accordion containers support a property named creationPolicy that manages the manner in which their nested view containers are instanti- ated at runtime. These are possible values of creationPolicy: l auto (the default) l all l none l queued When creationPolicy is set to the default of auto, only the initially active view is completely instantiated at first. The other view containers also are instantiated, but their child controls are left null. Any attempt to address these objects in ActionScript code while they’re not yet instantiated results in a null error. 482
  13. Chapter 16: Managing Application Navigation FIGURE 16.5 An application with explicit navigation by unique id This behavior is known as deferred instantiation and is a strategy for optimizing client-side perfor- mance in Flash Player. In a navigator container that contains dozens of views or more, if the applica- tion has to instantiate all the content before the user can interact with anything, significant delays can occur. To prevent this issue, the default behavior makes content visible as early as possible. You see the effect of deferred instantiation when you try to initialize some property of a nested component before the user decides to visit that content at runtime and get a runtime error. You can solve this by setting the navigator container’s creationPolicy property to all, meaning that all the views are instantiated during the navigator container’s instantiation. This strategy can work fine in a small- to medium-size application that doesn’t have a large number of nested views, or if you need to interact with child objects of nested views prior to the user viewing them. Alternatively, you can set creationPolicy to none, meaning that you don’t want the nested components ever to be instantiated automatically, and then take complete control over the process by explicitly calling the nested container’s createComponentsFromDescriptors() method when you see fit. Note The Container class implements such methods as addChild(), addChildAt(), and removeChild() that enable you to explicitly control the contents and order of a container’s nested child objects at runtime. You can use these methods to control not just which objects have been instantiated, but which are currently nested children of a navigator container. n 483
  14. Part II: Designing Flex Applications Tip The creationPolicy property is also implemented in layout containers. Layout containers instantiate all their child objects at the same time by default. If you prefer to take control over the instantiation process, set the layout container’s creationPolicy property to none, and then instantiate the child objects as neces- sary using with the container’s createComponentsFromDescriptors() method. n Finally, the effect of setting creationPolicy to queued means that you want to instantiate all objects automatically, but instead of creating all objects simultaneously (as with the setting of all), each nested view component’s content is instantiated only after the prior component’s instantiation has been completed. Managing navigator container dimensions By default, navigator containers size to the first visible child container. Any subsequent navigation results in bumping the child container up to the top left if it is smaller than the instantiated size, or the implementation of scrollbars if the container is larger. You can set the height and width of a navigator container using absolute pixel dimensions, per- centage dimensions, or dynamic sizing. You can use two common strategies for handling navigator container sizing: l Set the navigator container’s dimensions to specific pixel or percentage dimensions, and then set the nested container sizes to 100 percent height and width. Each of the nested view containers then resizes to fill the available space in the navigator container. l Set the nested containers to specific pixel dimensions, and set the navigator contain- er’s resizeToContent property to true. The navigator container then resizes to accom- modate each newly active view as the user navigates through the application. Caution Setting resizeToContent to true forces the navigator container to remeasure and redraw itself as the user navigates through the application. This can cause interesting and unintended visual effects, particularly when the navigator container has a visible border or background. n Using Navigator Bar Containers If you want a user to be able to navigate to any container within a ViewStack, you can use one of the navigator bar containers that are included with the Flex framework. The framework uses four navigator bar containers: l ButtonBar. Generates one Button control for each nested container. There are both MX and Spark versions of ButtonBar. The Spark version implements toggle buttons, making the ToggleButtonBar component unnecessary. l LinkBar. Generates one MX LinkButton control for each nested container. 484
  15. Chapter 16: Managing Application Navigation l TabBar. Generates one Tab for each nested container. l ToggleButtonBar. Generates one MX Button control for each nested container and shows the current selection through the Button control’s toggle behavior. Note You won’t find a Tab component or ActionScript class in the Flex documentation, but it’s used internally as a style selector to manage a TabBar’s visual presentation. Because each Tab is an instance of this internal class, you can change certain styles such as the amount of padding within each Tab: @namespace mx “library://ns.adobe.com/flex/mx”; mx|Tab { padding-left:10; padding-bottom:0; padding-top:0; padding-right:10; } n Using a data collection as a dataProvider Each of the navigator bar containers has a dataProvider property that you can set either to a collection of data or to a ViewStack by referencing its id. The MX navigator bar containers can accept an Array or ArrayCollection, while the Spark ButtonBar can accept an ArrayList or ArrayCollection, but not an Array. When using a data collection as the navigator bar’s dataProvider, the navigator bar generates one interactive component for each of the dataProvider object’s data items. The application in Listing 16.4 generates a Spark ButtonBar using a dataProvider set from an ArrayList of complex objects. Because the Array contains three data items, the user sees three Button objects. LISTING 16.4 A LinkBar with items generated from an ArrayCollection
  16. Part II: Designing Flex Applications LISTING 16.4 (continued) { var buttonURL:String = buttonData.getItemAt(event.newIndex).url; var request:URLRequest = new URLRequest(buttonURL); navigateToURL(request); } ]]> Adobe http://www.adobe.com Google http://www.google.com Microsoft http://www.microsoft.com On the Web The code in Listing 16.4 is available in the Web site files as NavBarWithArrayData.mxml in the chapter16 project. n Note In the preceding code, the tags are declared separately and then bound to the ButtonBar object’s dataProvider. n Note The label and url property names are arbitrary and not predefined in the Object class, but the fx prefix is required because they’re declared within the tag set. The value of the label property is used in the labels of the navigator bar container’s generated controls because the container’s labelField prop- erty defaults to label. You can use any other named object property for this purpose by setting the labelField to the property you want to use. n 486
  17. Chapter 16: Managing Application Navigation Handling navigator bar events When a navigator bar’s dataProvider is set as a data collection, it doesn’t automatically do any- thing when the user clicks one of its controls. Instead, you handle the navigator bar’s itemClick event for MX controls, and the change event for the Spark ButtonBar, by executing some ActionScript code. The itemClick event generates an event object typed as mx.events.ItemClickEvent. This object has an item property that references the underlying data of the interactive component that was clicked. Within an event handler function, the expression event.item returns the underly- ing data, and from that point you can reference the selected object’s data properties. The change event generates an event object typed as spark.events.IndexChangeEvent. The object has properties named newIndex and oldIndex that tell you which object has been selected by the user (based on its index position in the data collection) and which object was selected before the event. The application in Listing 16.4 handles the change event of a Spark ButtonBar control and responds by navigating to the selected URL. Using a ViewStack as a dataProvider When you pass a ViewStack to a navigator bar as its dataProvider, the navigator bar gener- ates one interactive control for each of the ViewStack container’s nested views. Each nested con- tainer’s label property is passed to each generated Button, LinkButton, or Tab for display. It also automatically causes its bound ViewStack to navigate to the related view when a control in the bar is clicked. You set a ViewStack as a dataProvider with a binding expression: The application in Listing 16.5 uses a ToggleButtonBar that generates one toggle button for each nested container of a ViewStack. LISTING 16.5 An application using a navigator bar container continued 487
  18. Part II: Designing Flex Applications LISTING 16.5 (continued) On the Web The code in Listing 16.5 is available in the Web site files as BookStoreNavBar.mxml in the chapter16 project. n Figure 16.6 shows the resulting application, with generated toggle button controls to handle navi- gation to each nested container. Note The Spark ButtonBar component’s primary advantage over the MX navigation toolbars is that it supports cus- tom skins using the new Spark skinning architecture. It also differs from the MX ButtonBar in that it toggles buttons automatically as navigation occurs, staying in sync with its bound ViewStack. In this behavior it’s clos- est in functionality to the MX ToggleButtonBar. n Managing navigator bar presentation Each of the MX navigator bar containers has a direction property that can be used to lay out the container vertically. For example, this LinkBar stacks its generated LinkButton controls vertically: The application in Listing 16.6 uses a vertical LinkBar wrapped in an HBox container. Binding expressions are used to match the component’s width and height properties as needed. LISTING 16.6 An application using a vertical navigator bar container
  19. Chapter 16: Managing Application Navigation xmlns:mx=”library://ns.adobe.com/flex/mx” xmlns:views=”views.*”> FIGURE 16.6 An application using a navigator bar container 489
  20. Part II: Designing Flex Applications On the Web The code in Listing 16.6 is available in the Web site files as BookStoreVerticalNav.mxml in the chapter16 project. n Figure 16.7 shows the resulting application, with a vertical LinkBar displaying stacked LinkButton controls. FIGURE 16.7 An application using a vertical navigator bar container The Spark ButtonBar component’s direction property takes values of ltr and rtl, which controls the order of button creation (left-to-right or right-to-left). Its layout property is like the same property as implemented in the Spark Application, Panel and List components: it accepts an instance of one of the layout classes such as VerticalLayout, HorizontalLayout, or TileLayout. The application in Listing 16.7 displays a Spark ButtonBar with its buttons stacked vertically. LISTING 16.7 An application using a vertical Spark ButtonBar component
Đồng bộ tài khoản