Какова цель xxScrollPosition в LayoutBase для списка? - PullRequest
1 голос
/ 01 сентября 2010

При написании пользовательского макета для списка, какие соображения необходимо учитывать для использования свойств horizontalScrollPosition / verticalScrollPosition в самом классе LayoutBase (в отличие от соответствующих свойств в layoutTarget)

Глядя наHorizontalLayout класс в качестве примера, он всегда ссылается и обновляет layoutTarget.horizontalScrollPosition.Горизонтальная ли прокрутка горизонтальной позиции класса LayoutBase когда-либо использовалась / использовалась?

УТОЧНЕНИЕ: Что я действительно спрашиваю здесь: какова связь между свойством в экземпляре макета и свойствомэкземпляр layoutTarget, и когда каждый из них должен использоваться?

Ответы [ 2 ]

0 голосов
/ 02 сентября 2010

layoutTarget

/**
 *  @private
 *  Work-around the Player globalToLocal and scrollRect changing before
 *  a frame is updated. 
 */
private function globalToLocal(x:Number, y:Number):Point
{
    var layoutTarget:GroupBase = target;
    var parent:DisplayObject = layoutTarget.parent;
    var local:Point = parent.globalToLocal(new Point(x, y));
    local.x -= layoutTarget.x;
    local.y -= layoutTarget.y;

    var scrollRect:Rectangle = getScrollRect();
    if (scrollRect)
    {
        local.x += scrollRect.x;
        local.y += scrollRect.y;
    }
    return local;
}

и это тоже

/**
 *  Calculates how much to scroll for the specified <code>dropLocation</code>
 *  during a drag and drop gesture.
 *
 *  Called by the <code>showDropIndicator()</code> method to calculate the scroll 
 *  during drag-scrolling.
 *
 *  @param context A valid DropLocation object previously obtained
 *  by calling the <code>calculateDropLocation()</code> method.
 *
 *  @param elapsedTime The duration, in milliseconds, since the drag scrolling start.
 *
 *  @return How much to drag scroll, or null if drag-scrolling is not needed.
 *
 *  @see spark.layouts.supportClasses.DropLocation 
 *  @see #calculateDropIndex()
 *  @see #calculateDropIndicatorBounds()
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
protected function calculateDragScrollDelta(dropLocation:DropLocation, elapsedTime:Number):Point
{
    var layoutTarget:GroupBase = target;
    if (layoutTarget.numElements == 0)
        return null;

    var scrollRect:Rectangle = getScrollRect();
    if (!scrollRect)
        return null;

    // Make sure that the drag-scrolling regions don't overlap 
    var x:Number = dropLocation.dropPoint.x;
    var y:Number = dropLocation.dropPoint.y;

    var horizontalRegionSize:Number = Math.min(dragScrollRegionSizeHorizontal, layoutTarget.width/2);
    var verticalRegionSize:Number = Math.min(dragScrollRegionSizeVertical, layoutTarget.height/2);
    // Return early if the mouse is outside of the drag-scroll region.
    if (scrollRect.left + horizontalRegionSize < x && x < scrollRect.right - horizontalRegionSize &&
        scrollRect.top + verticalRegionSize < y && y < scrollRect.bottom - verticalRegionSize )
        return null;

    if (elapsedTime < dragScrollInitialDelay)
        return new Point(); // Return zero point to continue firing events, but not actually scroll.
    elapsedTime -= dragScrollInitialDelay;

    // Speedup based on time elapsed
    var timeSpeedUp:Number = Math.min(elapsedTime, 2000) / 2000;
    timeSpeedUp *= 3;
    timeSpeedUp += 1;
    timeSpeedUp *= timeSpeedUp * dragScrollSpeed * dragScrollInterval / 50;

    var minDeltaX:Number = -scrollRect.left;
    var minDeltaY:Number = -scrollRect.top;
    var maxDeltaY:Number = target.contentHeight - scrollRect.bottom;
    var maxDeltaX:Number = target.contentWidth - scrollRect.right;

    var deltaX:Number = 0;
    var deltaY:Number = 0;

    if (minDeltaX != 0 && x - scrollRect.left < horizontalRegionSize)
    {
        // Scroll left
        deltaX = 1 - (x - scrollRect.left) / horizontalRegionSize;
        deltaX *=  deltaX * timeSpeedUp;
        deltaX = -Math.round(deltaX) - 1;
    }
    else  if (maxDeltaX != 0 && scrollRect.right - x < horizontalRegionSize)
    {
        // Scroll right
        deltaX = 1 - (scrollRect.right - x) / horizontalRegionSize;
        deltaX *= deltaX * timeSpeedUp;
        deltaX = Math.round(deltaX) + 1;
    }

    if (minDeltaY != 0 && y - scrollRect.top < verticalRegionSize)
    {
        // Scroll up
        deltaY = 1 - (y - scrollRect.top) / verticalRegionSize;
        deltaY *=  deltaY * timeSpeedUp;
        deltaY = -Math.round(deltaY) - 1;
    }
    else  if (maxDeltaY != 0 && scrollRect.bottom - y < verticalRegionSize)
    {
        // Scroll down
        deltaY = 1 - (scrollRect.bottom - y) / verticalRegionSize;
        deltaY *= deltaY * timeSpeedUp;
        deltaY = Math.round(deltaY) + 1;
    }

    deltaX = Math.max(minDeltaX, Math.min(maxDeltaX, deltaX));
    deltaY = Math.max(minDeltaY, Math.min(maxDeltaY, deltaY));

    if (deltaX == 0 && deltaY == 0)
        return null;
    return new Point(deltaX, deltaY);
}

HorizontalScrollPosition

/**
 *  @private
 *  Updates the scroll position and dispatches a DragEvent.
 */
private function dragScroll(event:TimerEvent):void
{
    // Scroll the target
    horizontalScrollPosition += _dragScrollDelta.x;
    verticalScrollPosition += _dragScrollDelta.y;

    // Validate target before dispatching the event
    target.validateNow();

    // Re-dispatch the event so that the drag initiator handles it as if
    // the DragProxy is dispatching in response to user input.
    // Always switch over to DRAG_OVER, don't re-dispatch DRAG_ENTER
    var dragEvent:DragEvent = new DragEvent(DragEvent.DRAG_OVER,
                                            _dragScrollEvent.bubbles,
                                            _dragScrollEvent.cancelable, 
                                            _dragScrollEvent.dragInitiator, 
                                            _dragScrollEvent.dragSource, 
                                            _dragScrollEvent.action, 
                                            _dragScrollEvent.ctrlKey, 
                                            _dragScrollEvent.altKey, 
                                            _dragScrollEvent.shiftKey);

    dragEvent.draggedItem = _dragScrollEvent.draggedItem;
    dragEvent.localX = _dragScrollEvent.localX;
    dragEvent.localY = _dragScrollEvent.localY;
    dragEvent.relatedObject = _dragScrollEvent.relatedObject;
    _dragScrollEvent.target.dispatchEvent(dragEvent);
}

и это тоже:

public function set horizontalScrollPosition(value:Number):void 
{
    if (value == _horizontalScrollPosition) 
        return;

    _horizontalScrollPosition = value;
    scrollPositionChanged();
}

давайте посмотрим тоже scrollPositionChanged();

 /**
 *  Called when the <code>verticalScrollPosition</code> or 
 *  <code>horizontalScrollPosition</code> properties change.
 *
 *  <p>The default implementation updates the target's <code>scrollRect</code> property by
 *  calling <code>updateScrollRect()</code>.
 *  Subclasses can override this method to compute other values that are
 *  based on the current <code>scrollPosition</code> or <code>scrollRect</code>.</p>
 *
 *  @see #updateScrollRect()
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */  
protected function scrollPositionChanged():void
{
    var g:GroupBase = target;
    if (!g)
        return;

    updateScrollRect(g.width, g.height);
}

также давайте посмотрим на эту часть кода

/**
*  Computes the <code>verticalScrollPosition</code> and 
*  <code>horizontalScrollPosition</code> deltas needed to 
*  scroll the element at the specified index into view.
* 
*  <p>This method attempts to minimize the change to <code>verticalScrollPosition</code>
*  and <code>horizontalScrollPosition</code>.</p>
* 
*  <p>If <code>clipAndEnableScrolling</code> is <code>true</code> 
*  and the element at the specified index is not
*  entirely visible relative to the target's scroll rectangle, then 
*  return the delta to be added to <code>horizontalScrollPosition</code> and
*  <code>verticalScrollPosition</code> that scrolls the element completely 
*  within the scroll rectangle's bounds.</p>
* 
*  @param index The index of the element to be scrolled into view.
*
*  @return A Point that contains offsets to horizontalScrollPosition 
*      and verticalScrollPosition that will scroll the specified
*      element into view, or null if no change is needed. 
*      If the specified element is partially visible and larger than the
*      scroll rectangle, meaning it is already the only element visible, then
*      return null.
*      If the specified index is invalid, or target is null, then
*      return null.
*      If the element at the specified index is null or includeInLayout
*      false, then return null.
* 
*  @see #clipAndEnableScrolling
*  @see #verticalScrollPosition
*  @see #horizontalScrollPosition
*  @see #udpdateScrollRect()
*  
*  @langversion 3.0
*  @playerversion Flash 10
*  @playerversion AIR 1.5
*  @productversion Flex 4
*/
public function getScrollPositionDeltaToElement(index:int):Point

и так, что если мы поговоримо разнице этих параметров в LayoutBase и HorizontalLayout?

в HL он использовался в private function updateDisplayListVirtual():void, но в LayoutBase такой функции нет, потому что LayoutBase просто базовый класс, как есть, но у него есть другой, который называетсякак public function updateDisplayList(width:Number, height:Number):void, но оно пустое.

Итак, если мы попытаемся понять, что делают все эти функции, imho, HL просто расширяет стандарт updateDisplayList на две функции, одна такая же, а другая виртуальная.

Зачем HL нужен виртуальный?Давайте посмотрим:

override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
    super.updateDisplayList(unscaledWidth, unscaledHeight);

    var layoutTarget:GroupBase = target; 
    if (!layoutTarget)
        return;

    if ((layoutTarget.numElements == 0) || (unscaledWidth == 0) || (unscaledHeight == 0))
    {
        setColumnCount(0);
        setIndexInView(-1, -1);
        if (layoutTarget.numElements == 0)
            layoutTarget.setContentSize(paddingLeft + paddingRight, paddingTop + paddingBottom);
        return;         
    }

    if (useVirtualLayout) 
        updateDisplayListVirtual();
    else
        updateDisplayListReal();
}

так что все вещи useVirtualLayout , но это из LayoutBase и позволяет увидеть:

 /**
 *  A container can hold any number of children. 
 *  However, each child requires an instance of an item renderer. 
 *  If the container has many children, you might notice performance degradation 
 *  as you add more children to the container. 
 *
 *  <p>Instead of creating an item renderer for each child, 
 *  you can configure the container to use a virtual layout. 
 *  With virtual layout, the container reuses item renderers so that it only creates 
 *  item renderers for the currently visible children of the container. 
 *  As a child is moved off the screen, possible by scrolling the container, 
 *  a new child being scrolled onto the screen can reuse its item renderer. </p>
 *  
 *  <p>To configure a container to use virtual layout, set the <code>useVirtualLayout</code> property 
 *  to <code>true</code> for the layout associated with the container. 
 *  Only the DataGroup or SkinnableDataContainer with the VerticalLayout, 
 *  HorizontalLayout, and TileLayout supports virtual layout. 
 *  Layout subclasses that do not support virtualization must prevent changing
 *  this property.</p>
 *
 *  <p><b>Note: </b>The BasicLayout class throws a run-time error if you set 
 *  <code>useVirtualLayout</code> to <code>true</code>.</p>
 * 
 *  <p>When <code>true</code>, layouts that support virtualization must use 
 *  the <code>target.getVirtualElementAt()</code> method, 
 *  rather than <code>getElementAt()</code>, and must only get the 
 *  elements they anticipate will be visible given the value of <code>getScrollRect()</code>.</p>
 * 
 *  <p>When <code>true</code>, the layout class must be able to compute
 *  the indices of the layout elements that overlap the <code>scrollRect</code> in its 
 *  <code>updateDisplayList()</code> method based exclusively on cached information, not
 *  by getting layout elements and examining their bounds.</p>
 * 
 *  <p>Typically virtual layouts update their cached information 
 *  in the <code>updateDisplayList()</code> method,
 *  based on the sizes and locations computed for the elements in view.</p>
 * 
 *  <p>Similarly, in the <code>measure()</code> method, virtual layouts should update the target's 
 *  measured size properties based on the <code>typicalLayoutElement</code> and other
 *  cached layout information, not by measuring elements.</p>
 * 
 *  <p>Containers cooperate with layouts that have <code>useVirtualLayout</code> = <code>true</code> by 
 *  recycling item renderers that were previously constructed, but are no longer in use.
 *  An item is considered to be no longer in use if its index is not
 *  within the range of <code>getVirtualElementAt()</code> indices requested during
 *  the container's most recent <code>updateDisplayList()</code> invocation.</p>
 *
 *  @default false
 * 
 *  @see #getScrollRect
 *  @see #typicalLayoutElement
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */

так что это ваш ответ, я думаю,Также я думаю, что люди, которые написали эту систему Spark, объяснят более широко, и я только с небольшим удовольствием помогу вам получить правильные ответы.

С уважением
Евгений

0 голосов
/ 01 сентября 2010

Используется ли горизонтальная ссылка на класс LayoutBase для ссылки / используется ли она когда-либо?

да, это можно использовать.

пожалуйста, смотрите! в коде найдите horizontalScrollPosition, по крайней мере, 3 функции используют этот параметр.

Будет лучше, если вы скажете, что именно вы хотите с ним делать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...