mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-29 07:16:33 +08:00
feat(BrowserGallery): integrate FloatButtonShowCase and enhance lazy loading for improved navigation
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using AtomUIGallery.ShowCases.AboutUs;
|
||||
using AtomUIGallery.ShowCases.Button;
|
||||
using AtomUIGallery.ShowCases.FloatButton;
|
||||
using AtomUIGallery.ShowCases.Icon;
|
||||
using AtomUIGallery.ShowCases.Palette;
|
||||
using Avalonia;
|
||||
@@ -21,12 +22,14 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
|
||||
private static readonly BrowserGalleryPageKind[] s_pagesToPreload =
|
||||
[
|
||||
BrowserGalleryPageKind.Button,
|
||||
BrowserGalleryPageKind.FloatButton,
|
||||
BrowserGalleryPageKind.Palette,
|
||||
BrowserGalleryPageKind.Icons
|
||||
];
|
||||
|
||||
private readonly Border _aboutUsNavigationItem;
|
||||
private readonly Border _buttonNavigationItem;
|
||||
private readonly Border _floatButtonNavigationItem;
|
||||
private readonly Border _paletteNavigationItem;
|
||||
private readonly Border _iconsNavigationItem;
|
||||
private readonly Grid _contentHost;
|
||||
@@ -72,10 +75,11 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
|
||||
};
|
||||
Grid.SetColumnSpan(header, 2);
|
||||
|
||||
_aboutUsNavigationItem = CreateNavigationItem("AboutUs", () => ShowAboutUs());
|
||||
_buttonNavigationItem = CreateNavigationItem("Button", () => ShowButton());
|
||||
_paletteNavigationItem = CreateNavigationItem("Palette", () => ShowPalette());
|
||||
_iconsNavigationItem = CreateNavigationItem("Icons", () => ShowIcons());
|
||||
_aboutUsNavigationItem = CreateNavigationItem("AboutUs", () => ShowAboutUs());
|
||||
_buttonNavigationItem = CreateNavigationItem("Button", () => ShowButton());
|
||||
_floatButtonNavigationItem = CreateNavigationItem("FloatButton", () => ShowFloatButton());
|
||||
_paletteNavigationItem = CreateNavigationItem("Palette", () => ShowPalette());
|
||||
_iconsNavigationItem = CreateNavigationItem("Icons", () => ShowIcons());
|
||||
|
||||
var navigation = new Border
|
||||
{
|
||||
@@ -97,6 +101,7 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
|
||||
},
|
||||
_aboutUsNavigationItem,
|
||||
_buttonNavigationItem,
|
||||
_floatButtonNavigationItem,
|
||||
_paletteNavigationItem,
|
||||
_iconsNavigationItem
|
||||
}
|
||||
@@ -158,6 +163,11 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
|
||||
ShowPage(BrowserGalleryPageKind.Button, _buttonNavigationItem);
|
||||
}
|
||||
|
||||
private void ShowFloatButton()
|
||||
{
|
||||
ShowPage(BrowserGalleryPageKind.FloatButton, _floatButtonNavigationItem);
|
||||
}
|
||||
|
||||
private void ShowPalette()
|
||||
{
|
||||
ShowPage(BrowserGalleryPageKind.Palette, _paletteNavigationItem);
|
||||
@@ -226,6 +236,10 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
|
||||
{
|
||||
DataContext = new ButtonViewModel(this)
|
||||
},
|
||||
BrowserGalleryPageKind.FloatButton => new FloatButtonShowCase
|
||||
{
|
||||
DataContext = new FloatButtonViewModel(this)
|
||||
},
|
||||
BrowserGalleryPageKind.Palette => new PaletteShowCase
|
||||
{
|
||||
DataContext = new PaletteViewModel(this)
|
||||
@@ -275,6 +289,7 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
|
||||
{
|
||||
ApplyNavigationItemState(_aboutUsNavigationItem, selectedItem == _aboutUsNavigationItem);
|
||||
ApplyNavigationItemState(_buttonNavigationItem, selectedItem == _buttonNavigationItem);
|
||||
ApplyNavigationItemState(_floatButtonNavigationItem, selectedItem == _floatButtonNavigationItem);
|
||||
ApplyNavigationItemState(_paletteNavigationItem, selectedItem == _paletteNavigationItem);
|
||||
ApplyNavigationItemState(_iconsNavigationItem, selectedItem == _iconsNavigationItem);
|
||||
}
|
||||
@@ -295,6 +310,7 @@ internal sealed class BrowserGalleryView : UserControl, IScreen
|
||||
{
|
||||
AboutUs,
|
||||
Button,
|
||||
FloatButton,
|
||||
Palette,
|
||||
Icons
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
- 新增 Browser Gallery 项目并跑通空壳应用。
|
||||
- Browser 启动阶段使用 AtomUI 红色 SVG logo。
|
||||
- Browser Gallery 不复制 `AboutUsPage` / `ButtonShowCase` / `PaletteShowCase` / `IconShowCase`,只做一层薄的宿主封装。
|
||||
- Browser Gallery 不复制 `AboutUsPage` / `ButtonShowCase` / `FloatButtonShowCase` / `PaletteShowCase` / `IconShowCase`,只做一层薄的宿主封装。
|
||||
- Browser 可以引用 `AtomUI.Desktop.Controls`,用户侧继续调用 `UseDesktopControls()`,控件库内部按平台自动降级。
|
||||
- 不改变公开 API,不影响 Desktop Gallery 原有行为。
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
| Button 迁移后 Browser 白屏 | 临时把 Browser 默认页切到 `ButtonShowCase` 时,页面无 `.splash-error` 但 canvas 持续白屏 | `ButtonShowCase` 首次引入 `ShowCasePanel` / `ShowCaseItem` / `Separator` / `OptionButtonGroup`,并且完整 Desktop `ButtonTheme` 在 Browser 首帧下过重且不稳定 | Browser provider 补 `Separator`、`OptionButtonGroup` 主题和 token;`BrowserButtonThemes.axaml` 使用轻量 `atom:Button` 降级主题,但保留 hover/pressed/loading/wave/icon/dashed/ghost 等交互表达,Desktop 仍走完整 `ButtonTheme` |
|
||||
| Browser Button 视觉降级过头 | Button ShowCase 中 dashed、icon-only、Search、Ghost 等区域与 Desktop 正常效果差异明显 | 首版 Browser Button 主题只保留基础状态,缺少 Desktop 的 Frame 高度、icon-only padding/尺寸、DashedBorder 和 Ghost/Danger 组合样式 | 在不恢复完整 Desktop `ButtonTheme` 的前提下,补齐 Browser Button 的关键可见样式;Release host 中验证 Button 和 Ghost 区域正常渲染 |
|
||||
| Link Button 在 Ghost 区域出现白底 | Desktop Gallery 的 Ghost Button 示例里,Link 类型按钮在灰色背景上出现白色背景块 | Desktop `ButtonTheme` 的 `ButtonType=Link` 分支直接给 template `Border#Frame` 设置了 `DefaultBg`,覆盖了按钮自身的透明背景 | 删除 Link 类型对 `Frame.Background` 的白底设置,改为 Link 按钮自身 `Background=Transparent`,让 template binding 正常透传 |
|
||||
| FloatButton 迁移需要 OverlayLayer | Browser 加入 `FloatButtonShowCase` 后需要让悬浮按钮挂载到正确的局部 overlay | `FloatButtonHost` / `FloatButtonGroupHost` 不依赖 Window,依赖 `ScopeAwareOverlayLayer`;ShowCase 内的 `atom:ScrollViewer` 模板已经提供 `ScopeAwareOverlayLayerPanel` | Browser provider 补 `FloatButton`、`Badge`、`ToggleSwitch` 主题和 token,继续复用共享 ShowCase,不新增 Browser 专用页面 |
|
||||
| FloatButtonGroup 存在重复父级风险 | 页面缓存、隐藏/显示或重新套模板后,同一批子按钮可能被再次加入内部 `FloatButtonItemsControl` | `FloatButtonGroupHost` 把 Host `Children` 转移到 overlay 内的 `FloatButtonGroup`,旧 group / items control 没有在 detach 或 re-template 时清理子项;click trigger 在 detach 时也可能重新订阅输入事件 | 内部补齐 group children、items control children 和 items layout children 的成对清理;click trigger 只在已附着视觉树时订阅,detach 时释放 |
|
||||
| Browser FloatButton Placement 展开缺子按钮 | Placement 示例中点击左侧展开组后,trigger 变为 X,但 X 左侧两个子按钮没有显示 | Browser 分支此前完全跳过 Desktop initialized handler,导致 `MotionTransformOptionsAnimator` 没有注册;`MoveRightInMotion` / `MoveLeftInMotion` 的 `TransformOperations` keyframe 动画停留在隐藏起始态 | initialized handler 所有平台都注册 `TransformOperations` animator;`ToolTipService` 和 `MediaBreakPointThemeBootstrapper` 继续只在 native window 下启用 |
|
||||
| FloatButton Tooltip 暂未打开 Browser 完整链路 | Tooltip 属性在 Browser 下不会导致页面崩溃,但本轮不验证 tooltip 弹层 | AtomUI Tooltip 会继续牵出 `Popup`、`PopupRoot`、`OverlayPopupHost`、`ArrowDecoratedBox`、`PopupHostToken`、`ToolTipService` 等一组资源,超出 FloatButton ShowCase 首轮接入范围 | 本轮先保证 FloatButton 主体、Badge、BackTop、Group 可用;Tooltip/Popup Browser 降级后续单独拆分验证 |
|
||||
| Browser shell 字体未继承 AtomUI 字体 | Browser Gallery 外壳文字看起来没有使用 AtomUI 的 AlibabaSans | Browser 根是 `UserControl`,没有 Desktop `atom:Window` theme 里的 `FontFamily="{atom:SharedTokenResource FontFamily}"` 继承入口 | `BrowserGalleryView` 根设置 `fonts:AlibabaSans#Alibaba Sans, $Default`,由 Avalonia 可继承 `FontFamily` 向导航外壳和共享 ShowCase 传递 |
|
||||
| Browser 导航切页卡顿明显 | AboutUs / Button / Palette / Icons 之间切换时,新页面出来有明显停顿 | Browser 宿主原先每次点击都 `new` 页面和 ViewModel,并替换 `ContentControl.Content`,导致 ShowCase XAML、控件模板、主题匹配、首次布局和绘制全部冷启动 | `BrowserGalleryView` 改为 lazy page cache,首次进入页面后保留在同一个 `Grid` 中,切换只调整 `IsVisible`;首屏加载后再按 idle 顺序预热 Button / Palette / Icons,降低用户首次点击重页面时的冷启动体感 |
|
||||
|
||||
@@ -72,6 +76,11 @@ var buttonShowCase = new ButtonShowCase
|
||||
DataContext = new ButtonViewModel(this)
|
||||
};
|
||||
|
||||
var floatButtonShowCase = new FloatButtonShowCase
|
||||
{
|
||||
DataContext = new FloatButtonViewModel(this)
|
||||
};
|
||||
|
||||
var paletteShowCase = new PaletteShowCase
|
||||
{
|
||||
DataContext = new PaletteViewModel(this)
|
||||
@@ -85,7 +94,7 @@ var iconShowCase = new IconShowCase
|
||||
|
||||
页面首次打开后会保留在 Browser 宿主的内容 `Grid` 中,非当前页通过 `IsVisible = false` 隐藏。这样可以保留 ViewModel、控件树、滚动位置和 Icons 已加载内容,避免切回时再次触发 XAML inflate / template / layout 冷启动。
|
||||
|
||||
首屏 `AboutUsPage` 加载完成后,Browser 宿主会用 `DispatcherPriority.ApplicationIdle` 依次预热 `ButtonShowCase`、`PaletteShowCase` 和 `IconShowCase`。预热页面先以 `Opacity = 0`、`IsHitTestVisible = false` 放入内容 `Grid`,让模板和布局在用户空闲时完成一轮,再隐藏回缓存;如果用户在预热期间点击该页面,正常导航会接管可见性。
|
||||
首屏 `AboutUsPage` 加载完成后,Browser 宿主会用 `DispatcherPriority.ApplicationIdle` 依次预热 `ButtonShowCase`、`FloatButtonShowCase`、`PaletteShowCase` 和 `IconShowCase`。预热页面先以 `Opacity = 0`、`IsHitTestVisible = false` 放入内容 `Grid`,让模板和布局在用户空闲时完成一轮,再隐藏回缓存;如果用户在预热期间点击该页面,正常导航会接管可见性。
|
||||
|
||||
当前 Browser 已接入页面没有后台定时任务;后续迁移有持续订阅或异步任务的 ShowCase 时,需要单独评估隐藏页保持 attached 的成本。
|
||||
|
||||
@@ -131,12 +140,15 @@ themeManagerBuilder.AddControlThemesProvider(RuntimePlatform.Features.SupportsNa
|
||||
Browser desktop provider 当前只承载 Browser Gallery 已接入 ShowCase 需要的最小集合:
|
||||
|
||||
```text
|
||||
Badge/Themes/BadgeThemes.axaml
|
||||
Buttons/Themes/BrowserButtonThemes.axaml
|
||||
FloatButton/Themes/FloatButtonThemes.axaml
|
||||
GroupBox/Themes/GroupBoxTheme.axaml
|
||||
Input/Themes/BrowserInputThemes.axaml
|
||||
OptionButtonGroup/Themes/OptionButtonBoxThemes.axaml
|
||||
ScrollViewer/Themes/ScrollViewerThemes.axaml
|
||||
Separator/Themes/SeparatorTheme.axaml
|
||||
Switch/Themes/ToggleSwitchThemes.axaml
|
||||
TabControl/Themes/TabControlThemes.axaml
|
||||
```
|
||||
|
||||
@@ -144,7 +156,9 @@ Browser token 当前只注册:
|
||||
|
||||
```text
|
||||
AddOnDecoratedBoxToken
|
||||
BadgeToken
|
||||
ButtonToken
|
||||
FloatButtonToken
|
||||
GroupBoxToken
|
||||
LineEditToken
|
||||
MenuToken
|
||||
@@ -152,6 +166,7 @@ OptionButtonToken
|
||||
ScrollViewerToken
|
||||
SeparatorToken
|
||||
TabControlToken
|
||||
ToggleSwitchToken
|
||||
```
|
||||
|
||||
Desktop 下仍然使用完整 `ControlTokenTypePool` 和 `DesktopControlThemesProvider`,并继续注册原有 initialized handler。Browser 下跳过该 handler,避免注册 Window/Tooltip/媒体断点等 native window 相关逻辑。
|
||||
@@ -176,6 +191,7 @@ Desktop 下仍然使用完整 `ControlTokenTypePool` 和 `DesktopControlThemesPr
|
||||
|
||||
```bash
|
||||
dotnet build controlgallery/AtomUIGallery.Browser/AtomUIGallery.Browser.csproj -c Debug
|
||||
dotnet build controlgallery/AtomUIGallery.Browser/AtomUIGallery.Browser.csproj -c Release
|
||||
dotnet build controlgallery/AtomUIGallery.Desktop/AtomUIGallery.Desktop.csproj -c Debug
|
||||
```
|
||||
|
||||
@@ -184,8 +200,10 @@ dotnet build controlgallery/AtomUIGallery.Desktop/AtomUIGallery.Desktop.csproj -
|
||||
- Browser Debug build 通过。
|
||||
- Browser Release build 通过。
|
||||
- Desktop Gallery Debug build 通过。
|
||||
- Browser 实跑 `AboutUsPage` / `ButtonShowCase` / `PaletteShowCase` / `IconShowCase` 渲染成功,无 `.splash-error`。
|
||||
- Browser 实跑 `AboutUsPage` / `ButtonShowCase` / `FloatButtonShowCase` / `PaletteShowCase` / `IconShowCase` 渲染成功,无 `.splash-error`。
|
||||
- `ButtonShowCase` 在 Release host 中验证首屏渲染成功,Button hover 状态可见,点击 smoke test 无当前端口错误日志;最终代码仍默认进入 `AboutUsPage`。
|
||||
- `FloatButtonShowCase` 在 Release host 中验证首屏渲染成功;切到 Button 后再切回 FloatButton 仍正常渲染;向下滚动到 Placement / Badge / BackTop 区域后渲染正常;点击 Placement click group 后无当前端口错误日志。
|
||||
- Browser 修复 `MotionTransformOptionsAnimator` 注册后,Release host 中复测 Placement 左侧展开组,X 左侧两个子按钮正常显示,无当前端口错误日志。
|
||||
- `IconShowCase` 的 `Outlined` / `Filled` / `Two Tone` tab 均已在 Browser 中切换并渲染图标网格。
|
||||
- Browser 导航 lazy cache 后,Release host 中执行 Button / Icons / Button / Icons 切换 smoke test,Icons 二次切回仍正常渲染,无当前端口错误日志。
|
||||
- Browser 导航 idle 预热后,Release host 中等待首屏预热并执行 Button / Palette / Icons 切换 smoke test,最终 Icons 正常渲染,无当前端口错误日志。
|
||||
@@ -206,6 +224,7 @@ Browser 运行验证时不要只依赖 DOM 文本,因为 Avalonia Browser 页
|
||||
## 待继续处理
|
||||
|
||||
- `UseDesktopColorPicker()` 和 `UseDesktopDataGrid()` 尚未接入 Browser 降级路径。
|
||||
- Browser Gallery 当前只接入 `AboutUsPage`、`ButtonShowCase`、`PaletteShowCase` 和 `IconShowCase`,完整 Workspace / AppView / AppShell 还未实现。
|
||||
- Browser Gallery 当前只接入 `AboutUsPage`、`ButtonShowCase`、`FloatButtonShowCase`、`PaletteShowCase` 和 `IconShowCase`,完整 Workspace / AppView / AppShell 还未实现。
|
||||
- Tooltip / Popup 的 Browser 降级链路尚未打开;`FloatButtonShowCase` 中 Tooltip 属性本轮只保证不阻塞页面渲染。
|
||||
- `BrowserDesktopControlThemesProvider` 的范围后续应随着 ShowCase 迁移逐步扩大,并保持最小可用集合。
|
||||
- `EmbeddableControlRootTheme` 在 Browser 下的精确不兼容点后续可以进一步拆解;当前先通过 Browser provider 排除该资源,保证启动路径稳定。
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
x:Class="AtomUI.Desktop.Controls.BrowserDesktopControlThemesProvider"
|
||||
Id="AtomUI.Desktop.Controls">
|
||||
<atom:ControlThemesProvider.ControlThemes>
|
||||
<ResourceInclude Source="Badge/Themes/BadgeThemes.axaml" />
|
||||
<ResourceInclude Source="Primitives/Themes/WaveSpiritDecoratorTheme.axaml" />
|
||||
<ResourceInclude Source="Buttons/Themes/BrowserButtonThemes.axaml" />
|
||||
<ResourceInclude Source="FloatButton/Themes/FloatButtonThemes.axaml" />
|
||||
<ResourceInclude Source="GroupBox/Themes/GroupBoxTheme.axaml" />
|
||||
<ResourceInclude Source="Input/Themes/BrowserInputThemes.axaml" />
|
||||
<ResourceInclude Source="OptionButtonGroup/Themes/OptionButtonBoxThemes.axaml" />
|
||||
<ResourceInclude Source="ScrollViewer/Themes/ScrollViewerThemes.axaml" />
|
||||
<ResourceInclude Source="Separator/Themes/SeparatorTheme.axaml" />
|
||||
<ResourceInclude Source="Switch/Themes/ToggleSwitchThemes.axaml" />
|
||||
<ResourceInclude Source="TabControl/Themes/TabControlThemes.axaml" />
|
||||
</atom:ControlThemesProvider.ControlThemes>
|
||||
</atom:ControlThemesProvider>
|
||||
|
||||
@@ -211,6 +211,7 @@ public class FloatButtonGroup : TemplatedControl, IMotionAwareControl
|
||||
private bool _showAnimating;
|
||||
private bool _hideAnimating;
|
||||
private bool _closeRequest;
|
||||
private bool _isAttachedToVisualTree;
|
||||
|
||||
static FloatButtonGroup()
|
||||
{
|
||||
@@ -291,6 +292,7 @@ public class FloatButtonGroup : TemplatedControl, IMotionAwareControl
|
||||
_triggerButton.PointerEntered -= HandlePointerEntered;
|
||||
_triggerButton.PointerExited -= HandlePointerExited;
|
||||
}
|
||||
DetachItemsControlChildren();
|
||||
_itemsControl = e.NameScope.Find<FloatButtonItemsControl>("ItemsControl");
|
||||
_triggerButton = e.NameScope.Find<FloatButton>("Trigger");
|
||||
_motionActor = e.NameScope.Find<BaseMotionActor>(BaseMotionActor.MotionActorPart);
|
||||
@@ -334,7 +336,7 @@ public class FloatButtonGroup : TemplatedControl, IMotionAwareControl
|
||||
{
|
||||
foreach (var child in newChildren)
|
||||
{
|
||||
if (child is FloatButton floatButton)
|
||||
if (child is AbstractFloatButton floatButton)
|
||||
{
|
||||
NotifyAddItem(floatButton);
|
||||
}
|
||||
@@ -351,9 +353,9 @@ public class FloatButtonGroup : TemplatedControl, IMotionAwareControl
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
for (var i = 0; i < e.OldItems!.Count; ++i)
|
||||
{
|
||||
if (e.OldItems[i] is FloatButton floatButton)
|
||||
if (e.OldItems[i] is AbstractFloatButton floatButton)
|
||||
{
|
||||
floatButton.SetCurrentValue(FloatButton.IsEmbedModeProperty, false);
|
||||
floatButton.SetCurrentValue(AbstractFloatButton.IsEmbedModeProperty, false);
|
||||
}
|
||||
}
|
||||
_itemsControl.Children.RemoveRange(e.OldStartingIndex, e.OldItems!.Count);
|
||||
@@ -409,20 +411,21 @@ public class FloatButtonGroup : TemplatedControl, IMotionAwareControl
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_clickTriggerDisposable?.Dispose();
|
||||
_clickTriggerDisposable = null;
|
||||
_isAttachedToVisualTree = true;
|
||||
ConfigureTriggerType();
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
ConfigureTriggerType();
|
||||
_isAttachedToVisualTree = false;
|
||||
DisposeClickTrigger();
|
||||
}
|
||||
|
||||
private void ConfigureTriggerType()
|
||||
{
|
||||
_clickTriggerDisposable?.Dispose();
|
||||
if (Trigger == FloatButtonGroupTrigger.Click)
|
||||
DisposeClickTrigger();
|
||||
if (_isAttachedToVisualTree && Trigger == FloatButtonGroupTrigger.Click)
|
||||
{
|
||||
var inputManager = AvaloniaLocator.Current.GetService(typeof(IInputManager)) as IInputManager;
|
||||
_clickTriggerDisposable = inputManager?.Process.Subscribe(HandleMouseClick);
|
||||
@@ -434,6 +437,20 @@ public class FloatButtonGroup : TemplatedControl, IMotionAwareControl
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeClickTrigger()
|
||||
{
|
||||
_clickTriggerDisposable?.Dispose();
|
||||
_clickTriggerDisposable = null;
|
||||
}
|
||||
|
||||
private void DetachItemsControlChildren()
|
||||
{
|
||||
if (_itemsControl is { Children.Count: > 0 } itemsControl)
|
||||
{
|
||||
itemsControl.Children.RemoveRange(0, itemsControl.Children.Count);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleMouseClick(RawInputEventArgs args)
|
||||
{
|
||||
if (args is RawPointerEventArgs pointerEventArgs)
|
||||
|
||||
@@ -172,12 +172,21 @@ public class FloatButtonGroupHost : TemplatedControl, IMotionAwareControl
|
||||
if (FloatButtonGroup != null)
|
||||
{
|
||||
_overlayLayer = ScopeAwareOverlayLayer.FindLayer(this);
|
||||
DetachFloatButtonGroupChildren();
|
||||
_overlayLayer?.Children.Remove(FloatButtonGroup);
|
||||
Disposables?.Dispose();
|
||||
Disposables = null;
|
||||
FloatButtonGroup = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void DetachFloatButtonGroupChildren()
|
||||
{
|
||||
if (FloatButtonGroup is { Children.Count: > 0 } floatButtonGroup)
|
||||
{
|
||||
floatButtonGroup.Children.RemoveRange(0, floatButtonGroup.Children.Count);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual FloatButtonGroup NotifyCreateFloatButtonGroup(CompositeDisposable disposables)
|
||||
{
|
||||
|
||||
@@ -93,9 +93,18 @@ internal class FloatButtonItemsControl : TemplatedControl
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
DetachItemsLayoutChildren();
|
||||
_itemsLayout = e.NameScope.Find<StackPanel>("PART_ItemsLayout");
|
||||
_itemsLayout?.Children.AddRange(Children);
|
||||
}
|
||||
|
||||
private void DetachItemsLayoutChildren()
|
||||
{
|
||||
if (_itemsLayout is { Children.Count: > 0 } itemsLayout)
|
||||
{
|
||||
itemsLayout.Children.RemoveRange(0, itemsLayout.Children.Count);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void NotifyChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
|
||||
@@ -32,10 +32,7 @@ public static class ThemeManagerBuilderExtensions
|
||||
themeManagerBuilder.AddLanguageProviders(languageProvider);
|
||||
}
|
||||
|
||||
if (RuntimePlatform.Features.SupportsNativeWindow)
|
||||
{
|
||||
themeManagerBuilder.InitializedHandlers.Add(HandleThemeManagerInitialized);
|
||||
}
|
||||
themeManagerBuilder.InitializedHandlers.Add(HandleThemeManagerInitialized);
|
||||
|
||||
return themeManagerBuilder;
|
||||
}
|
||||
@@ -43,12 +40,16 @@ public static class ThemeManagerBuilderExtensions
|
||||
private static void HandleThemeManagerInitialized(object? sender, EventArgs e)
|
||||
{
|
||||
Animation.RegisterCustomAnimator<TransformOperations, MotionTransformOptionsAnimator>();
|
||||
if (!RuntimePlatform.Features.SupportsNativeWindow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inputManager = AvaloniaLocator.CurrentMutable.GetService<IInputManager>();
|
||||
Debug.Assert(inputManager != null);
|
||||
AvaloniaLocator.CurrentMutable.BindToSelf(new ToolTipService(inputManager));
|
||||
|
||||
if (RuntimePlatform.Features.SupportsNativeWindow &&
|
||||
sender is ThemeManager themeManager)
|
||||
if (sender is ThemeManager themeManager)
|
||||
{
|
||||
MediaBreakPointThemeBootstrapper.Attach(themeManager);
|
||||
}
|
||||
@@ -59,14 +60,17 @@ public static class ThemeManagerBuilderExtensions
|
||||
return new List<Type>
|
||||
{
|
||||
typeof(AddOnDecoratedBoxToken),
|
||||
typeof(BadgeToken),
|
||||
typeof(ButtonToken),
|
||||
typeof(FloatButtonToken),
|
||||
typeof(GroupBoxToken),
|
||||
typeof(LineEditToken),
|
||||
typeof(MenuToken),
|
||||
typeof(OptionButtonToken),
|
||||
typeof(ScrollViewerToken),
|
||||
typeof(SeparatorToken),
|
||||
typeof(TabControlToken)
|
||||
typeof(TabControlToken),
|
||||
typeof(ToggleSwitchToken)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user