CenteredTabPanel.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. using System;
  2. using Avalonia;
  3. using Avalonia.Controls;
  4. namespace ControlCatalog.Pages
  5. {
  6. /// <summary>
  7. /// A custom panel that arranges N children in N+1 equally-sized slots, leaving the
  8. /// middle slot empty. Intended for tab bars that need a central action button
  9. /// overlaid on the gap.
  10. ///
  11. /// For N children the split is ⌊N/2⌋ items on the left and ⌈N/2⌉ on the right.
  12. /// Example – 4 tabs: [0][1][ gap ][2][3] (5 equal columns, center is free).
  13. /// </summary>
  14. public class CenteredTabPanel : Panel
  15. {
  16. protected override Size MeasureOverride(Size availableSize)
  17. {
  18. int count = Children.Count;
  19. if (count == 0)
  20. return default;
  21. int slots = count + 1;
  22. bool infiniteWidth = double.IsInfinity(availableSize.Width);
  23. double slotWidth = infiniteWidth ? 60.0 : availableSize.Width / slots;
  24. double maxHeight = 0;
  25. foreach (var child in Children)
  26. {
  27. child.Measure(new Size(slotWidth, availableSize.Height));
  28. maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
  29. }
  30. // When given finite width, fill it. When infinite (inside a ScrollViewer),
  31. // return a small positive width so the parent allocates real space.
  32. double desiredWidth = infiniteWidth ? slotWidth * slots : availableSize.Width;
  33. if (double.IsNaN(maxHeight) || double.IsInfinity(maxHeight))
  34. maxHeight = 0;
  35. return new Size(desiredWidth, maxHeight);
  36. }
  37. protected override Size ArrangeOverride(Size finalSize)
  38. {
  39. int count = Children.Count;
  40. if (count == 0)
  41. return finalSize;
  42. int slots = count + 1;
  43. double slotW = finalSize.Width / slots;
  44. int leftCount = count / 2; // items placed to the left of the gap
  45. for (int i = 0; i < count; i++)
  46. {
  47. // Skip the center slot (leftCount), reserved for the FAB.
  48. int slot = i < leftCount ? i : i + 1;
  49. Children[i].Arrange(new Rect(slot * slotW, 0, slotW, finalSize.Height));
  50. }
  51. return finalSize;
  52. }
  53. }
  54. }