Blazor实现微信的Tab切换功能
token 人气:0是否有小伙伴在使用tab的时候想进行滑动切换Tab?
并且有滑动左出左进,右出右进的效果 ,本文将讲解怎么在Blazor
中去通过滑动切换Tab
本文中的UI组件使用的是MASA Blazor
,您也可以是其他的UI框架,这个并不影响实际的运行效果,本文案例是兼容PC和Android的,演示效果是android中执行的,在PC中执行效果依然有效(亲测)
首先安装MASA Blazor
根据 MASA Blazor安装MASA Blazor
准备工作
- 创建
AppBar.razor
文件 - 修改
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>
创建 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; } }
创建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"); } }
添加相关页面,在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> @page "/personal-center" <h3>PersonalCenter</h3>
修改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>
创建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); }); } } }
运行效果:
加载全部内容