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

是否有小伙伴在使用tab的时候想进行滑动切换Tab?

并且有滑动左出左进,右出右进的效果 ,本文将讲解怎么在Blazor中去通过滑动切换Tab

本文中的UI组件使用的是MASA Blazor,您也可以是其他的UI框架,这个并不影响实际的运行效果,本文案例是兼容PC和Android的,演示效果是android中执行的,在PC中执行效果依然有效(亲测)

首先安装MASA Blazor 根据 MASA Blazor安装MASA Blazor

准备工作

  1. 创建 AppBar.razor文件

  2. 修改MainLayout.razor文件代码

@inherits LayoutComponentBase  <MApp>     <AppBar>         <div class="body">             @Body         </div>     </AppBar> </MApp>  <style> .body {     /*设置内容高度 需要减去导航栏的高度*/     height: calc(100vh - 48px);     max-height: calc(100vh - 48px); } </style> 
  1. 创建 AppBar.razor.css 文件并且添加相关代码 ,以下代码是为了实现切换的时候有一个出入效果,具体代码案例来自Animista - On-Demand CSS Animations Library

     /*左边滑动出*/ .slide-out-left {     -webkit-animation: slide-out-left 0.5s;     animation: slide-out-left 0.5s; }  /*右边滑动出*/ .slide-out-right {     -webkit-animation: slide-out-right 0.5s;     animation: slide-out-right 0.5s; }  /*右边滑动进*/ .slide-in-right {     -webkit-animation: slide-in-right 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;     animation: slide-in-right 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both; }  /*左边滑动进*/ .slide-in-left {     -webkit-animation: slide-in-left 0.5s;     animation: slide-in-left 0.5s; }  @-webkit-keyframes slide-out-left {     0% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     }      100% {         -webkit-transform: translateX(-1000px);         transform: translateX(-1000px);         opacity: 0;     } }  @keyframes slide-out-left {     0% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     }      100% {         -webkit-transform: translateX(-1000px);         transform: translateX(-1000px);         opacity: 0;     } }   @-webkit-keyframes slide-out-right {     0% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     }      100% {         -webkit-transform: translateX(1000px);         transform: translateX(1000px);         opacity: 0;     } }  @keyframes slide-out-right {     0% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     }      100% {         -webkit-transform: translateX(1000px);         transform: translateX(1000px);         opacity: 0;     } }   @-webkit-keyframes slide-in-left {     0% {         -webkit-transform: translateX(-1000px);         transform: translateX(-1000px);         opacity: 0;     }      100% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     } }  @keyframes slide-in-left {     0% {         -webkit-transform: translateX(-1000px);         transform: translateX(-1000px);         opacity: 0;     }      100% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     } } @-webkit-keyframes slide-in-right {     0% {         -webkit-transform: translateX(1000px);         transform: translateX(1000px);         opacity: 0;     }      100% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     } }  @keyframes slide-in-right {     0% {         -webkit-transform: translateX(1000px);         transform: translateX(1000px);         opacity: 0;     }      100% {         -webkit-transform: translateX(0);         transform: translateX(0);         opacity: 1;     } }  
  2. 创建AppBar的模型用于动态添加导航栏, 创建AppBarDto.cs文件并添加相关代码

public class AppBarDto {     public string Key { get; set; }      /// <summary>     /// 标题     /// </summary>     public string Title { get; init; }      /// <summary>     /// 图标     /// </summary>     public string? Icon { get; set; }      /// <summary>     /// 路由     /// </summary>     public string Href { get; init; }      public AppBarDto(string title, string href, string? icon = null)     {         Title = title;         Icon = icon;         Href = href;         Key = Guid.NewGuid().ToString("N");     } } 
  1. 添加相关页面,在Pages文件夹下,分别创建Index.razor,Feature.razor,Friend.razor,PersonalCenter.razor

文件相关代码:
Index.razor

@page "/" <h3>Index</h3> 

Feature.razor

@page "/feature" <h3>Feature</h3> 

Friend.razor

@page "/friend" <h3>Friend</h3> 

PersonalCenter.razor

@page "/personal-center" <h3>PersonalCenter</h3> 
  1. 修改AppBar.razor代码
  <div class="@Class" @ontouchstart="TouchStart" @ontouchend="TouchEnd" @onmousedown="Mousedown" @onmouseup="Mouseup" style="height: 100%">     @ChildContent </div>   @*这里也可以是其他组件的Tab,其实只是记录当前的导航的数据*@ <MTabs Centered        BackgroundColor="indigo"        ShowArrows="false"        Value="selectModel.Key"        Dark>     @foreach (var i in AppBars)     {         <MTab Value="i.Key" OnClick="()=>GoHref(i)">             @if (!string.IsNullOrEmpty(i.Icon))             {                 <MIcon Dark>@i.Icon</MIcon>             }             @i.Title         </MTab>     } </MTabs>  
  1. 创建AppBar.razor.cs 添加以下代码
 public partial class AppBar {     #region Inject      [Inject]     public required NavigationManager NavigationManager { get; set; }      #endregion      private readonly List<AppBarDto> AppBars = new();      [Parameter]     public RenderFragment ChildContent { get; set; }      private AppBarDto selectModel;      private string Class { get; set; }      protected override void OnInitialized()     {         AppBars.Add(new AppBarDto("首页", "/", "home"));         AppBars.Add(new AppBarDto("好友", "/personal-center", "mdi-account-group-outline"));         AppBars.Add(new AppBarDto("功能", "/feature", "mdi-wrench"));         AppBars.Add(new AppBarDto("个人中心", "/personal-center", "mdi-badge-account-alert"));          // 默认选择的导航标签         selectModel = AppBars[0];          base.OnInitialized();     }      /// <summary>     /// 导航栏跳转     /// </summary>     /// <param name="appBar"></param>     private void GoHref(AppBarDto appBar)     {         // 防止重复点击         if(appBar == selectModel)         {             return;         }          // 当点击导航的索引大于现在导航时启动滑动效果         if(AppBars.IndexOf(appBar) > AppBars.IndexOf(selectModel))         {             Class = "slide-out-left";             Task.Run(async () =>             {                 // 由于特效时间为0.5s 这里是等待特效完成                 await Task.Delay(450);                 NavigationManager.NavigateTo(selectModel.Href);                 Class = "slide-in-right";                 _ = InvokeAsync(StateHasChanged);             });         }         // 当点击导航的索引小于现在导航时启动滑动效果         else if (AppBars.IndexOf(appBar) < AppBars.IndexOf(selectModel))         {             Class = "slide-out-right";             Task.Run(async () =>             {                 // 由于特效时间为0.5s 这里是等待特效完成                 await Task.Delay(450);                 NavigationManager.NavigateTo(selectModel.Href);                 Class = "slide-in-left";                 _ = InvokeAsync(StateHasChanged);             });         }         selectModel = appBar;         NavigationManager.NavigateTo(appBar.Href);     }       /// <summary>     /// 开始X坐标     /// </summary>     private double _startX;       #region 移动端滑动处理      /// <summary>     /// 记录开始坐标     /// </summary>     /// <param name="args"></param>     private void TouchStart(TouchEventArgs args)     {         var touch = args.ChangedTouches[0];         _startX = touch.ScreenX;     }      private void TouchEnd(TouchEventArgs args)     {         var touch = args.ChangedTouches[0];         Switchover((decimal)touch.ScreenX);     }      #endregion      #region PC滑动处理      /// <summary>     /// 记录开始坐标     /// </summary>     /// <param name="args"></param>     private void Mousedown(MouseEventArgs args)     {         _startX = args.ScreenX;     }      private void Mouseup(MouseEventArgs args)     {         Switchover((decimal)args.ScreenX);     }      #endregion      private void Switchover(decimal screenX)     {         var index = AppBars.IndexOf(selectModel);         // 限制过度滑动         if (index == AppBars.Count || index > AppBars.Count)         {             return;         }          // 设置滑动最大位限制,达到这个限制才滑动生效         var size = 200;          // 需要滑动200才切换 如果开始坐标x大于 当前结束的x坐标往右边切换tab         if ((decimal)_startX - size > screenX)         {             // 如果右边往左边滑动 当前索引是当前最大数量的话不需要切换             if (index == AppBars.Count - 1)             {                 return;             }             selectModel = AppBars[index + 1];             Class = "slide-out-left";              Task.Run(async () =>             {                 // 由于特效时间为0.5s 这里是等待特效完成                 await Task.Delay(450);                 NavigationManager.NavigateTo(selectModel.Href);                 Class = "slide-in-right";                 _ = InvokeAsync(StateHasChanged);             });         }         else if ((decimal)_startX + size < screenX)         {             // 如果左边往右边滑动 当前索引是0的话不需要切换             if (index == 0)             {                 return;             }             selectModel = AppBars[index - 1];             Class = "slide-out-right";             Task.Run(async () =>             {                 // 由于特效时间为0.5s 这里是等待特效完成                 await Task.Delay(450);                 NavigationManager.NavigateTo(selectModel.Href);                 Class = "slide-in-left";                 _ = InvokeAsync(StateHasChanged);             });         }     } }  

运行效果:

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

一个热爱学习的token

发表评论

相关文章