Beispiel #1
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);
        }
Beispiel #2
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);
        }
Beispiel #3
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");
            }
        }
Beispiel #4
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");
        }