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

blazor,如何,实现,类似,tab,切换 · 浏览次数 : 548

小编点评

# AppBarDto ```csharp public class AppBarDto { public string Key { get; set; } public string Title { get; init; } public string Icon { get; set; } public string Href { get; init; } } ``` # AppBar ```csharp public partial class AppBar { #region Inject [Inject] public required NavigationManager NavigationManager { get; set; } #endregion private readonly List AppBars = new(); [Parameter] public RenderFragment ChildContent { get; set; } private double _startX; #region 移动端滑动处理 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 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); }); } }} } ``` #排版 ```csharp // 由于特效时间为0.5s 这里是等待特效完成 await Task.Delay(450); ```

正文

是否有小伙伴在使用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);
            });
        }
    }
}

运行效果:

一个热爱学习的token

与Blazor如何实现类似于微信的Tab切换?相似的内容:

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

是否有小伙伴在使用tab的时候想进行滑动切换Tab? 并且有滑动左出左进,右出右进的效果 ,本文将讲解怎么在Blazor中去通过滑动切换Tab 本文中的UI组件使用的是MASA Blazor,您也可以是其他的UI框架,这个并不影响实际的运行效果,本文案例是兼容PC和Android的,演示效果是and

Blazor实战——Known框架单表增删改查导

本章介绍学习增、删、改、查、导功能如何实现,下面以商品资料作为示例,该业务栏位如下: > 类型、编码、名称、规格、单位、库存下限、库存上限、备注 ## 1. 前后端共用 ### 1.1. 创建实体类 - 在KIMS项目Entities文件夹下创建KmGoods实体类 - 该类继承EntityBase

如何实现在react现有项目中嵌入Blazor?

如何实现在react现有项目中嵌入Blazor? 目前官方只提供了angular和react俩种示例所以本教程只讲react教程 思路讲解: 首先在现有react项目中我们可能某些组件是在Blazor中完成,但是我们没办法找到怎么在react中轻量级使用blazor组件,可能会有人会使用iframe

Blazor实战——Known框架多表增删改查

# 多表增删改查示例 本章介绍学习多张表增、删、改、查功能如何实现,下面以销货出库单作为示例,该业务栏位如下: > **销货出库单栏位** > - 销货单号、销货日期、状态、客户、备注 > > **销货出库单明细栏位** > - 商品编码、商品名称、规格型号、数量、单位、单价、金额 该示例适用于出货

如何取消Blazor Server烦人的重新连接?

# 如何取消Blazor Server烦人的重新连接? 相信很多Blazor的用户在开发内部系统上基本上都选择速度更快,加载更快的`Blazor Server`模式。 但是`Blazor Server`由于是`SignalR`实现,所以在访问的时候会建立`WebSocket`通道,用于`js`交互和

如何将现有的`Blazor`项目的主题切换写的更好看?

# 如何将现有的`Blazor`项目的主题切换写的更好看? 在现有的系统当中,我们的主题切换会比较生硬,下面我们将基于Masa Blazor实现好看的扩散主题切换的样式效果。 ## 安装MASA.Template ```sh dotnet new install MASA.Template ```

关于Unity 如何与Blazor Server结合

关于Unity 如何与Blazor Server结合 一、介绍 最近工作中有`Unity`与`Blazor Server`结合的需求,在网上找了一圈,发现这方面的资料比较少,特此写下这篇记录一下自己的实现过程,希望可以帮到有需要的朋友。(下方多图预警) OS Version : windows 11

Blazor实战——Known框架功能配置

本章介绍功能模块菜单、按钮、列表栏位如何配置。 ### 配置菜单模块 - 运行框架,进入“系统管理-模块管理”页面,点击左侧上级模块,点击【新增】按钮 ![输入图片说明](https://foruda.gitee.com/images/1684223573492708502/c0d8e5a8_143

如何使用MASA.Blazor

MASA.Blazor 是什么? 基于Material Design设计和BlazorComponent的交互能力提供标准的基础组件库。提供如布局、弹框标准、Loading、全局异常处理等标准场景的预置组件。从更多实际场景出发,满足更多用户和场景的需求,缩短开发周期,提高开发效率,并提供一整套Web

Blazor实战——Known框架快速开始

Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行。 开源地址: https://gitee.com/known/Known ## 1. 安装项目模板并创建新项目 - 打开命令行输入如下命令安装和创建。 ```bash -- 安装模板 dotnet