媒体选择器

用于自定义媒体选择器的 SwiftUI 库。

SPM Compatible Cocoapods Compatible Carthage Compatible License: MIT

特性

MediaPicker vs PhotosPicker

!SPM 重命名!

SPM 包现在名为 ExyteMediaPicker 而不是 MediaPicker,对于由此带来的不便,我们深表歉意。

用法

  1. 添加一个绑定 Bool 来控制选择器的显示状态。
  2. 添加 Media 数组以保存选择 ([Media])。
  3. 初始化媒体选择器并以您喜欢的方式显示它 - 例如,使用 .sheet 修饰符
.sheet(isPresented: $showMediaPicker) {
    MediaPicker(
        isPresented: $showMediaPicker,
        onChange: { medias = $0 }
    )
}

媒体模型

该库将返回一个 Media 结构数组供您随意使用。它具有以下字段和方法(所有方法都使用 async/await API)

模式

这个库允许你同时使用照片库和相机

照片网格

默认照片网格屏幕具有一个标准标题,其中包含“完成”和“取消”按钮,以及一个照片和相册之间的简单切换器。 使用它作为基本的开箱即用选择器(有关用法示例,请参见示例项目中的默认选择器)。 这可以自定义(请参见“初始化 - 视图构建器”部分)

相机

拍摄一张照片后,您会看到它的预览和一个小的加号图标,点击它您会返回到相机模式,并可以继续拍摄任意数量的照片。 完成后按“完成”,您将能够滚动浏览您拍摄的所有照片,然后再确认您要使用它们。 您拍摄的这些照片的预览屏幕也可以自定义(请参见“初始化 - 视图构建器”部分)

初始化 - 必需参数

isPresented - 用于确定是否应显示选择器的绑定
onChange - 一个闭包,每次选择更改时都会返回所选媒体

初始化 - 可选视图构建器

您可以传递 1-3 个视图构建器,以便将您自己的按钮和其他元素添加到媒体选择器屏幕。 创建 MediaPicker 时,您可以传递全部、部分或不传递这些(有关用法示例,请参见示例项目中的自定义选择器)。 您可以自定义的第一个屏幕是默认照片网格视图。 传递 albumSelectionBuilder 闭包,如下所示,以用您自己的视图替换标准视图

MediaPicker(
    isPresented: $isPresented,
    onChange: { selectedMedia = $0 },
    albumSelectionBuilder: { defaultHeaderView, albumSelectionView, isInFullscreen in
        VStack {
            if !isInFullscreen {
                defaultHeaderView
            }
            albumSelectionView
            Spacer()
            footerView
        }
        .background(Color.black)
    }
)

albumSelectionBuilder 为您提供两个要使用的视图

第二个可自定义的屏幕是拍摄照片后看到的屏幕。 传递 cameraSelectionBuilder,如下所示

MediaPicker(
    isPresented: $isPresented,
    onChange: { selectedMedia = $0 },
    cameraSelectionBuilder: { addMoreClosure, cancelClosure, cameraSelectionView in
        VStack {
            HStack {
                Spacer()
                Button("Done", action: { isPresented = false })
            }
            cameraSelectionView
            HStack {
                Button("Cancel", action: cancelClosure)
                Spacer()
                Button(action: addMoreClosure) {
                    Text("Take more photos")
                }
            }
        }
    }
)

cameraSelectionBuilder 为您提供以下参数

最后一个是实时相机屏幕

MediaPicker(
    isPresented: $isPresented,
    onChange: { selectedMedia = $0 },
    cameraViewBuilder: { cameraSheetView, cancelClosure, showPreviewClosure, takePhotoClosure, startVideoCaptureClosure, stopVideoCaptureClosure, toggleFlash, flipCamera in
        cameraSheetView
            .overlay(alignment: .topLeading) {
                HStack {
                    Button("Cancel") { cancelClosure() }
                        .foregroundColor(Color("CustomPurple"))
                    Spacer()
                    Button("Done") { showPreviewClosure() }
                        .foregroundColor(Color("CustomPurple"))
                }
                .padding()
            }
            .overlay(alignment: .bottom) {
                HStack {
                    Button("Take photo") { takePhotoClosure() }
                        .greenButtonStyle()
                    Button(videoIsBeingRecorded ? "Stop video capture" : "Capture video") {
                        videoIsBeingRecorded ? stopVideoCaptureClosure() : startVideoCaptureClosure()
                        videoIsBeingRecorded.toggle()
                    }
                    .greenButtonStyle()
                }
                .padding()
            }
    }
)

cameraViewBuilder 实时相机拍摄视图和许多闭包,您可以随意使用

可用修饰符

showLiveCameraCell - 在图库网格的左上角显示实时相机源单元格
mediaSelectionType - 限制显示的媒体类型:.photo、.video 或两者
mediaSelectionStyle - 显示所选/未选媒体状态的方式:计数器或简单的复选标记
mediaSelectionLimit - 允许的最大选择数量,对于无限制选择为“nil”
showFullscreenPreview - 如果为 true - 点击媒体会打开全屏预览,如果为 false - 点击图像会立即选择此图像并关闭选择器

可用修饰符 - 过滤

applyFilter((Media) async -> Media?) - 传递一个闭包,以单独应用于每个媒体。 Closures's 返回类型是 Media?:如果您希望它显示在照片网格上,则返回闭包提供给您的 Media,如果您想排除它,则返回 nil。 您应用于每个媒体的代码可以是异步的(使用 async/await 语法,查看示例项目中的 FilterMediaPickerapplyFilter(([Media]) async -> [Media]) - 相同,但将闭包应用于整个媒体数组。 也可以用于重新排序。

可用修饰符 - 屏幕旋转

如果您的应用限制屏幕旋转,则可以跳过本节。

我们建议锁定 MediaPicker 的方向,因为默认的旋转动画在相机屏幕上看起来不好。 目前,SwiftUI 不提供锁定屏幕方向的方法,因此该库有一个带有 orientationHandler 参数的初始化程序 - 当您进入/离开 MediaPicker 内的相机屏幕时,会调用一个闭包。 在此闭包中,您需要使用 AppDelegate 来锁定/解锁旋转 - 有关实现,请参见示例项目。

可用修饰符:管理相册

albums - 用户相册的列表(如在 Photos 应用程序中),如果您希望以不同于 showingDefaultHeader 的方式显示它们。
pickerMode - 如果您不打算使用默认标题,请设置此项。 可用选项是
* .photos - 显示默认照片网格
* .albums - 显示相册列表,每个相册都有一张预览照片
* .album(Album) - 显示一个相册
* .camera - 显示全屏封面相机表 * .cameraSelection - 显示使用相机拍摄的照片的预览(有关实现,请参见示例项目中的自定义选择器)

可用修饰符:主题

mediaPickerTheme - 颜色设置。 用法示例(有关所有可用设置,请参见 MediaPickerTheme

MediaPicker(...)
  .mediaPickerTheme(
      main: .init(
          background: .black
      ),
      selection: .init(
          emptyTint: .white,
          emptyBackground: .black.opacity(0.25),
          selectedTint: Color("CustomPurple")
      )
  )

这是一个您可以自定义颜色和元素以创建自定义外观选择器的示例

例子

要尝试 MediaPicker 示例

安装

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/exyte/ExyteMediaPicker.git")
]

CocoaPods

pod 'ExyteMediaPicker'

Carthage

github "Exyte/MediaPicker"

要求

我们的其他开源 SwiftUI 库

PopupView - Toasts 和 popups 库
Grid - 最强大的 Grid 容器
ScalingHeaderScrollView - 带有粘性标题的滚动视图,滚动时会缩小
AnimatedTabBar - 带有多种预设动画的选项卡栏
Chat - 聊天 UI 框架,具有完全可自定义的消息单元格、输入视图和内置的媒体选择器
OpenAI Wrapper lib for OpenAI REST API
AnimatedGradient - 动画线性渐变
ConcentricOnboarding - 动画入职流程
FloatingButton - 浮动按钮菜单
ActivityIndicatorView - 一些动画加载指示器
ProgressIndicatorView - 一些动画进度指示器
FlagAndCountryCode - 每个国家/地区的电话代码和标志
SVGView - SVG 解析器
LiquidSwipe - 流动导航动画