An interactive iOS image viewer that does it all: double tap to zoom, flick to dismiss, et cetera.

Overview

DO NOT USE. "I AM SUPER DUPER CEREAL, YOU GUYS."

This repository is no longer under active development. I think it's probably still safe to use on iOS 7 through 9, but your mileage may vary. I may someday do a thorough rewrite in Swift, taking into account newer API features, etc. ~ Jared

JTSImageViewController

An interactive iOS image viewer that does it all: double tap to zoom, flick to dismiss, et cetera.

Pull Requests

Pull requests are welcome, but should be submitted on the dev branch. Exceptions will be made for critical bug fixes.

What Does it Do?

JTSImageViewController is like a "light box" for iOS. It's similar to image viewers you may have seen in apps like Twitter, Tweetbot, and others. It presents an image in a full-screen interactive view. Users can pan and zoom, and use Tweetbot-style dynamic gestures to dismiss it with a fun flick.

Screenshot

How Does it Work?

Usage is pretty simple, though there are some cool options and delegate methods if you need them. Here's what your simplest implementation might look like:

- (void)someBigImageButtonTapped:(id)sender {
    
    // Create image info
    JTSImageInfo *imageInfo = [[JTSImageInfo alloc] init];
    imageInfo.image = YOUR_SOURCE_IMAGE;
    imageInfo.referenceRect = self.bigImageButton.frame;
    imageInfo.referenceView = self.bigImageButton.superview;
    
    // Setup view controller
    JTSImageViewController *imageViewer = [[JTSImageViewController alloc]
                                           initWithImageInfo:imageInfo
                                           mode:JTSImageViewControllerMode_Image
                                           backgroundStyle:JTSImageViewControllerBackgroundOption_Scaled];
    
    // Present the view controller.
    [imageViewer showFromViewController:self transition:JTSImageViewControllerTransition_FromOriginalPosition];
}

That's it.

Extras and Options

  • Image Downloads: If you don't have the source image already, just use the imageURL property when setting up the JTSImageInfo instance. JTSImageViewController will handle downloading the image for you.

  • Background Styles: Choose between a scaled-and-dimmed style or a scaled-dimmed-and-blurred background style. The latter is like the one used in Tweetbot.

  • Alt-Text Mode: Need to show the alt text for an image? JTSImageViewController includes an alternate mode that shows a full-screen, centered text view using the same style as the image mode.

  • Handle Long-Presses: Implement an interactionsDelegate to respond to long presses on the image, or to temporarily disable user interactions (comes in handy if you show an overlay that could cause gesture conflict).

License

MIT License, see the included file.

Comments
  • Background flickers w/ iPhone 6 when clicking image

    Background flickers w/ iPhone 6 when clicking image

    It looks like the size of cloned UIView gets shifted (the title moves down then flickers away).. Is it possible to just have a complete black overlay then have the image do the animation expand into its placeholder to avoid showing the existing UIView?

    This is preventing me from using this tool in production.

    opened by civilordergone 6
  • Jerking motion on initial transition on iPhone 6 and 6+

    Jerking motion on initial transition on iPhone 6 and 6+

    When presenting images, such as the one in the sample project, on the iPhone 6 and 6+ simulators, the main view seems to jerk before presenting the image. It enlarges a little, then shrinks back, then continues with the correct animation.

    opened by edekhayser 5
  • Support for video?

    Support for video?

    Any plans or interest in using this controller for video as well as images? If so, I would be happy to work on it (I just don't want to put the work in if you don't have any interest of supporting video at all).

    opened by rosskimes 5
  • blurredSnapshotFromParentmostViewController return type

    blurredSnapshotFromParentmostViewController return type

    opened by dkhamsing 5
  • Background Rotation

    Background Rotation

    I noticed that the view controller that is beneath the image does not rotate. This means if you display an image, then rotate the screen, then dismiss the image. There is an abrupt change in orientation after the animation finishes. Is there a way for the view beneath the image to rotate also?

    opened by Hackmodford 4
  • Flickering (zoom / dismiss conflict) + make fick to dismiss an option

    Flickering (zoom / dismiss conflict) + make fick to dismiss an option

    On a real device, when I want to zoom the image, it flickers (actually really fast resizes/moves), whenever my zoom gesture is fast. I have to zoom very gently to prevent this. Once I manage to zoom it's ok, this issue appears for zoomLevel == 1 and fast gesture.

    On simulator it happens if I firstly drag it with mouse, then press option, to begin zooming, when I firstly click option, than mouse, it's ok. So probably it recognizes the beginning of zooming as dragging.

    Here's a gif:

    (this is iOS 7.1 with JTS 1.3, although I did notice this issue a month ago, when I firstly tried to use it) The example works fine, the problem is with presenting it from my tableViewCell.

    I tried with different combinations of referenceRect/View and modifying code in library (messing with _flags and zoomLevel), but with no luck.

    What I do is add a UITapGestureRecognizer to my UIImageView in a UITableViewCell. In tap handler I present JTS:

    
    //Note: This happens in UITableViewCell subclass
    
    -(void)awakeFromNib
    {
    self.photoImageView.userInteractionEnabled = YES;
        UITapGestureRecognizer *imageTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
        [self.photoImageView addGestureRecognizer:imageTapGesture];
    }
    
    -(void)handleTap:(UITapGestureRecognizer *)gesture
    {
        CGPoint location = [gesture locationInView:[gesture.view superview]];
        if(!CGRectContainsPoint(self.photoImageView.frame, location))
            return;
    
        JTSImageInfo *imageInfo = [JTSImageInfo new];
        imageInfo.image = self.photoImageView.image;
        imageInfo.referenceRect = self.photoImageView.frame;
        imageInfo.referenceView = self.parentVC.view;
    
        JTSImageViewController *imageViewer = [[JTSImageViewController alloc] initWithImageInfo:imageInfo mode:JTSImageViewControllerMode_Image backgroundStyle:JTSImageViewControllerBackgroundStyle_ScaledDimmedBlurred];
    
        imageViewer.interactionsDelegate = self; //thought I could block flickering this way, but tapping also has been disabled
        imageViewer.dismissalDelegate = self;
    
        [imageViewer showFromViewController:self.parentVC transition:JTSImageViewControllerTransition_FromOffscreen]; //transition has no impact on this issue
    }
    
    opened by andrew-frank 4
  • Blurry Image when Image is smaller than image view

    Blurry Image when Image is smaller than image view

    I may be missing something, but I have a problem when an image is smaller than the image view it is being displayed in. This is mostly an issue on the iPad. The image is stretched to fill the entire image view instead of just being displayed smaller (and at a suitable resolution) within the image view. I feel like I must be missing something, but if not, this may be a bug, or at least an intended effect?

    opened by inPhilly 3
  • iOS 8 contentOffset

    iOS 8 contentOffset

    Hi,

    First of all thank you for all the amazing work on this project.

    The issue I have is very minuscule. In iOS 8 while using a UITableView, I present the JTSImageViewController and upon dismissal the table view scrolls (not animated) to the top, that is to say the contentOffset is lost.

    I read through most of the code in JTSImageViewController.m and it is not at fault. Apparently it's the default behaviour to reset the contentOffset after returning from a modal view controller. I have tried automaticallyAdjustsScrollViewInsets = NO and using a UITableView inside a UIViewController instead of a UITableViewController but no luck. I've also tried setting the contentOffset back after the dismissal but it flashes.

    It seems setting the modal presentation style of JTSImageViewController to UIModalPresentationOverFullScreen fixes the issue (since it doesn't remove the hierarchy below it and retains the scroll position I think). As this enum is new to iOS 8 I am going to assume that it's an iOS 8 only issue (since if it wasn't there would be more issues about it).

    Any thoughts? Has anyone else experienced this? If so should I make a pull request for this simple change?

    if ([[[UIDevice currentDevice] systemVersion] compare:@"8.0" options:NSNumericSearch] != NSOrderedAscending) {
        self.modalPresentationStyle = UIModalPresentationOverFullScreen;
    }
    
    opened by Shayanzadeh 3
  • Carthage Support

    Carthage Support

    Hi Jared,

    Thanks for writing this component. I added a dynamic framework so that people who use Carthage can use this too. I have also added completion parameter to the -showFromViewController:transition: as I needed this too.

    Let me know what you think

    opened by lbrndnr 3
  • CocoaPods Support

    CocoaPods Support

    Adds a podspec file so the library can be used as a CocoaPod.

    If I'm missing anything important in the file, let me know. I tried to keep it fairly simple, and it worked well on test integrations.

    opened by bcapps 3
  • iOS 9 setStatusBarHidden is deprecated

    iOS 9 setStatusBarHidden is deprecated

    under iOS 9, this warning appears several times during compilation:
    'setStatusBarHidden:withAnimation:' is deprecated: first deprecated in iOS 9.0 - Use -[UIViewController prefersStatusBarHidden]

    It's not difficult to fix per se (the correct approach has been around since iOS 7), but because it doesn't appear that iOS 9 provides a means of animating the status bar fade--you've either got it or not--changing this will affect the logic a bit.

    opened by mbachrach 2
  • Property of mutable type 'NSMutableDictionary' has 'copy' attribute; an immutable object will be stored instead

    Property of mutable type 'NSMutableDictionary' has 'copy' attribute; an immutable object will be stored instead

    When Analyzing my project, I get that issue : /MyProject/Pods/JTSImageViewController/Source/JTSImageInfo.h:23:1: Property of mutable type 'NSMutableDictionary' has 'copy' attribute; an immutable object will be stored instead

    screen shot 2017-04-14 at 6 25 17 pm

    opened by Uliori 0
  • Hint mentioning alternatives

    Hint mentioning alternatives

    Hey @jaredsinclair .

    Maybe you could add a note with links to alternatives like NYTPhotoViewer or IDMPhotoBrowser for example. It took me a while to find some. So maybe that would help people who once used your controller starting new projects.

    Best, Roman.

    opened by r-dent 1
  • Landscape mode

    Landscape mode

    The landscape orientation is not working with my App when I change the orientation of the device. Is the auto rotate feature supported or not ?

    I can't see any informations about this.

    opened by petretRaf 0
Releases(1.5.1)
  • 1.5.1(Sep 14, 2015)

  • 1.5(Mar 13, 2015)

  • 1.4(Nov 3, 2014)

    • Support for iOS 8 & Bug Fixes – This includes a fix for the various "flicker" bugs that can occur under certain cases (showing the viewer, double-tapping to zoom, etc.). Special note on iOS 8 and autorotation: since iOS 8 changes the way autorotation events are propagated to view controllers, a landscape-to-landscape rotation (or a portrait-to-portrait rotation) will look a little strange on iOS 8. This is because neither viewWillTransitionToSize: nor willAnimateToInterfaceOrientation: are called for these edge cases. A sad oversight on Apple's part.
    • API Change: Background Options – The background style has been changed to background options to make it clearer which combinations are available: blurred, scaled, both, or neither. The "dimming" is a separate option controlled via a background color (which remains unchanged).
    • Animation Delegate – Added a new delegate property and a new < JTSImageViewControllerAnimationDelegate> protocol, which gives you an easy way to add or remove custom interface elements overlaid on top of the image viewer without resorting to subclassing or forking. Great for custom sharing or cancel buttons.
    • UI Improvements – JTSImageInfo has an option for referenceContentMode and referenceCornerRadius, making your animations looks 10x better when expanding from source views that use those parameters. Check out the sample app for an extreme example. Anti-aliasing is also enabled on the image view inside the viewer.
    • UIMenuController – You can optionally enable a UIMenuController. Adds the ability to copy the image.
    • Miscellaneous – Add support for iPhone 6 and 6 Plus to the sample app. Make the use of dot notation fully consistent throughout.

    Thanks to all the contributors for their pull requests in this release!

    Source code(tar.gz)
    Source code(zip)
  • 1.2(Jun 3, 2014)

    • Bug Fixes – Fixed minor UI bugs: landscape orientation when using the blurred background mode, improperly tinted status bars, etc.
    • Touch Improvements – Tweaked the dynamics when dragging and flicking away images. It was too tight in previous versions.
    • API Changes – Moved some options that had previously been readwrite properties into delegate methods, and added one or two new options along the way. For example, you can set a custom background color for the image view (for images you'd rather not have clear backgrounds).
    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Apr 27, 2014)

    • Bug Fixes – Fixes a bug with animated GIFs that could lead to a crash, and a bug that causes animation glitches for some views on some devices.
    Source code(tar.gz)
    Source code(zip)
  • 1.1(Apr 27, 2014)

    • iPad Support – Adds support for iPad, as well as all four interface orientations (portrait upside down had been excluded from earlier versions).
    • Bug Fixes – Adds fixes for bugs with UINavigationBar and UIToolBar showing up as black on some devices.
    • Flick-to-Dismiss Improvements – Tweaked the UIDynamics configuration to feel more natural on devices with a variety of screen sizes.
    • New Options – Expose two new options: the blur radius used when blurring the background, and the opacity of the shadow view that dims the background.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Apr 10, 2014)

Owner
Jared Sinclair
Designer and developer of apps like ‘sodes, Unread, Riposte, and others • iOS at @bignerdranch • Previously at @blackpixel • Oldsmobile man
Jared Sinclair
Firefox for iOS, branch works with Xcode 12.5.1, Swift 5.4.2 and supports iOS 11.4 and above.

Firefox for iOS Download on the App Store. This branch (main) This branch works with Xcode 12.5.1, Swift 5.4.2 and supports iOS 11.4 and above. Please

Mozilla Mobile 11.2k Jan 7, 2023
An iOS widget-based HN reader

Benuse, an iOS widget-based HN reader Why did you build this app? There already exist some great native Hacker News clients for iOS. I would recommend

Jordan Mann 8 Jul 21, 2022
iOS app to record how much things cost using various data persistence implementations.

how-much iOS app to record how much things cost using various data persistence implementations. The basic data unit is an item, a simple dictionary: {

null 22 Aug 15, 2022
The (second) best iOS app for GitHub.

GitHawk is the second-highest rated iOS app for GitHub. Features 0️⃣ Inbox Zero your notifications ?? Comment even faster than on GitHub desktop ?? Th

GitHawk 2.8k Dec 23, 2022
WordPress for iOS - Official repository

WordPress for iOS Build Instructions Please refer to the sections below for more detailed information. The instructions assume the work is performed f

WordPress Mobile 3.4k Jan 9, 2023
Fully open source text editor for iOS written in Swift.

Edhita Fully open source text editor for iOS written in Swift. http://edhita.bornneet.com/ What Edhita means? Edhita (Romaji) == エディタ (Katakana) == Ed

Tatsuya Tobioka 1.2k Jan 7, 2023
iOS app for 5calls.org

5Calls iOS App This is the repository for the iOS app for 5Calls.org. Requirements Xcode 10.2.1 iOS 10.2 Getting Started Install the dependencies: bun

5 Calls 129 Dec 25, 2022
iOS Money Manager for Board Games

Warning! This is an old project. It does contain a lot of bad code I wrote when I started out with iOS Development. I am not mantaining this project a

Richard 164 Sep 27, 2022
Development of the TUM Campus App for iOS devices - for and from students at Technical University of Munich.

Tum Campus App - An Unofficial Guide Through University Life The TUM Campus App (TCA) is an open source project, developed by volunteers and available

TUM Developers 93 Dec 16, 2022
Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus.

VPN On Turning on a VPN is always a painful experience on an iOS device due to the deep nested menus. This App installs a Today Widget into Notificati

Lex Tang 4.4k Dec 26, 2022
Lightweight iOS Photo Blur App

Blurry Blurry is the go-to image blurring tool to help you apply beautiful blurs for your photos. It is perfect for creating wallpapers, backgrounds,

Andy 17 Nov 22, 2022
Kickstarter for iOS. Bring new ideas to life, anywhere.

Welcome to Kickstarter’s open source iOS app! Come on in, take your shoes off, stay a while—explore how Kickstarter’s native squad has built and conti

Kickstarter 8k Jan 6, 2023
Alfresco iOS App - Alfresco is the open platform for business-critical content management and collaboration.

Welcome to the Alfresco iOS App Alfresco is the open platform for business-critical content management and collaboration. Alfresco Mobile was designed

Alfresco Software 42 Sep 26, 2022
📱 Nextcloud iOS app

Nextcloud iOS app Check out https://nextcloud.com and follow us on twitter.com/nextclouders or twitter.com/NextcloudiOS How to contribute If you want

Nextcloud 1.4k Dec 30, 2022
Kommunicate iOS SDK for customer support

Kommunicate iOS Chat SDK for Customer Support An Open Source iOS Live Chat SDK for Customer Support Overview Kommunicate provides open source live cha

Kommunicate 39 Dec 14, 2022
Simple sample of using the VIP (Clean Swift) architecture for iOS

MyAnimeList Simple sample of using the VIP (Clean Swift) architecture for iOS. ViewController: controls the event handling, view life cycle and displa

null 24 Oct 12, 2022
📱 Wire for iOS (iPhone and iPad)

Wire™ This repository is part of the source code of Wire. You can find more information at wire.com or by contacting [email protected]. You can find

Wire Swiss GmbH 3.2k Jan 8, 2023
Swift audio synthesis, processing, & analysis platform for iOS, macOS and tvOS

AudioKit AudioKit is an audio synthesis, processing, and analysis platform for iOS, macOS (including Catalyst), and tvOS. Installation To add AudioKit

AudioKit 9.5k Jan 5, 2023
🍣Making Recipes iOS app

Recipes App ❤️ Support my apps ❤️ Push Hero - pure Swift native macOS application to test push notifications PastePal - Pasteboard, note and shortcut

Khoa 88 Nov 22, 2022