示例#1
0
        /// <summary>
        /// Realize indexed item.
        /// </summary>
        /// <param name="index"> Index position of realizing item </param>
        internal virtual RecyclerViewItem RealizeItem(int index)
        {
            object context = InternalItemSource.GetItem(index);

            // Check DataTemplate is Same!
            if (ItemTemplate is DataTemplateSelector)
            {
                // Need to implements for caching of selector!
            }
            else
            {
                // pop item
                RecyclerViewItem item = PopRecycleCache(ItemTemplate);
                if (item != null)
                {
                    DecorateItem(item, index, context);
                    return(item);
                }
            }

            object content = DataTemplateExtensions.CreateContent(ItemTemplate, context, (BindableObject)this) ?? throw new Exception("Template return null object.");

            if (content is RecyclerViewItem)
            {
                RecyclerViewItem item = (RecyclerViewItem)content;
                ContentContainer.Add(item);
                DecorateItem(item, index, context);
                return(item);
            }
            else
            {
                throw new Exception("Template content must be type of ViewItem");
            }
        }
示例#2
0
        protected virtual void MeasureChild(RecyclerView parent, RecyclerViewItem child)
        {
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }
            if (child == null)
            {
                throw new ArgumentNullException(nameof(child));
            }

            if (child.Layout == null)
            {
                return;
            }

            //FIXME: This measure can be restricted size of child to be less than parent size.
            // but our parent can be not calculated yet, also some child can be bigger than it's parent size,
            // so we use implicit value 9999 as restricted specification.
            MeasureSpecification childWidthMeasureSpec = LayoutGroup.GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(9999), MeasureSpecification.ModeType.Exactly),
                new LayoutLength(0),
                new LayoutLength(child.WidthSpecification));

            MeasureSpecification childHeightMeasureSpec = LayoutGroup.GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(9999), MeasureSpecification.ModeType.Exactly),
                new LayoutLength(0),
                new LayoutLength(child.HeightSpecification));

            child.Layout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
示例#3
0
        protected virtual void MeasureChild(RecyclerView parent, RecyclerViewItem child)
        {
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }
            if (child == null)
            {
                throw new ArgumentNullException(nameof(child));
            }

            if (child.Layout == null)
            {
                return;
            }

            //FIXME: This measure can be restricted size of child to be less than parent size.
            // but in some multiple-line TextLabel can be long enough to over the it's parent size.

            MeasureSpecification childWidthMeasureSpec = LayoutGroup.GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(parent.Size.Width - parent.Padding.Start - parent.Padding.End - child.Margin.Start - child.Margin.End), MeasureSpecification.ModeType.Exactly),
                new LayoutLength(0),
                new LayoutLength(child.WidthSpecification));

            MeasureSpecification childHeightMeasureSpec = LayoutGroup.GetChildMeasureSpecification(
                new MeasureSpecification(new LayoutLength(parent.Size.Height - parent.Padding.Top - parent.Padding.Bottom - child.Margin.Top - child.Margin.Bottom), MeasureSpecification.ModeType.Exactly),
                new LayoutLength(0),
                new LayoutLength(child.HeightSpecification));

            child.Layout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
示例#4
0
 private void DecorateItem(RecyclerViewItem item, int index, object context)
 {
     item.Index           = index;
     item.ParentItemsView = this;
     item.Template        = (ItemTemplate as DataTemplateSelector)?.SelectDataTemplate(InternalItemSource.GetItem(index), this) ?? ItemTemplate;
     item.BindingContext  = context;
     item.Relayout       += OnItemRelayout;
 }
示例#5
0
 protected virtual RecyclerViewItem PopRecycleCache(DataTemplate Template)
 {
     for (int i = 0; i < RecycleCache.Count; i++)
     {
         RecyclerViewItem item = RecycleCache[i];
         if (item.Template == Template)
         {
             RecycleCache.Remove(item);
             item.Show();
             return(item);
         }
     }
     return(null);
 }
示例#6
0
        public override void NotifyItemSizeChanged(RecyclerViewItem item)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            if (!IsInitialized ||
                (colView.SizingStrategy == ItemSizingStrategy.MeasureFirst &&
                 item.Index != 0) ||
                (item.Index < 0))
            {
                return;
            }

            float PrevSize, CurrentSize;

            if (item.Index == (colView.InternalItemSource.Count - 1))
            {
                PrevSize = ScrollContentSize - ItemPosition[item.Index];
            }
            else
            {
                PrevSize = ItemPosition[item.Index + 1] - ItemPosition[item.Index];
            }

            CurrentSize = (IsHorizontal ? item.Size.Width : item.Size.Height);

            if (CurrentSize != PrevSize)
            {
                if (colView.SizingStrategy == ItemSizingStrategy.MeasureAll)
                {
                    ItemSize[item.Index] = CurrentSize;
                }
                else
                {
                    StepCandidate = CurrentSize;
                }
            }
            if (ItemSizeChanged == -1)
            {
                ItemSizeChanged = item.Index;
            }
            else
            {
                ItemSizeChanged = Math.Min(ItemSizeChanged, item.Index);
            }

            //ScrollContentSize += Diff; UpdateOnce?
        }
示例#7
0
        public override View RequestNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
        {
            if (currentFocusedView == null)
            {
                throw new ArgumentNullException(nameof(currentFocusedView));
            }

            View nextFocusedView = null;
            int  targetSibling   = -1;

            switch (direction)
            {
            case View.FocusDirection.Left:
            {
                targetSibling = IsHorizontal ? currentFocusedView.SiblingOrder - 1 : targetSibling;
                break;
            }

            case View.FocusDirection.Right:
            {
                targetSibling = IsHorizontal ? currentFocusedView.SiblingOrder + 1 : targetSibling;
                break;
            }

            case View.FocusDirection.Up:
            {
                targetSibling = IsHorizontal ? targetSibling : currentFocusedView.SiblingOrder - 1;
                break;
            }

            case View.FocusDirection.Down:
            {
                targetSibling = IsHorizontal ? targetSibling : currentFocusedView.SiblingOrder + 1;
                break;
            }
            }

            if (targetSibling > -1 && targetSibling < Container.Children.Count)
            {
                RecyclerViewItem candidate = Container.Children[targetSibling] as RecyclerViewItem;
                if (candidate.Index >= 0 && candidate.Index < colView.InternalItemSource.Count)
                {
                    nextFocusedView = candidate;
                }
            }

            return(nextFocusedView);
        }
示例#8
0
 protected virtual bool PushRecycleCache(RecyclerViewItem item)
 {
     if (item == null)
     {
         throw new ArgumentNullException(nameof(item));
     }
     if (RecycleCache.Count >= CacheMax)
     {
         return(false);
     }
     if (item.Template == null)
     {
         return(false);
     }
     item.Hide();
     item.Index = -1;
     RecycleCache.Add(item);
     return(true);
 }
示例#9
0
        /// <summary>
        /// Unrealize indexed item.
        /// </summary>
        /// <param name="item"> Target item for unrealizing </param>
        /// <param name="recycle"> Allow recycle. default is true </param>
        internal virtual void UnrealizeItem(RecyclerViewItem item, bool recycle = true)
        {
            item.Index           = -1;
            item.ParentItemsView = null;
            // Remove BindingContext null set for performance improving.
            //item.BindingContext = null;
            item.IsPressed  = false;
            item.IsSelected = false;
            item.IsEnabled  = true;
            // Remove Update Style on default for performance improving.
            //item.UpdateState();
            item.Relayout -= OnItemRelayout;

            if (!recycle || !PushRecycleCache(item))
            {
                //ContentContainer.Remove(item);
                Utility.Dispose(item);
            }
        }
示例#10
0
        /// <summary>
        /// Unrealize indexed item.
        /// </summary>
        /// <param name="item"> Target item for unrealizing </param>
        /// <param name="recycle"> Allow recycle. default is true </param>
        internal virtual void UnrealizeItem(RecyclerViewItem item, bool recycle = true)
        {
            if (item == null)
            {
                return;
            }
            item.Index           = -1;
            item.ParentItemsView = null;
            item.BindingContext  = null;
            item.IsPressed       = false;
            item.IsSelected      = false;
            item.IsEnabled       = true;
            item.UpdateState();
            item.Relayout -= OnItemRelayout;

            if (!recycle || !PushRecycleCache(item))
            {
                //ContentContainer.Remove(item);
                Utility.Dispose(item);
            }
        }
示例#11
0
 public virtual void NotifyItemSizeChanged(RecyclerViewItem item)
 {
 }
示例#12
0
        public override void Initialize(RecyclerView view)
        {
            colView = view as CollectionView;
            if (colView == null)
            {
                throw new ArgumentException("LinearLayouter only can be applied CollectionView.", nameof(view));
            }
            // 1. Clean Up
            foreach (RecyclerViewItem item in VisibleItems)
            {
                colView.UnrealizeItem(item, false);
            }
            VisibleItems.Clear();
            ItemPosition.Clear();
            ItemSize.Clear();
            groups.Clear();

            FirstVisible = 0;
            LastVisible  = 0;

            IsHorizontal = (colView.ScrollingDirection == ScrollableBase.Direction.Horizontal);

            RecyclerViewItem header = colView?.Header;
            RecyclerViewItem footer = colView?.Footer;
            float            width, height;
            int count = colView.InternalItemSource.Count;

            if (header != null)
            {
                MeasureChild(colView, header);

                width = header.Layout != null?header.Layout.MeasuredWidth.Size.AsRoundedValue() : 0;

                height = header.Layout != null?header.Layout.MeasuredHeight.Size.AsRoundedValue() : 0;

                headerSize = IsHorizontal ? width : height;
                hasHeader  = true;

                colView.UnrealizeItem(header);
            }
            else
            {
                hasHeader = false;
            }

            if (footer != null)
            {
                MeasureChild(colView, footer);

                width = footer.Layout != null?footer.Layout.MeasuredWidth.Size.AsRoundedValue() : 0;

                height = footer.Layout != null?footer.Layout.MeasuredHeight.Size.AsRoundedValue() : 0;

                footerSize   = IsHorizontal ? width : height;
                footer.Index = count - 1;
                hasFooter    = true;

                colView.UnrealizeItem(footer);
            }
            else
            {
                hasFooter = false;
            }

            //No Internal Source exist.
            if (count == (hasHeader ? (hasFooter ? 2 : 1) : 0))
            {
                return;
            }

            int firstIndex = hasHeader ? 1 : 0;

            if (colView.IsGrouped)
            {
                isGrouped = true;

                if (colView.GroupHeaderTemplate != null)
                {
                    while (!colView.InternalItemSource.IsGroupHeader(firstIndex))
                    {
                        firstIndex++;
                    }
                    //must be always true
                    if (colView.InternalItemSource.IsGroupHeader(firstIndex))
                    {
                        RecyclerViewItem groupHeader = colView.RealizeItem(firstIndex);
                        firstIndex++;

                        if (groupHeader == null)
                        {
                            throw new Exception("[" + firstIndex + "] Group Header failed to realize!");
                        }

                        // Need to Set proper height or width on scroll direction.
                        if (groupHeader.Layout == null)
                        {
                            width  = groupHeader.WidthSpecification;
                            height = groupHeader.HeightSpecification;
                        }
                        else
                        {
                            MeasureChild(colView, groupHeader);

                            width  = groupHeader.Layout.MeasuredWidth.Size.AsRoundedValue();
                            height = groupHeader.Layout.MeasuredHeight.Size.AsRoundedValue();
                        }
                        //Console.WriteLine("[NUI] GroupHeader Size {0} :{0}", width, height);
                        // pick the StepCandidate.
                        groupHeaderSize = IsHorizontal ? width : height;
                        colView.UnrealizeItem(groupHeader);
                    }
                }
                else
                {
                    groupHeaderSize = 0F;
                }

                if (colView.GroupFooterTemplate != null)
                {
                    int firstFooter = firstIndex;
                    while (!colView.InternalItemSource.IsGroupFooter(firstFooter))
                    {
                        firstFooter++;
                    }
                    //must be always true
                    if (colView.InternalItemSource.IsGroupFooter(firstFooter))
                    {
                        RecyclerViewItem groupFooter = colView.RealizeItem(firstFooter);

                        if (groupFooter == null)
                        {
                            throw new Exception("[" + firstFooter + "] Group Footer failed to realize!");
                        }
                        // Need to Set proper height or width on scroll direction.
                        if (groupFooter.Layout == null)
                        {
                            width  = groupFooter.WidthSpecification;
                            height = groupFooter.HeightSpecification;
                        }
                        else
                        {
                            MeasureChild(colView, groupFooter);

                            width  = groupFooter.Layout.MeasuredWidth.Size.AsRoundedValue();
                            height = groupFooter.Layout.MeasuredHeight.Size.AsRoundedValue();
                        }
                        // pick the StepCandidate.
                        groupFooterSize = IsHorizontal ? width : height;

                        colView.UnrealizeItem(groupFooter);
                    }
                }
                else
                {
                    groupFooterSize = 0F;
                }
            }
            else
            {
                isGrouped = false;
            }

            bool failed = false;

            //Final Check of FirstIndex
            while (colView.InternalItemSource.IsHeader(firstIndex) ||
                   colView.InternalItemSource.IsGroupHeader(firstIndex) ||
                   colView.InternalItemSource.IsGroupFooter(firstIndex))
            {
                if (colView.InternalItemSource.IsFooter(firstIndex))
                {
                    StepCandidate = 0F;
                    failed        = true;
                    break;
                }
                firstIndex++;
            }

            if (!failed)
            {
                RecyclerViewItem sizeDeligate = colView.RealizeItem(firstIndex);
                if (sizeDeligate == null)
                {
                    // error !
                    throw new Exception("Cannot create content from DatTemplate.");
                }

                sizeDeligate.BindingContext = colView.InternalItemSource.GetItem(firstIndex);

                // Need to Set proper height or width on scroll direction.
                if (sizeDeligate.Layout == null)
                {
                    width  = sizeDeligate.WidthSpecification;
                    height = sizeDeligate.HeightSpecification;
                }
                else
                {
                    MeasureChild(colView, sizeDeligate);

                    width  = sizeDeligate.Layout.MeasuredWidth.Size.AsRoundedValue();
                    height = sizeDeligate.Layout.MeasuredHeight.Size.AsRoundedValue();
                }
                //Console.WriteLine("[NUI] Layout Size {0} :{0}", width, height);
                // pick the StepCandidate.
                StepCandidate = IsHorizontal ? width : height;
                if (StepCandidate == 0)
                {
                    StepCandidate = 1;                     //????
                }
                colView.UnrealizeItem(sizeDeligate);
            }

            float Current = 0.0F;
            IGroupableItemSource source       = colView.InternalItemSource;
            GroupInfo            currentGroup = null;

            for (int i = 0; i < count; i++)
            {
                if (colView.SizingStrategy == ItemSizingStrategy.MeasureAll)
                {
                    if (i == 0 && hasHeader)
                    {
                        ItemSize.Add(headerSize);
                    }
                    else if (i == count - 1 && hasFooter)
                    {
                        ItemSize.Add(footerSize);
                    }
                    else if (source.IsGroupHeader(i))
                    {
                        ItemSize.Add(groupHeaderSize);
                    }
                    else if (source.IsGroupFooter(i))
                    {
                        ItemSize.Add(groupFooterSize);
                    }
                    else
                    {
                        ItemSize.Add(StepCandidate);
                    }
                }
                if (isGrouped)
                {
                    if (i == 0 && hasHeader)
                    {
                        //ItemPosition.Add(Current);
                        Current += headerSize;
                    }
                    else if (i == count - 1 && hasFooter)
                    {
                        //ItemPosition.Add(Current);
                        Current += footerSize;
                    }
                    else
                    {
                        //GroupHeader must always exist in group usage.
                        if (source.IsGroupHeader(i))
                        {
                            currentGroup = new GroupInfo()
                            {
                                GroupParent = source.GetGroupParent(i),
                                //hasHeader = true,
                                //hasFooter = false,
                                StartIndex    = i,
                                Count         = 1,
                                GroupSize     = groupHeaderSize,
                                GroupPosition = Current
                            };
                            currentGroup.ItemPosition.Add(0);
                            groups.Add(currentGroup);
                            Current += groupHeaderSize;
                        }
                        //optional
                        else if (source.IsGroupFooter(i))
                        {
                            //currentGroup.hasFooter = true;
                            currentGroup.Count++;
                            currentGroup.GroupSize += groupFooterSize;
                            currentGroup.ItemPosition.Add(Current - currentGroup.GroupPosition);
                            Current += groupFooterSize;
                        }
                        else
                        {
                            currentGroup.Count++;
                            currentGroup.GroupSize += StepCandidate;
                            currentGroup.ItemPosition.Add(Current - currentGroup.GroupPosition);
                            Current += StepCandidate;
                        }
                    }
                }
                else
                {
                    ItemPosition.Add(Current);

                    if (i == 0 && hasHeader)
                    {
                        Current += headerSize;
                    }
                    else if (i == count - 1 && hasFooter)
                    {
                        Current += footerSize;
                    }
                    else
                    {
                        Current += StepCandidate;
                    }
                }
            }

            ScrollContentSize = Current;
            if (IsHorizontal)
            {
                colView.ContentContainer.SizeWidth = ScrollContentSize;
            }
            else
            {
                colView.ContentContainer.SizeHeight = ScrollContentSize;
            }


            base.Initialize(view);
            //Console.WriteLine("[NUI] Init Done, StepCnadidate{0}, Scroll{1}", StepCandidate, ScrollContentSize);
        }
示例#13
0
        public override void RequestLayout(float scrollPosition, bool force = false)
        {
            // Layouting is only possible after once it initialized.
            if (!IsInitialized)
            {
                return;
            }
            int LastIndex = colView.InternalItemSource.Count - 1;

            if (!force && PrevScrollPosition == Math.Abs(scrollPosition))
            {
                return;
            }
            PrevScrollPosition = Math.Abs(scrollPosition);

            if (ItemSizeChanged >= 0)
            {
                for (int i = ItemSizeChanged; i <= LastIndex; i++)
                {
                    UpdatePosition(i);
                }
                ScrollContentSize = ItemPosition[LastIndex - 1] + GetItemSize(LastIndex);
            }

            int prevFirstVisible = FirstVisible;
            int prevLastVisible  = LastVisible;

            (float X, float Y)visibleArea = (PrevScrollPosition,
                                             PrevScrollPosition + (IsHorizontal ? colView.Size.Width : colView.Size.Height)
                                             );

            // 1. Set First/Last Visible Item Index.
            (int start, int end) = FindVisibleItems(visibleArea);
            FirstVisible         = start;
            LastVisible          = end;

            // 2. Unrealize invisible items.
            List <RecyclerViewItem> unrealizedItems = new List <RecyclerViewItem>();

            foreach (RecyclerViewItem item in VisibleItems)
            {
                if (item.Index < FirstVisible || item.Index > LastVisible)
                {
                    //Console.WriteLine("[NUI] Unrealize{0}!", item.Index);
                    unrealizedItems.Add(item);
                    colView.UnrealizeItem(item);
                }
            }
            VisibleItems.RemoveAll(unrealizedItems.Contains);

            // 3. Realize and placing visible items.
            for (int i = FirstVisible; i <= LastVisible; i++)
            {
                RecyclerViewItem item = null;
                // 4. Get item if visible or realize new.
                if (i >= prevFirstVisible && i <= prevLastVisible)
                {
                    item = GetVisibleItem(i);
                    if (item)
                    {
                        continue;
                    }
                }
                if (item == null)
                {
                    item = colView.RealizeItem(i);
                }

                VisibleItems.Add(item);

                // 5. Placing item.
                float posX = 0F, posY = 0F;
                if (isGrouped)
                {
                    //isHeader?
                    if (colView.Header == item)
                    {
                        posX = 0F;
                        posY = 0F;
                    }
                    else if (colView.Footer == item)
                    {
                        posX = (IsHorizontal ? ScrollContentSize - item.SizeWidth : 0F);
                        posY = (IsHorizontal ? 0F : ScrollContentSize - item.SizeHeight);
                    }
                    else
                    {
                        GroupInfo gInfo = GetGroupInfo(i);
                        posX = (IsHorizontal ? gInfo.GroupPosition + gInfo.ItemPosition[i - gInfo.StartIndex] : 0F);
                        posY = (IsHorizontal ? 0F : gInfo.GroupPosition + gInfo.ItemPosition[i - gInfo.StartIndex]);
                    }
                }
                else
                {
                    posX = (IsHorizontal ? ItemPosition[i] : 0F);
                    posY = (IsHorizontal ? 0F : ItemPosition[i]);
                }

                item.Position = new Position(posX, posY);
                //Console.WriteLine("[NUI] ["+item+"]["+item.Index+"] :: ["+item.Position.X+", "+item.Position.Y+"] ==== \n");
            }
        }
示例#14
0
        public override void Initialize(RecyclerView view)
        {
            colView = view as CollectionView;
            if (colView == null)
            {
                throw new ArgumentException("GridLayouter only can be applied CollectionView.", nameof(view));
            }

            // 1. Clean Up
            foreach (RecyclerViewItem item in VisibleItems)
            {
                colView.UnrealizeItem(item, false);
            }
            VisibleItems.Clear();
            groups.Clear();

            FirstVisible = 0;
            LastVisible  = 0;

            IsHorizontal = (colView.ScrollingDirection == ScrollableBase.Direction.Horizontal);

            RecyclerViewItem header = colView?.Header;
            RecyclerViewItem footer = colView?.Footer;
            float            width, height;
            int count = colView.InternalItemSource.Count;
            int pureCount = count - (header ? 1 : 0) - (footer ? 1 : 0);

            // 2. Get the header / footer and size deligated item and measure the size.
            if (header != null)
            {
                MeasureChild(colView, header);

                width = header.Layout != null?header.Layout.MeasuredWidth.Size.AsRoundedValue() : 0;

                height = header.Layout != null?header.Layout.MeasuredHeight.Size.AsRoundedValue() : 0;

                headerSize = IsHorizontal ? width : height;
                hasHeader  = true;

                colView.UnrealizeItem(header);
            }

            if (footer != null)
            {
                MeasureChild(colView, footer);

                width = footer.Layout != null?footer.Layout.MeasuredWidth.Size.AsRoundedValue() : 0;

                height = footer.Layout != null?footer.Layout.MeasuredHeight.Size.AsRoundedValue() : 0;

                footerSize   = IsHorizontal ? width : height;
                footer.Index = count - 1;
                hasFooter    = true;

                colView.UnrealizeItem(footer);
            }

            int firstIndex = header ? 1 : 0;

            if (colView.IsGrouped)
            {
                isGrouped = true;

                if (colView.GroupHeaderTemplate != null)
                {
                    while (!colView.InternalItemSource.IsGroupHeader(firstIndex))
                    {
                        firstIndex++;
                    }
                    //must be always true
                    if (colView.InternalItemSource.IsGroupHeader(firstIndex))
                    {
                        RecyclerViewItem groupHeader = colView.RealizeItem(firstIndex);
                        firstIndex++;

                        if (groupHeader == null)
                        {
                            throw new Exception("[" + firstIndex + "] Group Header failed to realize!");
                        }

                        // Need to Set proper hieght or width on scroll direciton.
                        if (groupHeader.Layout == null)
                        {
                            width  = groupHeader.WidthSpecification;
                            height = groupHeader.HeightSpecification;
                        }
                        else
                        {
                            MeasureChild(colView, groupHeader);

                            width  = groupHeader.Layout.MeasuredWidth.Size.AsRoundedValue();
                            height = groupHeader.Layout.MeasuredHeight.Size.AsRoundedValue();
                        }
                        //Console.WriteLine("[NUI] GroupHeader Size {0} :{0}", width, height);
                        // pick the StepCandidate.
                        groupHeaderSize = IsHorizontal ? width : height;
                        colView.UnrealizeItem(groupHeader);
                    }
                }
                else
                {
                    groupHeaderSize = 0F;
                }

                if (colView.GroupFooterTemplate != null)
                {
                    int firstFooter = firstIndex;
                    while (!colView.InternalItemSource.IsGroupFooter(firstFooter))
                    {
                        firstFooter++;
                    }
                    //must be always true
                    if (colView.InternalItemSource.IsGroupFooter(firstFooter))
                    {
                        RecyclerViewItem groupFooter = colView.RealizeItem(firstFooter);

                        if (groupFooter == null)
                        {
                            throw new Exception("[" + firstFooter + "] Group Footer failed to realize!");
                        }
                        // Need to Set proper hieght or width on scroll direciton.
                        if (groupFooter.Layout == null)
                        {
                            width  = groupFooter.WidthSpecification;
                            height = groupFooter.HeightSpecification;
                        }
                        else
                        {
                            MeasureChild(colView, groupFooter);

                            width  = groupFooter.Layout.MeasuredWidth.Size.AsRoundedValue();
                            height = groupFooter.Layout.MeasuredHeight.Size.AsRoundedValue();
                        }
                        // pick the StepCandidate.
                        groupFooterSize = IsHorizontal ? width : height;

                        colView.UnrealizeItem(groupFooter);
                    }
                }
                else
                {
                    groupFooterSize = 0F;
                }
            }
            else
            {
                isGrouped = false;
            }

            bool failed = false;

            //Final Check of FirstIndex
            while (colView.InternalItemSource.IsHeader(firstIndex) ||
                   colView.InternalItemSource.IsGroupHeader(firstIndex) ||
                   colView.InternalItemSource.IsGroupFooter(firstIndex))
            {
                if (colView.InternalItemSource.IsFooter(firstIndex))
                {
                    StepCandidate = 0F;
                    failed        = true;
                    break;
                }
                firstIndex++;
            }

            sizeCandidate = new Size2D(0, 0);
            if (!failed)
            {
                // Get Size Deligate. FIXME if group exist index must be changed.
                RecyclerViewItem sizeDeligate = colView.RealizeItem(firstIndex);
                if (sizeDeligate == null)
                {
                    throw new Exception("Cannot create content from DatTemplate.");
                }
                sizeDeligate.BindingContext = colView.InternalItemSource.GetItem(firstIndex);

                // Need to Set proper hieght or width on scroll direciton.
                if (sizeDeligate.Layout == null)
                {
                    width  = sizeDeligate.WidthSpecification;
                    height = sizeDeligate.HeightSpecification;
                }
                else
                {
                    MeasureChild(colView, sizeDeligate);

                    width  = sizeDeligate.Layout.MeasuredWidth.Size.AsRoundedValue();
                    height = sizeDeligate.Layout.MeasuredHeight.Size.AsRoundedValue();
                }
                //Console.WriteLine("[NUI] item Size {0} :{1}", width, height);

                // pick the StepCandidate.
                StepCandidate = IsHorizontal ? width : height;
                spanSize      = IsHorizontal ? Convert.ToInt32(Math.Truncate((double)(colView.Size.Height / height))) :
                                Convert.ToInt32(Math.Truncate((double)(colView.Size.Width / width)));

                sizeCandidate = new Size2D(Convert.ToInt32(width), Convert.ToInt32(height));

                colView.UnrealizeItem(sizeDeligate);
            }

            if (StepCandidate < 1)
            {
                StepCandidate = 1;
            }
            if (spanSize < 1)
            {
                spanSize = 1;
            }

            if (isGrouped)
            {
                float Current = 0.0F;
                IGroupableItemSource source       = colView.InternalItemSource;
                GroupInfo            currentGroup = null;

                for (int i = 0; i < count; i++)
                {
                    if (i == 0 && hasHeader)
                    {
                        Current += headerSize;
                    }
                    else if (i == count - 1 && hasFooter)
                    {
                        Current += footerSize;
                    }
                    else
                    {
                        //GroupHeader must always exist in group usage.
                        if (source.IsGroupHeader(i))
                        {
                            currentGroup = new GroupInfo()
                            {
                                GroupParent   = source.GetGroupParent(i),
                                StartIndex    = i,
                                Count         = 1,
                                GroupSize     = groupHeaderSize,
                                GroupPosition = Current
                            };
                            groups.Add(currentGroup);
                            Current += groupHeaderSize;
                        }
                        //optional
                        else if (source.IsGroupFooter(i))
                        {
                            //currentGroup.hasFooter = true;
                            currentGroup.Count++;
                            currentGroup.GroupSize += groupFooterSize;
                            Current += groupFooterSize;
                        }
                        else
                        {
                            currentGroup.Count++;
                            int index = i - currentGroup.StartIndex - 1; // groupHeader must always exist.
                            if ((index % spanSize) == 0)
                            {
                                currentGroup.GroupSize += StepCandidate;
                                Current += StepCandidate;
                            }
                        }
                    }
                }
                ScrollContentSize = Current;
            }
            else
            {
                // 3. Measure the scroller content size.
                ScrollContentSize = StepCandidate * Convert.ToInt32(Math.Ceiling((double)pureCount / (double)spanSize));
                if (hasHeader)
                {
                    ScrollContentSize += headerSize;
                }
                if (hasFooter)
                {
                    ScrollContentSize += footerSize;
                }
            }

            if (IsHorizontal)
            {
                colView.ContentContainer.SizeWidth = ScrollContentSize;
            }
            else
            {
                colView.ContentContainer.SizeHeight = ScrollContentSize;
            }

            base.Initialize(colView);
            //Console.WriteLine("Init Done, StepCnadidate{0}, spanSize{1}, Scroll{2}", StepCandidate, spanSize, ScrollContentSize);
        }
示例#15
0
 /// <inheritdoc/>
 public override void NotifyItemSizeChanged(RecyclerViewItem item)
 {
     // All Item size need to be same in grid!
     // if you want to change item size, change dataTemplate to re-initing.
     return;
 }
示例#16
0
        /// <summary>
        /// This is called to find out where items are lain out according to current scroll position.
        /// </summary>
        /// <param name="scrollPosition">Scroll position which is calculated by ScrollableBase</param>
        /// <param name="force">boolean force flag to layouting forcely.</param>
        public override void RequestLayout(float scrollPosition, bool force = false)
        {
            // Layouting is only possible after once it intialized.
            if (!IsInitialized)
            {
                return;
            }
            int LastIndex = colView.InternalItemSource.Count;

            if (!force && PrevScrollPosition == Math.Abs(scrollPosition))
            {
                return;
            }
            PrevScrollPosition = Math.Abs(scrollPosition);

            int  prevFirstVisible = FirstVisible;
            int  prevLastVisible  = LastVisible;
            bool IsHorizontal     = (colView.ScrollingDirection == ScrollableBase.Direction.Horizontal);

            (float X, float Y)visibleArea = (PrevScrollPosition,
                                             PrevScrollPosition + (IsHorizontal ? colView.Size.Width : colView.Size.Height)
                                             );

            //Console.WriteLine("[NUI] itemsView [{0},{1}] [{2},{3}]", colView.Size.Width, colView.Size.Height, colView.ContentContainer.Size.Width, colView.ContentContainer.Size.Height);

            // 1. Set First/Last Visible Item Index.
            (int start, int end) = FindVisibleItems(visibleArea);
            FirstVisible         = start;
            LastVisible          = end;

            //Console.WriteLine("[NUI] {0} :visibleArea before [{1},{2}] after [{3},{4}]", scrollPosition, prevFirstVisible, prevLastVisible, FirstVisible, LastVisible);

            // 2. Unrealize invisible items.
            List <RecyclerViewItem> unrealizedItems = new List <RecyclerViewItem>();

            foreach (RecyclerViewItem item in VisibleItems)
            {
                if (item.Index < FirstVisible || item.Index > LastVisible)
                {
                    //Console.WriteLine("[NUI] Unrealize{0}!", item.Index);
                    unrealizedItems.Add(item);
                    colView.UnrealizeItem(item);
                }
            }
            VisibleItems.RemoveAll(unrealizedItems.Contains);

            //Console.WriteLine("Realize Begin [{0} to {1}]", FirstVisible, LastVisible);
            // 3. Realize and placing visible items.
            for (int i = FirstVisible; i <= LastVisible; i++)
            {
                //Console.WriteLine("[NUI] Realize!");
                RecyclerViewItem item = null;
                // 4. Get item if visible or realize new.
                if (i >= prevFirstVisible && i <= prevLastVisible)
                {
                    item = GetVisibleItem(i);
                    if (item)
                    {
                        continue;
                    }
                }
                if (item == null)
                {
                    item = colView.RealizeItem(i);
                }
                VisibleItems.Add(item);

                (float x, float y) = GetItemPosition(i);
                // 5. Placing item.
                item.Position = new Position(x, y);
                //Console.WriteLine("[NUI] ["+item.Index+"] ["+item.Position.X+", "+item.Position.Y+" ==== \n");
            }
            //Console.WriteLine("Realize Done");
        }