MinimizableView 2.4.2

MinimizableView 2.4.2

Dominik Butz 维护。



  • dominikbutz

MinimizableView (iOS 13+ / iPadOS)

Version License Platform

MinimizableView 是一个简单的 SwiftUI 视图,用于 iOS 和 iPadOS,可以像 Spotify 或 Apple Music 应用中的迷你播放器一样最小化。目前,SwiftUI 似乎不支持自定义模态对话框(具有与 sheet、actionSheet、alert、popover 等不同的动画/状态),因此这个简单的视图可以被视为一种解决方案。它只能从 iOS 13.0 使用,因为 SwiftUI 不在以前的 iOS 版本中使用。

版本 2.0 中的破坏性更改。请查看以下版本历史中的详细信息

特别感谢 Kavsoft (此处查看) - 我使用了示例中部分 MiniPlayer 内容。尽管如此,框架是我自己的创新。

示例项目

此仓库仅包含 Swift 包,不包含示例代码。请在此处下载示例项目 这里。您需要通过 CocoaPods 或 Swift 包管理器添加 MinimizableView 包(见下文 - 安装)。

特性

  • 创建您自己的内容、背景和紧凑视图。紧凑视图是可选的 - 如果在初始化器中设置,将出现在最小化状态下。

  • 通过更改 MinimizableViewHandler 的设置属性,您可以自定义以下属性

    • minimizedHeight
    • overrideHeight(如果您想设置与几何大小高度不同的高度)
    • lateralMargin
    • edgesIgnoringSafeAreas

    查看示例以获取详细信息。

安装

推荐使用Swift Package Manager (SPM) 或 cocoapods 进行安装。

SPM:选择您的项目(不是目标),然后选择Swift Packages选项卡。点击+并输入MinimizableView - SPM应在GitHub上找到此包。

Cocoapods

platform :ios, '14.0'

target '[project name]' do pod 'MinimizableView' end

查看下面的版本历史记录以获取当前版本。

确保在您使用MinimizableView或MinimizableViewHandler的每个文件中导入MinimizableView。

import MinimizableView

使用方法

查看以下示例。此存储库只包含Swift包,没有示例代码。请在此处下载示例项目链接

MinimizableView example

代码示例:内容视图(您的主视图)

简单地将.minimizableView修饰符附加到您的主视图,例如TabView。要触发显示、关闭、最小化和展开,您需要调用MinimizableViewHandler的相关功能:present()、dismiss()、minimize()和expand()。建议在每次使用tapGesture切换展开状态时,在minimizableViewHandler上调用toggleExpansionState()。

如果您不需要紧凑视图,只需传入EmptyView。在MinimizableView体中检查compactView是否为EmptyView,然后不显示它。如果没有紧凑视图,最小化状态时内容顶部将显示在屏幕底部。使用minimizableViewHandler作为EnvironmentObject在您的内容视图中 - 例如,在最小化属性更改时一次性移除和插入特定的子视图。

您还需要将minimizableViewHandler作为环境对象附加到MinimizableView。

struct RootView: View {

    @ObservedObject var miniHandler: MinimizableViewHandler = MinimizableViewHandler()
    @State var selectedTabIndex: Int = 0
    
    @Namespace var namespace

    
    var body: some View {
        GeometryReader { proxy in

                TabView(selection: self.$selectedTabIndex) {
                    
                    Button(action: {
                        print(proxy.safeAreaInsets.bottom)
                        self.miniHandler.present()
                        
                    }) { TranslucentTextButtonView(title: "Launch Minimizable View", foregroundColor: .green, backgroundColor: .green)}.disabled(self.miniHandler.isPresented)
                        
                        .tabItem {
                            Image(systemName: "chevron.up.square.fill")
                            Text("Main View")
                    }.tag(0)
                    
                    Text("More stuff").tabItem {
                        Image(systemName: "dot.square.fill")
                        Text("2nd View")
                    }.tag(1)
                    
                    ListView(availableWidth: proxy.size.width)
                        .tabItem {
                        Image(systemName: "square.split.2x1.fill")
                        Text("List View")
                    }.tag(2)
                    
                    
                }.background(Color(.secondarySystemFill))
                .statusBar(hidden: self.miniHandler.isPresented && self.miniHandler.isMinimized == false)
                // if you want a separate compactView, replace EmptyView() by some custom view. It will appear above the top part of your contentView, so make sure the compact view has a background colour. 
                .minimizableView(content: {ContentExample(animationNamespaceId: self.namespace)}, compactView: {EmptyView()}, backgroundView: {
                    VStack(spacing: 0){
                        
                        BlurView(style: .systemChromeMaterial)
                        if self.miniHandler.isMinimized {
                            Divider()
                        }
                    }.cornerRadius(self.miniHandler.isMinimized ? 0 : 20)
                    .onTapGesture(perform: {
                        if self.miniHandler.isMinimized {
                            self.miniHandler.expand(
                                ////alternatively, override the default animation. self.miniHandler.expand(animation: Animation)
                        }
                    })
                }, dragOnChanged: { (value) in
                    self.dragOnChanged(value: value)
                }, dragOnEnded: { (value) in
                    self.dragOnEnded(value: value)
                }, geometry: proxy, settings: MiniSettings(minimizedHeight: 80))
                .environmentObject(self.miniHandler)
     
        }
    
        //
    }
    
    
    func dragOnChanged(value: DragGesture.Value) {
        if self.miniHandler.isMinimized == false  { // expanded state
            if value.translation.height > 0 {
                self.miniHandler.draggedOffsetY = value.translation.height

            }
        } else {// minimized state
            
            if value.translation.height < 0 {
                self.miniHandler.draggedOffsetY = value.translation.height

            }
        }
    }
    
    func dragOnEnded(value: DragGesture.Value) {
        if self.miniHandler.isMinimized == false  {
            if value.translation.height > 60 {
                  self.miniHandler.minimize()
           
            }
            
        } else {
            if value.translation.height < -60 {
                  self.miniHandler.expand()
    
              }
            
        }
       withAnimation(.spring()) {
            self.miniHandler.draggedOffsetY = 0
       }

    }
}

   

变更日志

版本 2.2

iOS 15 更新:由于 miniView 上的动画修饰符可能影响内容视图子视图的动画,从而导致奇怪的行为,因此已从设置中移除了动画。现在,miniView 处理函数 present()、expand()、minimize() 和 toggleExpansionState() 包含了可以覆盖的动画参数(默认为 .spring())。

版本 2.1.1

iOS 15 更新:修复了在最小化状态下向上拖动 miniView 可能导致无限循环的bug。

版本 2.1

在设置中添加了 edgesIgnoringSafeArea。默认值是 [.bottom, .top]。如果需要,请确保为内容添加顶部填充。

版本 2.0.2

bug 修复:在最小化状态下且键盘出现时,miniView 现在将在键盘隐藏后正确地消失和重新出现。

版本 2.0.1

将 minimizedBottomMargin 移至 miniView 初始化器。这在例如根据屏幕方向改变底部边距时非常有用。

版本 2.0

破坏性更改。以下参数需要在初始化器中设置

  • backgroundView
  • onDragChanged 和 onDragEnded
  • settings(可选)

版本 1.2.1

错误修复:当处于最小化状态时,如果键盘显示(而不是悬浮在键盘上方),迷你视图将消失。

版本 1.2

compactView 参数不能为 nil。如果您不想有单独的 compactView,请传递 EmptyView。从 minimizableView body(contentView 和 compactView)中删除过渡效果。相反,将过渡修饰符附加到您的 contentView 和 compactView 实现上。有关详细信息,请查看示例存储库。MiniSettings 结构体的参数现在可以在初始化器中直接设置。

版本 1.1.1

动画略有改进。

版本 1.1

内容视图仅在迷你视图呈现时出现。其他一些小改进。

版本 1.0

初始化器改动:内容视图和紧凑视图现在需要插入到闭包中,不再需要转换为 AnyView!错误修复:在没有物理主按钮的设备上(例如 iPhone 11 max),最小视图在隐藏状态下不再显示顶部。额外功能:便利修改器(见示例)。

版本 0.3.2

错误修复:onMinimization 现在按预期调用。仅在 isPresented 为 true 时调用 onExpansion。

版本 0.3.1

当可最小化视图的呈现状态为 false 时,在 offsetY 中添加安全边距 - 这修复了屏幕底部阴影可见性的错误。

版本 0.3

通过 VerticalDragGesture 修改器的收缩/扩展现在只在拖动结束时触发。VerticalDragGesture 视图修改器现在是框架内部的 - 相反,使用 修改器函数 verticalDragGesture(translationHeightTriggerValue: CGFloat)

版本 0.2.1

更新 frameHeight 和 offsetY 函数以允许在向上拖动时展开最小化框架。

版本 0.2

首次公开发行。

作者

[email protected]

许可协议

MinimizableView 在 MIT 许可协议下可用。有关更多信息,请参阅 LICENSE 文件。