翼度科技»论坛 编程开发 .net 查看内容

Blazor如何实现类似于微信的Tab切换?

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
是否有小伙伴在使用tab的时候想进行滑动切换Tab?
并且有滑动左出左进,右出右进的效果 ,本文将讲解怎么在Blazor中去通过滑动切换Tab
本文中的UI组件使用的是MASA Blazor,您也可以是其他的UI框架,这个并不影响实际的运行效果,本文案例是兼容PC和Android的,演示效果是android中执行的,在PC中执行效果依然有效(亲测)
首先安装MASA Blazor 根据 MASA Blazor安装MASA Blazor
准备工作


  • 创建 AppBar.razor文件
  • 修改MainLayout.razor文件代码
  1. @inherits LayoutComponentBase
  2. <MApp>
  3.     <AppBar>
  4.         
  5.             @Body
  6.         
  7.     </AppBar>
  8. </MApp>
复制代码

  • 创建 AppBar.razor.css 文件并且添加相关代码 ,以下代码是为了实现切换的时候有一个出入效果,具体代码案例来自Animista - On-Demand CSS Animations Library
    1. /*左边滑动出*/
    2. .slide-out-left {
    3.     -webkit-animation: slide-out-left 0.5s;
    4.     animation: slide-out-left 0.5s;
    5. }
    6. /*右边滑动出*/
    7. .slide-out-right {
    8.     -webkit-animation: slide-out-right 0.5s;
    9.     animation: slide-out-right 0.5s;
    10. }
    11. /*右边滑动进*/
    12. .slide-in-right {
    13.     -webkit-animation: slide-in-right 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
    14.     animation: slide-in-right 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
    15. }
    16. /*左边滑动进*/
    17. .slide-in-left {
    18.     -webkit-animation: slide-in-left 0.5s;
    19.     animation: slide-in-left 0.5s;
    20. }
    21. @-webkit-keyframes slide-out-left {
    22.     0% {
    23.         -webkit-transform: translateX(0);
    24.         transform: translateX(0);
    25.         opacity: 1;
    26.     }
    27.     100% {
    28.         -webkit-transform: translateX(-1000px);
    29.         transform: translateX(-1000px);
    30.         opacity: 0;
    31.     }
    32. }
    33. @keyframes slide-out-left {
    34.     0% {
    35.         -webkit-transform: translateX(0);
    36.         transform: translateX(0);
    37.         opacity: 1;
    38.     }
    39.     100% {
    40.         -webkit-transform: translateX(-1000px);
    41.         transform: translateX(-1000px);
    42.         opacity: 0;
    43.     }
    44. }
    45. @-webkit-keyframes slide-out-right {
    46.     0% {
    47.         -webkit-transform: translateX(0);
    48.         transform: translateX(0);
    49.         opacity: 1;
    50.     }
    51.     100% {
    52.         -webkit-transform: translateX(1000px);
    53.         transform: translateX(1000px);
    54.         opacity: 0;
    55.     }
    56. }
    57. @keyframes slide-out-right {
    58.     0% {
    59.         -webkit-transform: translateX(0);
    60.         transform: translateX(0);
    61.         opacity: 1;
    62.     }
    63.     100% {
    64.         -webkit-transform: translateX(1000px);
    65.         transform: translateX(1000px);
    66.         opacity: 0;
    67.     }
    68. }
    69. @-webkit-keyframes slide-in-left {
    70.     0% {
    71.         -webkit-transform: translateX(-1000px);
    72.         transform: translateX(-1000px);
    73.         opacity: 0;
    74.     }
    75.     100% {
    76.         -webkit-transform: translateX(0);
    77.         transform: translateX(0);
    78.         opacity: 1;
    79.     }
    80. }
    81. @keyframes slide-in-left {
    82.     0% {
    83.         -webkit-transform: translateX(-1000px);
    84.         transform: translateX(-1000px);
    85.         opacity: 0;
    86.     }
    87.     100% {
    88.         -webkit-transform: translateX(0);
    89.         transform: translateX(0);
    90.         opacity: 1;
    91.     }
    92. }
    93. @-webkit-keyframes slide-in-right {
    94.     0% {
    95.         -webkit-transform: translateX(1000px);
    96.         transform: translateX(1000px);
    97.         opacity: 0;
    98.     }
    99.     100% {
    100.         -webkit-transform: translateX(0);
    101.         transform: translateX(0);
    102.         opacity: 1;
    103.     }
    104. }
    105. @keyframes slide-in-right {
    106.     0% {
    107.         -webkit-transform: translateX(1000px);
    108.         transform: translateX(1000px);
    109.         opacity: 0;
    110.     }
    111.     100% {
    112.         -webkit-transform: translateX(0);
    113.         transform: translateX(0);
    114.         opacity: 1;
    115.     }
    116. }
    复制代码
  • 创建AppBar的模型用于动态添加导航栏, 创建AppBarDto.cs文件并添加相关代码
  1. public class AppBarDto
  2. {
  3.     public string Key { get; set; }
  4.     /// <summary>
  5.     /// 标题
  6.     /// </summary>
  7.     public string Title { get; init; }
  8.     /// <summary>
  9.     /// 图标
  10.     /// </summary>
  11.     public string? Icon { get; set; }
  12.     /// <summary>
  13.     /// 路由
  14.     /// </summary>
  15.     public string Href { get; init; }
  16.     public AppBarDto(string title, string href, string? icon = null)
  17.     {
  18.         Title = title;
  19.         Icon = icon;
  20.         Href = href;
  21.         Key = Guid.NewGuid().ToString("N");
  22.     }
  23. }
复制代码

  • 添加相关页面,在Pages文件夹下,分别创建Index.razor,Feature.razor,Friend.razor,PersonalCenter.razor
文件相关代码:
Index.razor
  1. @page "/"
  2. <h3>Index</h3>
复制代码
Feature.razor
  1. @page "/feature"
  2. <h3>Feature</h3>
复制代码
Friend.razor
  1. @page "/friend"
  2. <h3>Friend</h3>
复制代码
PersonalCenter.razor
  1. @page "/personal-center"
  2. <h3>PersonalCenter</h3>
复制代码

  • 修改AppBar.razor代码
  1.     @ChildContent
  2. @*这里也可以是其他组件的Tab,其实只是记录当前的导航的数据*@
  3. <MTabs Centered
  4.        BackgroundColor="indigo"
  5.        ShowArrows="false"
  6.        Value="selectModel.Key"
  7.        Dark>
  8.     @foreach (var i in AppBars)
  9.     {
  10.         <MTab Value="i.Key" OnClick="()=>GoHref(i)">
  11.             @if (!string.IsNullOrEmpty(i.Icon))
  12.             {
  13.                 <MIcon Dark>@i.Icon</MIcon>
  14.             }
  15.             @i.Title
  16.         </MTab>
  17.     }
  18. </MTabs>
复制代码

  • 创建AppBar.razor.cs 添加以下代码
  1. public partial class AppBar
  2. {
  3.     #region Inject
  4.     [Inject]
  5.     public required NavigationManager NavigationManager { get; set; }
  6.     #endregion
  7.     private readonly List<AppBarDto> AppBars = new();
  8.     [Parameter]
  9.     public RenderFragment ChildContent { get; set; }
  10.     private AppBarDto selectModel;
  11.     private string Class { get; set; }
  12.     protected override void OnInitialized()
  13.     {
  14.         AppBars.Add(new AppBarDto("首页", "/", "home"));
  15.         AppBars.Add(new AppBarDto("好友", "/personal-center", "mdi-account-group-outline"));
  16.         AppBars.Add(new AppBarDto("功能", "/feature", "mdi-wrench"));
  17.         AppBars.Add(new AppBarDto("个人中心", "/personal-center", "mdi-badge-account-alert"));
  18.         // 默认选择的导航标签
  19.         selectModel = AppBars[0];
  20.         base.OnInitialized();
  21.     }
  22.     /// <summary>
  23.     /// 导航栏跳转
  24.     /// </summary>
  25.     /// <param name="appBar"></param>
  26.     private void GoHref(AppBarDto appBar)
  27.     {
  28.         // 防止重复点击
  29.         if(appBar == selectModel)
  30.         {
  31.             return;
  32.         }
  33.         // 当点击导航的索引大于现在导航时启动滑动效果
  34.         if(AppBars.IndexOf(appBar) > AppBars.IndexOf(selectModel))
  35.         {
  36.             Class = "slide-out-left";
  37.             Task.Run(async () =>
  38.             {
  39.                 // 由于特效时间为0.5s 这里是等待特效完成
  40.                 await Task.Delay(450);
  41.                 NavigationManager.NavigateTo(selectModel.Href);
  42.                 Class = "slide-in-right";
  43.                 _ = InvokeAsync(StateHasChanged);
  44.             });
  45.         }
  46.         // 当点击导航的索引小于现在导航时启动滑动效果
  47.         else if (AppBars.IndexOf(appBar) < AppBars.IndexOf(selectModel))
  48.         {
  49.             Class = "slide-out-right";
  50.             Task.Run(async () =>
  51.             {
  52.                 // 由于特效时间为0.5s 这里是等待特效完成
  53.                 await Task.Delay(450);
  54.                 NavigationManager.NavigateTo(selectModel.Href);
  55.                 Class = "slide-in-left";
  56.                 _ = InvokeAsync(StateHasChanged);
  57.             });
  58.         }
  59.         selectModel = appBar;
  60.         NavigationManager.NavigateTo(appBar.Href);
  61.     }
  62.     /// <summary>
  63.     /// 开始X坐标
  64.     /// </summary>
  65.     private double _startX;
  66.     #region 移动端滑动处理
  67.     /// <summary>
  68.     /// 记录开始坐标
  69.     /// </summary>
  70.     /// <param name="args"></param>
  71.     private void TouchStart(TouchEventArgs args)
  72.     {
  73.         var touch = args.ChangedTouches[0];
  74.         _startX = touch.ScreenX;
  75.     }
  76.     private void TouchEnd(TouchEventArgs args)
  77.     {
  78.         var touch = args.ChangedTouches[0];
  79.         Switchover((decimal)touch.ScreenX);
  80.     }
  81.     #endregion
  82.     #region PC滑动处理
  83.     /// <summary>
  84.     /// 记录开始坐标
  85.     /// </summary>
  86.     /// <param name="args"></param>
  87.     private void Mousedown(MouseEventArgs args)
  88.     {
  89.         _startX = args.ScreenX;
  90.     }
  91.     private void Mouseup(MouseEventArgs args)
  92.     {
  93.         Switchover((decimal)args.ScreenX);
  94.     }
  95.     #endregion
  96.     private void Switchover(decimal screenX)
  97.     {
  98.         var index = AppBars.IndexOf(selectModel);
  99.         // 限制过度滑动
  100.         if (index == AppBars.Count || index > AppBars.Count)
  101.         {
  102.             return;
  103.         }
  104.         // 设置滑动最大位限制,达到这个限制才滑动生效
  105.         var size = 200;
  106.         // 需要滑动200才切换 如果开始坐标x大于 当前结束的x坐标往右边切换tab
  107.         if ((decimal)_startX - size > screenX)
  108.         {
  109.             // 如果右边往左边滑动 当前索引是当前最大数量的话不需要切换
  110.             if (index == AppBars.Count - 1)
  111.             {
  112.                 return;
  113.             }
  114.             selectModel = AppBars[index + 1];
  115.             Class = "slide-out-left";
  116.             Task.Run(async () =>
  117.             {
  118.                 // 由于特效时间为0.5s 这里是等待特效完成
  119.                 await Task.Delay(450);
  120.                 NavigationManager.NavigateTo(selectModel.Href);
  121.                 Class = "slide-in-right";
  122.                 _ = InvokeAsync(StateHasChanged);
  123.             });
  124.         }
  125.         else if ((decimal)_startX + size < screenX)
  126.         {
  127.             // 如果左边往右边滑动 当前索引是0的话不需要切换
  128.             if (index == 0)
  129.             {
  130.                 return;
  131.             }
  132.             selectModel = AppBars[index - 1];
  133.             Class = "slide-out-right";
  134.             Task.Run(async () =>
  135.             {
  136.                 // 由于特效时间为0.5s 这里是等待特效完成
  137.                 await Task.Delay(450);
  138.                 NavigationManager.NavigateTo(selectModel.Href);
  139.                 Class = "slide-in-left";
  140.                 _ = InvokeAsync(StateHasChanged);
  141.             });
  142.         }
  143.     }
  144. }
复制代码
运行效果:


一个热爱学习的token
qq交流群:737776595
微信交流群:


来源:https://www.cnblogs.com/hejiale010426/archive/2023/01/23/17064872.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具