Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (8.09 MB, 764 trang )
Solution
Wrap a Group or DataGroup container in an instance of spark.components.Scroller and
define the dimensions and clipAndEnableScrolling property of the container, or assign
a container as the viewport property of a spark.components.ScrollBar instance.
Discussion
Unlike MX containers, which support scrolling internally, the separation of responsibilities within the Spark architecture provides more lightweight containers and affords
more control over delegating tasks. Within the new Spark paradigm, you can assign
specific controls that handle navigating within a container. The spark.components.
supportClasses.GroupBase class, which both DataGroup and Group extend, is an implementation of the IViewport interface. By default, the clipAndEnableScrolling property
of a GroupBase-based container is set to false and the container renders child elements
outside of any specified bounds. Setting the clipAndEnableScrolling property to true
and wrapping the IViewport instance in a Scroller component renders child elements
within a defined area and updates the read-only contentWidth and contentHeight properties of the container to the specified dimensions.
To enable scrolling for an IViewport, the container can be wrapped in a Scroller
instance with the declared child container attributed as the viewport property value:
Lorem ipsum dolor sit amet consectetur adipisicing elit.
clipAndEnableScrolling="true"
itemRenderer="spark.skins.spark.DefaultItemRenderer">
Any data elements that are rendered outside of the viewport bounds of a container
explicitly set using the width and height properties are displayed based on the scrolling
properties of the s:Scroller component. Based on the positions of the child elements
within the container viewport, a VScrollBar control and a HScrollBar control are added
44 | Chapter 2: Containers
www.it-ebooks.info
to the display. The scroll bars are positioned at the viewport’s width and height property
values, unless you specify custom values for the Scroller instance’s width and height
properties.
Containers that support skinning, such as BorderContainer, SkinnableContainer, and
SkinnableDataContainer, do not implement the IViewport interface. However, the content layer to which child elements are added for each skinnable container is attributed
as an IViewport implementation. As such, you have a couple of options for enabling
scrolling of child content in a skinnable container.
The skin part that serves as the content layer for a BorderContainer and a Skinnable
Container is the contentGroup. When children are declared for a skinnable container
directly in MXML markup, the child elements are added and laid out within the content
layer. One way to enable scrolling of the content is to declare an IViewport implementation wrapped in a Scroller component as the only child of the skinnable container,
as in the following example:
clipAndEnableScrolling="true" />
The Scroller-wrapped Group declared as the only child for the BorderContainer is added
as the only child within the contentGroup for the container. Scrolling is not applied to
the contentGroup layer specifically, but because its only child element is a Group container wrapped in a Scroller whose dimensions are updated to equal the dimensions
of the skinnable container, it appears as if the content for the BorderContainer is made
scrollable.
Another approach to providing scrolling for the content of a skinnable container is to
apply a custom skin to the container that wraps its content-layer skin part in a
Scroller. This is a custom skin for a SkinnableDataContainer:
xmlns:s="library://ns.adobe.com/flex/spark"
name="CustomScrollableSkin">
[HostComponent("spark.components.SkinnableDataContainer")]
2.7 Enable Scrolling in a Container | 45
www.it-ebooks.info
]]>
left="2" right="2" top="2" bottom="2">
left="0" right="0" top="0" bottom="0"
minWidth="0" minHeight="0" />
The CustomScrollableSkin fulfills a contract to serve as a skin to a Skinnable
DataContainer by declaring the [HostComponent] metadata and required states. Also
declared is the required skin part, dataGroup, which is the content layer for item
renderers and is wrapped in a s:Scroller component to enable scrolling within the
container.
The custom skin is supplied to the skinnable container as a qualified class name
attributed to the skinClass property, as in the following example:
Lorem ipsum dolor sit amet consectetur adipisicing elit.
itemRenderer="spark.skins.spark.DefaultItemRenderer"
skinClass="com.oreilly.f4cb.CustomScrollableSkin">
46 | Chapter 2: Containers
www.it-ebooks.info
The ability to use a Scroller to enable scrolling of content within containers is a major
convenience. The skin layout of a Scroller component is a private implementation,
however, and the skin parts for the scroll bars are considered read-only. To have more
control over the layout and the relationship between a viewport and scroll bars, add a
ScrollBar-based control to the display list directly and assign an instance of a target
container as the viewport property value:
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
clipAndEnableScrolling="true"
itemRenderer="spark.skins.spark.DefaultItemRenderer">
In this example, a DataGroup is attributed as the IViewport implementation instance of
a s:VScrollBar control. The thumb size of the scroll bar is based on the height of the
scroll bar and the contentHeight value of the target container. As the scroll position
changes on the scroll bar, the verticalScrollPosition value is passed down to the
IViewport implementation and handed to the layout delegate for the container.
While wrapping a container with a Scroller internally detects the need for scroll bars
based on the content of the container and dimensions of its viewport, with this
approach you have less control over the layout with relation to the target viewport.
Targeting a container using scroll bars declared directly on the display list allows more
control over the layout, but its visibility is not inherently set based on the content
Width and contentHeight of a viewport. The visibility of a scroll bar control can, however, be determined based on the container’s dimensions and its viewport counterpart
2.7 Enable Scrolling in a Container | 47
www.it-ebooks.info
value, as in the following example for updating the visibility of a s:VScrollBar
control:
visible="{group.height < group.contentHeight}" />
When the clipAndEnableScrolling property of an IViewport implementation is set to
true, the read-only contentWidth and contentHeight properties are set based on the
bounds of the container’s display list. By comparing the defined height property of the
viewport with the contentHeight, the visibility and necessity of the VScrollBar control
in this example can be determined.
See Also
Recipe 3.13
2.8 Scale Children of a Container
Problem
You want to resize, scale, and lay out the child elements of a container based on the
dimensions of the container.
Solution
Use the resizeMode property of a GroupBase-based container.
Discussion
Layout delegates applied to Group and DataGroup containers have properties that modify
the layout and size of child elements directly or through transformations. Additionally,
the layout of children can be modified based on the resizeMode property value of
GroupBase-based containers that take the size of the container into consideration. The
default value of the resizeMode property is noScale, which specifies that the container
resizes itself and children are subsequently resized based on the properties of the layout
delegate. The child content of a container can be scaled uniformly by setting the
resizeMode property value to scale, which bases the layout of its children on the measured size of the container.
The following example demonstrates switching between the two resize modes within
a Group container:
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
import mx.events.SliderEvent;
48 | Chapter 2: Containers
www.it-ebooks.info
import spark.components.ResizeMode;
private function toggleResizeMode():void
{
group.resizeMode = ( group.resizeMode == ResizeMode.NO_SCALE )
? group.resizeMode = ResizeMode.SCALE
: group.resizeMode = ResizeMode.NO_SCALE;
}
]]>
width="{slider.value}" height="{slider.value}"
resizeMode="{ResizeMode.NO_SCALE}">
width="120"
minimum="100" maximum="300"
value="300"
liveDragging="true" />
As the value of the s:HSlider control changes, the dimensions of the container are
reflected through binding. The resizeMode is changed when a click event is received
from the s:Button control, swapping between the scale and noScale modes enumerated
in the ResizeMode class.
The TileLayout delegate applied to the Group container has an orientation property
value specifying that children should be laid out in columns based on the dimensions
2.8 Scale Children of a Container | 49
www.it-ebooks.info