Skip to content

Commit e5080c1

Browse files
committed
feat: 实现主页卡片分页功能
- 更新 HomePage.xaml 和 HomePage.xaml.cs 文件以支持卡片分页显示 - 添加动态调整每页卡片数的逻辑,优化用户界面 - 引入分页按钮和相关事件处理,提升用户体验
1 parent 46b4f73 commit e5080c1

2 files changed

Lines changed: 234 additions & 82 deletions

File tree

Pages/HomePage.xaml

Lines changed: 113 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
TextOptions.TextRenderingMode="ClearType">
1515

1616
<Grid>
17-
<ScrollViewer VerticalScrollBarVisibility="Auto">
17+
<ScrollViewer VerticalScrollBarVisibility="Disabled">
1818
<Grid Margin="24">
1919
<Grid.RowDefinitions>
2020
<RowDefinition Height="Auto"/>
@@ -108,86 +108,118 @@
108108
</Border>
109109

110110
<!-- 主页卡片区域 -->
111-
<ItemsControl x:Name="HomeCardsContainer"
112-
Grid.Row="1"
113-
Margin="0,0,0,16">
114-
<ItemsControl.ItemsPanel>
115-
<ItemsPanelTemplate>
116-
<UniformGrid Columns="2"
117-
HorizontalAlignment="Stretch"
118-
Margin="0,0,0,0"/>
119-
</ItemsPanelTemplate>
120-
</ItemsControl.ItemsPanel>
121-
<ItemsControl.ItemTemplate>
122-
<DataTemplate>
123-
<Border Background="{DynamicResource SurfaceBrush}"
124-
CornerRadius="12"
125-
Padding="20"
126-
Margin="0,0,12,12"
127-
BorderThickness="1"
128-
BorderBrush="{DynamicResource BorderBrush}">
129-
<Border.Effect>
130-
<DropShadowEffect Color="Black"
131-
BlurRadius="10"
132-
ShadowDepth="2"
133-
Opacity="0.1"/>
134-
</Border.Effect>
135-
<Border.Style>
136-
<Style TargetType="Border">
137-
<Style.Triggers>
138-
<Trigger Property="IsMouseOver" Value="True">
139-
<Trigger.EnterActions>
140-
<BeginStoryboard>
141-
<Storyboard>
142-
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
143-
To="1.02" Duration="0:0:0.2">
144-
<DoubleAnimation.EasingFunction>
145-
<CubicEase EasingMode="EaseOut"/>
146-
</DoubleAnimation.EasingFunction>
147-
</DoubleAnimation>
148-
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
149-
To="1.02" Duration="0:0:0.2">
150-
<DoubleAnimation.EasingFunction>
151-
<CubicEase EasingMode="EaseOut"/>
152-
</DoubleAnimation.EasingFunction>
153-
</DoubleAnimation>
154-
</Storyboard>
155-
</BeginStoryboard>
156-
</Trigger.EnterActions>
157-
<Trigger.ExitActions>
158-
<BeginStoryboard>
159-
<Storyboard>
160-
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
161-
To="1.0" Duration="0:0:0.2">
162-
<DoubleAnimation.EasingFunction>
163-
<CubicEase EasingMode="EaseOut"/>
164-
</DoubleAnimation.EasingFunction>
165-
</DoubleAnimation>
166-
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
167-
To="1.0" Duration="0:0:0.2">
168-
<DoubleAnimation.EasingFunction>
169-
<CubicEase EasingMode="EaseOut"/>
170-
</DoubleAnimation.EasingFunction>
171-
</DoubleAnimation>
172-
</Storyboard>
173-
</BeginStoryboard>
174-
</Trigger.ExitActions>
175-
</Trigger>
176-
</Style.Triggers>
177-
<Setter Property="RenderTransform">
178-
<Setter.Value>
179-
<ScaleTransform ScaleX="1.0" ScaleY="1.0"/>
180-
</Setter.Value>
181-
</Setter>
182-
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
183-
<Setter Property="Cursor" Value="Hand"/>
184-
</Style>
185-
</Border.Style>
186-
<ContentControl Content="{Binding Content}"/>
187-
</Border>
188-
</DataTemplate>
189-
</ItemsControl.ItemTemplate>
190-
</ItemsControl>
111+
<Grid Grid.Row="1" Margin="0,0,0,16">
112+
<Grid.RowDefinitions>
113+
<RowDefinition Height="*"/>
114+
<RowDefinition Height="Auto"/>
115+
</Grid.RowDefinitions>
116+
117+
<ItemsControl x:Name="HomeCardsContainer"
118+
Grid.Row="0">
119+
<ItemsControl.ItemsPanel>
120+
<ItemsPanelTemplate>
121+
<UniformGrid Columns="2"
122+
HorizontalAlignment="Stretch"
123+
Margin="0,0,0,0"/>
124+
</ItemsPanelTemplate>
125+
</ItemsControl.ItemsPanel>
126+
<ItemsControl.ItemTemplate>
127+
<DataTemplate>
128+
<Border Background="{DynamicResource SurfaceBrush}"
129+
CornerRadius="12"
130+
Padding="20"
131+
Margin="0,0,12,12"
132+
BorderThickness="1"
133+
BorderBrush="{DynamicResource BorderBrush}">
134+
<Border.Effect>
135+
<DropShadowEffect Color="Black"
136+
BlurRadius="10"
137+
ShadowDepth="2"
138+
Opacity="0.1"/>
139+
</Border.Effect>
140+
<Border.Style>
141+
<Style TargetType="Border">
142+
<Style.Triggers>
143+
<Trigger Property="IsMouseOver" Value="True">
144+
<Trigger.EnterActions>
145+
<BeginStoryboard>
146+
<Storyboard>
147+
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
148+
To="1.02" Duration="0:0:0.2">
149+
<DoubleAnimation.EasingFunction>
150+
<CubicEase EasingMode="EaseOut"/>
151+
</DoubleAnimation.EasingFunction>
152+
</DoubleAnimation>
153+
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
154+
To="1.02" Duration="0:0:0.2">
155+
<DoubleAnimation.EasingFunction>
156+
<CubicEase EasingMode="EaseOut"/>
157+
</DoubleAnimation.EasingFunction>
158+
</DoubleAnimation>
159+
</Storyboard>
160+
</BeginStoryboard>
161+
</Trigger.EnterActions>
162+
<Trigger.ExitActions>
163+
<BeginStoryboard>
164+
<Storyboard>
165+
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
166+
To="1.0" Duration="0:0:0.2">
167+
<DoubleAnimation.EasingFunction>
168+
<CubicEase EasingMode="EaseOut"/>
169+
</DoubleAnimation.EasingFunction>
170+
</DoubleAnimation>
171+
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
172+
To="1.0" Duration="0:0:0.2">
173+
<DoubleAnimation.EasingFunction>
174+
<CubicEase EasingMode="EaseOut"/>
175+
</DoubleAnimation.EasingFunction>
176+
</DoubleAnimation>
177+
</Storyboard>
178+
</BeginStoryboard>
179+
</Trigger.ExitActions>
180+
</Trigger>
181+
</Style.Triggers>
182+
<Setter Property="RenderTransform">
183+
<Setter.Value>
184+
<ScaleTransform ScaleX="1.0" ScaleY="1.0"/>
185+
</Setter.Value>
186+
</Setter>
187+
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
188+
<Setter Property="Cursor" Value="Hand"/>
189+
</Style>
190+
</Border.Style>
191+
<ContentControl Content="{Binding Content}"/>
192+
</Border>
193+
</DataTemplate>
194+
</ItemsControl.ItemTemplate>
195+
</ItemsControl>
196+
197+
<StackPanel x:Name="HomeCardsPaginationPanel"
198+
Grid.Row="1"
199+
Orientation="Horizontal"
200+
HorizontalAlignment="Center"
201+
Margin="0,4,0,0"
202+
Visibility="Collapsed">
203+
<Button x:Name="HomeCardsPrevButton"
204+
Content="上一页"
205+
Height="34"
206+
Padding="14,0,14,0"
207+
Margin="0,0,8,0"
208+
Style="{StaticResource MaterialDesignOutlinedButton}"/>
209+
210+
<TextBlock x:Name="HomeCardsPageText"
211+
VerticalAlignment="Center"
212+
Margin="0,0,8,0"
213+
FontSize="13"
214+
Foreground="{DynamicResource TextSecondaryBrush}"/>
215+
216+
<Button x:Name="HomeCardsNextButton"
217+
Content="下一页"
218+
Height="34"
219+
Padding="14,0,14,0"
220+
Style="{StaticResource MaterialDesignOutlinedButton}"/>
221+
</StackPanel>
222+
</Grid>
191223

192224
<!-- 快速启动区域 -->
193225
<Border Grid.Row="2"

Pages/HomePage.xaml.cs

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ public partial class HomePage : Page
2323
private readonly Dictionary<string, HomeCardInfo> _registeredCards = new Dictionary<string, HomeCardInfo>();
2424
private readonly List<HomeCardInfo> _displayedCards = new List<HomeCardInfo>();
2525
private bool _builtInCardsRegistered = false;
26+
27+
// 卡片分页
28+
private const int MinRowsPerPage = 1;
29+
private const int MaxRowsPerPage = 4;
30+
private const double EstimatedCardRowHeight = 172; // 经验值:单行两张卡片的大致高度(含Margin)
31+
private const double EstimatedPaginationHeight = 50;
32+
33+
private int _rowsPerPage = 2;
34+
private int _cardsPerPage = 4;
35+
private int _currentPage = 1;
36+
private int _totalPages = 1;
2637

2738
public HomePage()
2839
{
@@ -33,6 +44,13 @@ public HomePage()
3344
// 注册插件卡片回调
3445
PluginContext.OnHomeCardRegistered += OnPluginCardRegistered;
3546
PluginContext.OnHomeCardUnregistered += OnPluginCardUnregistered;
47+
48+
// 注册分页按钮事件
49+
HomeCardsPrevButton.Click += (_, __) => ChangeCardPage(-1);
50+
HomeCardsNextButton.Click += (_, __) => ChangeCardPage(1);
51+
52+
// 窗口尺寸变化时,动态调整每页卡片数(节流,避免频繁刷新)
53+
SizeChanged += HomePage_SizeChanged;
3654
}
3755

3856
private void HomePage_Loaded(object sender, RoutedEventArgs e)
@@ -51,6 +69,8 @@ private void HomePage_Unloaded(object sender, RoutedEventArgs e)
5169
{
5270
VersionComboBox.SelectionChanged -= VersionComboBox_SelectionChanged;
5371
}
72+
73+
SizeChanged -= HomePage_SizeChanged;
5474

5575
// 取消注册插件卡片回调
5676
PluginContext.OnHomeCardRegistered -= OnPluginCardRegistered;
@@ -1497,8 +1517,24 @@ private void RefreshCardsDisplay()
14971517
{
14981518
Dispatcher.Invoke(() =>
14991519
{
1520+
// 计算总页数
1521+
var totalCards = _displayedCards.Count;
1522+
_totalPages = Math.Max(1, (int)Math.Ceiling(totalCards / (double)_cardsPerPage));
1523+
1524+
// 确保当前页在合法范围内
1525+
if (_currentPage < 1) _currentPage = 1;
1526+
if (_currentPage > _totalPages) _currentPage = _totalPages;
1527+
1528+
// 取当前页数据
1529+
var pageCards = _displayedCards
1530+
.Skip((_currentPage - 1) * _cardsPerPage)
1531+
.Take(_cardsPerPage)
1532+
.ToList();
1533+
15001534
HomeCardsContainer.ItemsSource = null;
1501-
HomeCardsContainer.ItemsSource = _displayedCards;
1535+
HomeCardsContainer.ItemsSource = pageCards;
1536+
1537+
UpdatePaginationUI(totalCards);
15021538
});
15031539
}
15041540

@@ -1676,6 +1712,90 @@ public void RefreshCards()
16761712
LoadHomeCards();
16771713
}
16781714

1715+
private DispatcherTimer? _pageRecalcTimer;
1716+
1717+
private void HomePage_SizeChanged(object sender, SizeChangedEventArgs e)
1718+
{
1719+
// 节流:拖拽缩放窗口时避免每次都重算+刷新
1720+
if (_pageRecalcTimer == null)
1721+
{
1722+
_pageRecalcTimer = new DispatcherTimer
1723+
{
1724+
Interval = TimeSpan.FromMilliseconds(120)
1725+
};
1726+
_pageRecalcTimer.Tick += (_, __) =>
1727+
{
1728+
_pageRecalcTimer?.Stop();
1729+
RecalculateCardsPerPageAndRefresh();
1730+
};
1731+
}
1732+
1733+
_pageRecalcTimer.Stop();
1734+
_pageRecalcTimer.Start();
1735+
}
1736+
1737+
private void RecalculateCardsPerPageAndRefresh()
1738+
{
1739+
// 根据页面实际高度估算卡片区域可用高度
1740+
// 主页结构:上方Banner(200) + 间距(16) + 卡片区 + 间距(16) + 快速启动区(约120) + Margin(24*2)
1741+
var pageHeight = ActualHeight;
1742+
if (pageHeight <= 0)
1743+
{
1744+
pageHeight = 700; // 设计期兜底
1745+
}
1746+
1747+
var estimatedQuickLaunchArea = 160;
1748+
var reserved = 200 + 16 + 16 + estimatedQuickLaunchArea + 48;
1749+
var availableHeight = Math.Max(0, pageHeight - reserved);
1750+
1751+
// 预留分页控件高度(即使暂时不显示,也避免临界时“跳动”)
1752+
var effectiveHeight = Math.Max(0, availableHeight - EstimatedPaginationHeight);
1753+
1754+
var rows = (int)Math.Floor(effectiveHeight / EstimatedCardRowHeight);
1755+
rows = Math.Max(MinRowsPerPage, Math.Min(MaxRowsPerPage, rows));
1756+
1757+
_rowsPerPage = rows;
1758+
_cardsPerPage = Math.Max(2, _rowsPerPage * 2); // 两列布局
1759+
1760+
RefreshCardsDisplay();
1761+
}
1762+
1763+
private void ChangeCardPage(int delta)
1764+
{
1765+
if (_totalPages <= 1)
1766+
{
1767+
_currentPage = 1;
1768+
return;
1769+
}
1770+
1771+
_currentPage += delta;
1772+
if (_currentPage < 1) _currentPage = 1;
1773+
if (_currentPage > _totalPages) _currentPage = _totalPages;
1774+
1775+
RefreshCardsDisplay();
1776+
}
1777+
1778+
private void UpdatePaginationUI(int totalCards)
1779+
{
1780+
if (HomeCardsPaginationPanel == null || HomeCardsPrevButton == null || HomeCardsNextButton == null || HomeCardsPageText == null)
1781+
{
1782+
return;
1783+
}
1784+
1785+
var needPagination = totalCards > _cardsPerPage;
1786+
HomeCardsPaginationPanel.Visibility = needPagination ? Visibility.Visible : Visibility.Collapsed;
1787+
1788+
if (!needPagination)
1789+
{
1790+
HomeCardsPageText.Text = string.Empty;
1791+
return;
1792+
}
1793+
1794+
HomeCardsPageText.Text = $"{_currentPage} / {_totalPages}";
1795+
HomeCardsPrevButton.IsEnabled = _currentPage > 1;
1796+
HomeCardsNextButton.IsEnabled = _currentPage < _totalPages;
1797+
}
1798+
16791799
#endregion
16801800
}
16811801
}

0 commit comments

Comments
 (0)