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); }
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); }