Beispiel #1
0
 internal abstract void Layout(int positionOrigin, IntSize viewportSize, ref IntVector offset);
Beispiel #2
0
 private void OffsetChildren(IntVector delta)
 {
     OffsetChildrenHorizontal(-delta.X);
     OffsetChildrenVertical(-delta.Y);
 }
Beispiel #3
0
        public override void OnLayoutChildren(Recycler recycler, State state)
        {
            var adapterChangeType = _adapterChangeType;

            if (state.IsPreLayout)
            {
                adapterChangeType = default(AdapterChangeType);
            }

            // adapter updates
            if (!state.IsPreLayout)
            {
                while (_deferredLayout.Count > 0)
                {
                    _deferredLayout.Dequeue()(recycler, state);
                }
            }

            // get visible items
            var positions = _virtualLayout.GetPositions(
                positionOrigin: _positionOrigin,
                itemCount: state.ItemCount,
                viewport: Viewport
                ).ToRange();

            // disappearing
            var disappearing = _viewByAdaptorPosition.Keys.Except(positions).ToList();

            // defer cleanup of displaced items and lay them out off-screen so they animate off-screen
            if (adapterChangeType == AdapterChangeType.Added)
            {
                positions = positions.Concat(disappearing).OrderBy(o => o).ToArray();
                disappearing.Clear();
            }

            // recycle
            foreach (var position in disappearing)
            {
                var view = _viewByAdaptorPosition[position];

                // remove
                _viewByAdaptorPosition.Remove(position);

                // scrap
                new DecoratedView(this, view).DetachAndScrap(recycler);
            }

            // TODO: Generalize
            if (adapterChangeType == AdapterChangeType.Removed && _positionOrigin == state.ItemCount - 1)
            {
                var vlayout = _virtualLayout.LayoutItem(_positionOrigin, _positionOrigin);
                _locationOffset = new IntVector(vlayout.Width - Width, _locationOffset.Y);
            }

            _visibleAdapterPosition.Clear();
            var nextLocationOffset = new IntPoint(int.MaxValue, int.MaxValue);
            var nextPositionOrigin = int.MaxValue;

            foreach (var position in positions)
            {
                // attach
                AndroidView view;
                if (!_viewByAdaptorPosition.TryGetValue(position, out view))
                {
                    AddView(_viewByAdaptorPosition[position] = view = recycler.GetViewForPosition(position));
                }

                // layout
                var decoratedView  = new DecoratedView(this, view);
                var layout         = _virtualLayout.LayoutItem(_positionOrigin, position);
                var physicalLayout = layout - _locationOffset;
                decoratedView.Layout(physicalLayout);

                var isVisible = Viewport.IntersectsWith(layout);
                if (isVisible)
                {
                    _visibleAdapterPosition.Add(position);
                }

                // update offsets
                if (isVisible && position < nextPositionOrigin)
                {
                    nextLocationOffset = layout.Location;
                    nextPositionOrigin = position;
                }
            }

            // update origin
            if (nextPositionOrigin != int.MaxValue)
            {
                _positionOrigin  = nextPositionOrigin;
                _locationOffset -= (IntVector)nextLocationOffset;
            }

            // scrapped views not re-attached must be recycled (why isn't this done by Android, I dunno)
            foreach (var viewHolder in recycler.ScrapList.ToArray())
            {
                recycler.RecycleView(viewHolder.ItemView);
            }
        }