美文网首页
SwiftUI封装(一)——SwiftUI自定义TabBar定义

SwiftUI封装(一)——SwiftUI自定义TabBar定义

作者: 俺不是大佬儿 | 来源:发表于2023-12-20 14:54 被阅读0次

先看可实现的效果

效果 中心异形 常规+滑块 滑块效果

最近在做SwiftUI的项目需要自己造一些轮子,把实战案例分享给大家共同学习

SwiftUI中提供了TabView控件可以快速创建带有TabBar菜单的应用,但是有些复杂的效果就不能满足需求了,扒拉了半天找到的参考案例都是收费的,本着程序员不为难程序员的态度选择了自定义这条路

思路

  1. 定义枚举类型LKTabBarStyle实现不同样式的选择;
  2. 根据SwiftUI中ZStack的特性定义TabBar容器LKTabBarContainerView;
  3. 根据LKTabBarStyle枚举实现对应的TabBar利用ZStack将用户的自定义页面与LKTabBarView按层级进行添加;
  4. 为方便调用使用PreferenceKey将自定义在菜单页面中的BarItem传递到TabBar容器LKTabBarContainerView对LKTabBarView进行布局实现LKTabBarStyle的样式效果;
  5. 利用动画实现TabBarItem的丝滑切换效果。

具体实现

1.自定义TabBar样式枚举支持 normal:常规型、sliderLump:滑动色块、colorLump:常规色块、shaped:中心异形(仿墨迹天气的样式)

///TabBar样式枚举
enum LKTabBarStyle {
    
    //normal:常规型、sliderLump:滑动色块、colorLump:常规色块、shaped:中心异形
    
    ///normal:常规型
    case normal
    ///滑动色块
    case sliderLump
    ///常规色块
    case colorLump
    ///中心异形(仿墨迹天气)
    case shaped
}

2.定义需要的TabBar菜单item,采用枚举的方式将选中未选中时的状态资源一并进行定义,方便布局时调用(资源的定义使用扩展嵌套struct的结构,用于空间命名调用)

//
//  LKTabBarItem.swift
//  SwiftUITabBar
//
//  Created by 李棒棒 on 2023/12/9.
//

import SwiftUI

enum LKTabBarItem: Hashable {
    
    case home,//首页
         news,//资讯
         media,//自媒体
         message,//消息
         mine,//个人中心
         publish//发布
    
    ///标题
    var title: String {
        switch self {
        case .home:
            return String.Btn.home
        case .news:
            return String.Btn.news
        case .media:
            return String.Btn.media
        case .message:
            return String.Btn.message
        case .mine:
            return String.Btn.main
        case .publish:
            return ""
        }
    }
    
    
    ///未选中时图标
    var normalIcon: String {
        switch self {
        case .home:
            return String.Img.tab_home
        case .news:
            return String.Img.tab_news
        case .media:
            return String.Img.tab_media
        case .message:
            return String.Img.tab_message
        case .mine:
            return String.Img.tab_mine
        case .publish:
            return ""
        }
    }
    
    ///选中时图标
    var seIcon: String {
        switch self {
        case .home:
            return String.Img.tab_home_selected
        case .news:
            return String.Img.tab_news_selected
        case .media:
            return String.Img.tab_media_selected
        case .message:
            return String.Img.tab_message_selected
        case .mine:
            return String.Img.tab_mine_selected
        case .publish:
            return ""
        }
    }
    
    //未选中时的字体
    var norFont:Font {
        return Font.system(size: 14,weight: .regular)
    }
    
    //已选中时的字体
    var seFont:Font {
        return Font.system(size: 16,weight: .bold)
    }
    //未选中时的字体颜色
    var norTitleColor:Color {
        return Color.gray
    }
    //已选中时的字体颜色
    var seTitleColor:Color {
        return Color.blue
    }
    
    ///item的滑动色块配色
    var lumpColor: Color {
        switch self {
        case .home:
            return Color.blue
        case .news:
            return Color.red
        case .media:
            return Color.yellow
        case .message:
            return Color.green
        case .mine:
            return Color.cyan
        case .publish:
            return Color.clear
        }
    }
}

3.根据枚举样式对LKTabBarView进行布局

//
//  LKTabBarView.swift
//  SwiftUITabBar
//
//  Created by 李棒棒 on 2023/12/9.
//

import SwiftUI

struct LKTabBarView: View {
    
    let tabItems:[LKTabBarItem]
    let style:LKTabBarStyle
    @Binding var selectedItem:LKTabBarItem
    @Namespace private var namespace
    //动画过渡
    @State var animationSelectedItem:LKTabBarItem
    
    @State private var showingAlert = false
    
    var body: some View {
        
        switch style {
            
        case .normal:
            
            normalTabBar
                .onChange(of: selectedItem) { oldValue, newValue in
                    withAnimation(.easeInOut) {
                        animationSelectedItem = newValue
                    }
                }
            
        case .sliderLump:
            
            sliderLumpTabBar
                .onChange(of: selectedItem) { oldValue, newValue in
                    withAnimation(.easeInOut) {
                        animationSelectedItem = newValue
                    }
                }
            
        case .colorLump:
            
            colorLumpTabBar
                .onChange(of: selectedItem) { oldValue, newValue in
                    withAnimation(.easeInOut) {
                        animationSelectedItem = newValue
                    }
                }
            
        case .shaped:
            
            shapedTabBar
                .ignoresSafeArea()
                .onChange(of: selectedItem) { oldValue, newValue in
                    withAnimation(.easeInOut) {
                        animationSelectedItem = newValue
                    }
                }
        }
    }
}

调用示例

通过PreferenceKey的定义,调用方法就比较的灵活便捷,同时支持二级页面嵌套TabBar使用

//
//  SwiftUITabBarApp.swift
//  SwiftUITabBar
//
//  Created by 李棒棒 on 2023/12/9.
//

import SwiftUI

@main
struct SwiftUITabBarApp: App {
    
    @State private var tabSelected: LKTabBarItem = .home
    
    var body: some Scene {
        
        WindowGroup {
            
            LKTabBarContainerView(selectedItem: $tabSelected,
                                  tabBarStyle: .shaped) {
                //首页
                HomeView().tabBarItem(.home, selectedItem: $tabSelected)
                    .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height)
                    .background(Color.gray.opacity(0.6))
                    .ignoresSafeArea()
                
                //资讯
                ContentView().tabBarItem(.news, selectedItem: $tabSelected)
                    .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height)
                    .ignoresSafeArea()
                
                //自媒体
                Color.red.tabBarItem(.publish, selectedItem: $tabSelected)
                    .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height)
                    .ignoresSafeArea()
                
                //消息
                ContentView().tabBarItem(.message, selectedItem: $tabSelected)
                    .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height)
                    .ignoresSafeArea()
                //我的
                ContentView().tabBarItem(.mine, selectedItem: $tabSelected)
                    .frame(maxWidth: UIScreen.main.bounds.width, maxHeight: UIScreen.main.bounds.height)
                    .ignoresSafeArea()
            }
        }
    }
}

LKTabBar-SwiftUI

大功告成,欢迎大家交流学习 点点关注开发不迷路

相关文章

网友评论

      本文标题:SwiftUI封装(一)——SwiftUI自定义TabBar定义

      本文链接:https://www.haomeiwen.com/subject/pavbgdtx.html