• Stars
    star
    274
  • Rank 145,166 (Top 3 %)
  • Language
    Swift
  • License
    MIT License
  • Created almost 2 years ago
  • Updated 9 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Customizable media picker written with SwiftUI

Media Picker

SwiftUI library for a customizable media picker.


We are a development agency building phenomenal apps.

SPM Compatible Cocoapods Compatible Carthage Compatible License: MIT

Features

  • Photo and video picker
  • Single and multiple selection
  • Full-screen view
  • Live photo preview & capture
  • Full customization

MediaPicker vs PhotosPicker

  • The iOS 16 PhotosPicker only provides you with a button, while this library gives you the whole view, meaning you can build it into you own screens and customize it as you see fit.
  • PhotosPicker only lets you pick photos from the library - no camera.
  • MediaPicker provides a default looking library picker, with ability to manage albums, and also a camera view to take photos/video

!SPM Renaming!

SPM package is now called ExyteMediaPicker instead of MediaPicker, sorry for any inconveniences.

Usage

  1. Add a binding Bool to control the picker presentation state.
  2. Add Media array to save selection ([Media]).
  3. Initialize the media picker and present it however you like - for example, using the .sheet modifier
.sheet(isPresented: $showMediaPicker) {
    MediaPicker(
        isPresented: $showMediaPicker,
        onChange: { medias = $0 }
    )
}

Media model

The lbrary will return an array of Media structs for you to use as you see fit. It has the following fields and methods (all the methods use async/await API):

  • type - .image or .video
  • duration - nil for .image
  • getURL() - returns URL to media (automatically stores in temporary directory if needed)
  • getThumbnailURL() - returns URL to media's thumbnail (for image just returns the image itself)
  • getData() - returns media's Data representation
  • getThumbnailData() - returns media's thumbnail Data representation

Modes

This library lets you use both photo library and camera

Photos grid

Default photos grid screen has a standard header which contains the 'Done' and 'Cancel' buttons, and a simple switcher between Photos and Albums. Use it for a basic out-of-the box picker (see default picker in example project for an usage example). This can be customized (see "Init - view builders" section)

Camera

After making one photo, you see a preview of it and a little plus icon, by tapping it you return back to camera mode and can continue making as many photos as you like. Press "Done" once you're finished and you will be able to scroll through all the photos you've taken before confirming you'd like to use them. This preview screen of photos you've taken can also be customized (see "Init - view builders" section)

Init - required parameters

isPresented - a binding to determine whether the picker should be displayed or not
onChange - a closure that returns the selected media every time the selection changes

Init - optional view builders

You can pass two view builders in order to add your own buttons and other elements to media picker screens. First screen you can customize is default photos grid view. Pass albumSelectionBuilder closure like this to replace the standard one with your own view:

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

albumSelectionBuilder gives you two views to work with:

  • defaultHeaderView - a default looking header with photos/albums mode switcher
  • albumSelectionView - the photos grid itself

The second customizable screen is the one you see after taking a photo. Pass cameraSelectionBuilder like this:

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 gives you these parameters:

  • addMoreClosure - you can call this closure on tap of your own button, it will work same as default plus icon on camera selection preview screen
  • cancelClosure - show confirmation and return to photos grid screen if confirmed
  • cameraSelectionView - swipable camera photos preview collection itself

You can pass one, both or none of these when creating your MediaPicker. (see the custom picker in the example project for usage example)

Available modifiers

showLiveCameraCell - show live camera feed cell in the top left corner of the gallery grid
mediaSelectionType - limit displayed media type: .photo, .video or both
mediaSelectionStyle - a way to display selected/unselected media state: a counter or a simple checkmark
mediaSelectionLimit - the maximum selection quantity allowed, 'nil' for unlimited selection

Available modifiers - filtering

applyFilter((Media) async -> Media?) - pass a closure to apply to each of medias individually. Closures's return type is Media?: return Media the closure gives to you if you want it to be displayed on photo grid, or nil if you want to exclude it. The code you apply to each media can be asyncronous (using async/await syntactics, check out FilterMediaPicker in example project) applyFilter(([Media]) async -> [Media]) - same but apply the closure to whole medias array. Can also be used for reodering.

Available modifiers - screen rotation

If your app restricts screen rotation, you can skip this section.

We recommend locking orientation for MediaPicker, because default rotation animations don't look good on the camera screen. At the moment SwiftUI doesn't provide a way of locking screen orientation, so the library has an initializer with an orientationHandler parameter - a closure that is called when you enter/leave the camera screen inside MediaPicker. In this closure you need to use AppDelegate to lock/unlock the rotation - see example project for implementation.

Available modifiers: managing albums

albums - a list of user's albums (like in Photos app), if you want to display them differently than showingDefaultHeader does.
pickerMode - set this if you don't plan to use the default header. Available options are:
* .photos - displays the default photos grid
* .albums - displays a list of albums with one preview photo for each
* .album(Album) - displays one album
* .camera - shows a fullscreen cover camera sheet * .cameraSelection - displays a preview of photos taken with camera (see the custom picker in the example project for implementation)

Available modifiers: theme

mediaPickerTheme - color settings. Example usage (see MediaPickerTheme for all available settings):

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

Here is an example of how you can customize colors and elements to create a custom looking picker:

Examples

To try out the MediaPicker examples:

  • Clone the repo https://github.com/exyte/MediaPicker.git
  • Open Examples/Examples.xcworkspace in the Xcode
  • Run it!

Installation

Swift Package Manager

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

CocoaPods

pod 'ExyteMediaPicker'

Carthage

github "Exyte/MediaPicker"

Requirements

  • iOS 15+
  • Xcode 13+

Our other open source SwiftUI libraries

PopupView - Toasts and popups library
Grid - The most powerful Grid container
ScalingHeaderScrollView - A scroll view with a sticky header which shrinks as you scroll
AnimatedTabBar - A tabbar with number of preset animations
Chat - Chat UI framework with fully customizable message cells, input view, and a built-in media picker
ConcentricOnboarding - Animated onboarding flow
FloatingButton - Floating button menu
ActivityIndicatorView - A number of animated loading indicators
ProgressIndicatorView - A number of animated progress indicators
SVGView - SVG parser
LiquidSwipe - Liquid navigation animation

More Repositories

1

Macaw

Powerful and easy-to-use vector graphics Swift library with SVG support
Swift
5,964
star
2

PopupView

Toasts and popups library written with SwiftUI
Swift
2,976
star
3

Grid

The most powerful Grid container missed in SwiftUI
Swift
1,682
star
4

ARTetris

Augmented Reality Tetris made with ARKit and SceneKit
Swift
1,532
star
5

ActivityIndicatorView

A number of preset loading indicators created with SwiftUI
Swift
1,276
star
6

ConcentricOnboarding

SwiftUI library for a walkthrough or onboarding flow with tap actions
Swift
1,242
star
7

FloatingButton

Easily customizable floating button menu created with SwiftUI
Swift
1,010
star
8

ScalingHeaderScrollView

A scroll view with a sticky header which shrinks as you scroll. Written with SwiftUI.
Swift
890
star
9

ReadabilityKit

Preview extractor for news, articles and full-texts in Swift
Swift
829
star
10

fan-menu

Menu with a circular layout based on Macaw
Swift
726
star
11

Chat

A SwiftUI Chat UI framework with fully customizable message cells and a built-in media picker
Swift
561
star
12

SVGView

SVG parser and renderer written in SwiftUI
Swift
550
star
13

LiquidSwipe

Example of using SwiftUI to create a beautiful Liquid Swipe control
Swift
478
star
14

Macaw-Examples

Various usages of the Macaw library
Swift
354
star
15

AnimatedTabBar

A tabbar with a number of preset animations written in pure SwiftUI
Swift
284
star
16

AndroidAnimatedNavigationBar

AnimatedNavigationBar is a navigation bar with a number of preset animations written in Jetpack Compose
Kotlin
263
star
17

replicating

Kotlin
245
star
18

ProgressIndicatorView

An iOS progress indicator view library written in SwiftUI
Swift
200
star
19

ComposeMultiplatformDribbbleAudio

A repo for the Dribbble Replicating Compose Multiplatform article
Kotlin
71
star
20

android-waves-progressbar

A depth gauge progress bar, inspired by Apple Watch dive widget.
Kotlin
41
star
21

clean-swift-article

Swift
37
star
22

sweet.eclipse

Sweet Eclipse
HTML
33
star
23

gaster

Ethereum transactions stats for your smart contracts
JavaScript
30
star
24

FlagAndCountryCode

A country code and flag icon provider library for iOS apps
Swift
28
star
25

android-replicating

Replicating complex UI using Jetpack Compose
Kotlin
23
star
26

ShapedBackgroundAndroid

Repo for the instagram-like shaped background on Android
Kotlin
23
star
27

wwdc2020-tutorials

Swift
21
star
28

AnimatedGradient

Swift
18
star
29

core-haptics-example

Swift
13
star
30

homebrew-formulae

Ruby
1
star
31

openai-assistants-api

Swift
1
star