How to make Image page viewer for images swift ios - ios

I wanna display a couple of images from the assets folders, into my application. so I wanna make a page view.
First, images will be inside collection view, then on click, the image will be full screen. Then the user can slide between the images by swiping right and left as shown in the following photo:
I found this tutorial:
PhotosGalleryApp
Updated:
I have this in my storyboard:
Now in GaleryViewController I show the images in cells
when user click on it, I open the image in fullscreen in PhotoViewController.
PhotoViewController.swift :
import UIKit
class PhotoViewController: UIViewController{
#IBOutlet weak var imageView: UIImageView!
var index: Int = 0;
var pageViewController : UIPageViewController?
#IBAction func btnCancelClicked(sender: AnyObject) {
self.navigationController?.popToRootViewControllerAnimated(true);
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
initUI();
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(animated: Bool) {
self.navigationController?.hidesBarsOnTap = true;
self.navigationController?.hidesBarsOnSwipe = true;
displayPhoto()
}
func initUI() -> Void {
// pageViewController = UIPageViewController(transitionStyle: .Scroll, navigationOrientation: .Horizontal, options: nil)
// pageViewController!.dataSource = self
}
func displayPhoto() {
self.imageView.image = UIImage(named: Constants.Statics.images[index])
}
I have the images in static structure so i can access them anywhere:
class Constants {
struct Statics {
static let images = ["1.jpg","2.jpg","3.jpg","4.jpg","5.jpg","7.jpg","8.jpg"]
}
}
My problem is: I want to add the feature that allow me to swipe between pictures inside the PhotoViewController.
Any ideas?
Thank you

You can do one of the following two things to achieve your goal :
Make a modal segue of the cell to the next UICollectionViewController where the images are showed in full screen, and in the prepareForSegue pass all the data (images) you need to show and where exactly you are in this moment (indexOfImage).
You can watch the didSelectItemAtIndexPath and then pass all the data to one instance of the next UICollectionViewController you want to show with the presentViewController func.
But it's very important that in the next UICollectionViewController you have set pageEnabled = true in code or in the Interface Builder (I though is much easy to do.)
UPDATE:
Very good tutorials on how to make a slide show of images using an UIScrollView or an UICollectionView :
How To Use UIScrollView to Scroll and Zoom Content
Creating a Paged Photo Gallery With a UICollectionView
I hope this help you.

Related

Swift Detect UISlider image tap

So I have a UISlider that looks like this:
Image here
It is set up like this, so the images are not UIImageView's, but images in the UISlider:
Image 2 here
I want to add a function so when the user press the image on left side, it runs one function, and when the user presses the image on the right side, it runs another function. Is this even possible?
Here's how you can do it. Please read the comments carefully.
import UIKit
class ViewController: UIViewController {
// This is linked to your storyboard layout
#IBOutlet weak var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Add a tap gesture recognizer to the slider
slider.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(sliderTapped(_:))))
}
#objc private func sliderTapped(_ tapRecognizer: UITapGestureRecognizer) {
let location = tapRecognizer.location(in: slider)
// UISlider can tell you min/max value image frames
// CAUTION: Use images those are big enough to be easy tap targets
// In my case, I used images of size 30x30
let minImageRect = slider.minimumValueImageRect(forBounds: slider.bounds)
let maxImageRect = slider.maximumValueImageRect(forBounds: slider.bounds)
// Now you can check which image out of min/max was tapped
if minImageRect.contains(location) {
print("Min Image Tapped")
} else if maxImageRect.contains(location) {
print("Max Image Tapped")
}
}
}

How to show FullScreenSlideshowViewController on ViewDidLoad

I am new to iOS development, I have created android app where app gets sets of images (sometimes over 100 images) from urls and loads into imageView with zoomEnabled Inside ViewPager.
Now I want to create same app for iOS, I have found this lib ImageSliderShow. Problem with this is it shows fullscreen ONLY when user did tap on selected image. I have been struggling to presentFullScreenController on viewDidLoad with no lock.
I only want image to be shown in fullScreen, example:
Select Category A From CategoryVC -> Loads ImageSlideVC, gets set of images from server, show in FullScreenView.
How can i achieve this? Adding this:
slideshow.presentFullScreenController(from: self)
on viewDidLoad didn't work:
#IBOutlet var slideshow: ImageSlideshow!
let kingfisherSource = [KingfisherSource(urlString: "https://images.unsplash.com/photo-1447746249824-4be4e1b76d66?w=1080")!,
KingfisherSource(urlString: "https://images.unsplash.com/photo-1447746249824-4be4e1b76d66?w=1080")!,
KingfisherSource(urlString: "https://images.unsplash.com/photo-1463595373836-6e0b0a8ee322?w=1080")!]
override func viewDidLoad() {
super.viewDidLoad()
slideshow.setImageInputs(kingfisherSource)
slideshow.presentFullScreenController(from: self)
}
I dont get any error, output is same as before (shows slideshow in smallview with no zoom)
Please help
EDIT
by doing in viewDidAppear, after split second view is loaded its loads into fullscreen. First its smallview then shows in fullscreen. I think i have to do something inside setImageInputs
this is what its looks like :
open func setImageInputs(_ inputs: [InputSource]) {
self.images = inputs
self.pageControl.numberOfPages = inputs.count
// in circular mode we add dummy first and last image to enable smooth scrolling
if circular && images.count > 1 {
var scImages = [InputSource]()
if let last = images.last {
scImages.append(last)
}
scImages += images
if let first = images.first {
scImages.append(first)
}
self.scrollViewImages = scImages
} else {
self.scrollViewImages = images
}
reloadScrollView()
layoutScrollView()
layoutPageControl()
setTimerIfNeeded()
}
try to do it in viewDidAppear
#IBOutlet var slideshow: ImageSlideshow!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
slideshow.setImageInputs(kingfisherSource)
slideshow.presentFullScreenController(from: self)
}
Presenting viewController in ViewDidLoad is a bad practice.

How do I make my ImageView scrollable without affecting the rest of the view?

How Do I add multipleImages for the top part and have it scrollable without moving the rest of the content? Also, how do I have the little dots at the bottom to indicate which image I'm on? My code for the image is down below.
import SDWebImage
#IBOutlet weak var headerImage: UIImageView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let imageUrl:NSURL? = NSURL(string: headerPhoto!)
if let url = imageUrl {
headerImage.sd_setImage(with: url as URL!)
}
}
You are looking for something called image slide show or image slider.
Instead of creating them by yourself which requires lots of effort, here is a GitHub library that is easy to use.
Basicly the way slider works is that it is a horizontal scroll view and each cell in the scroll view is an image so that you can scroll. Then, put a fixed page index element on the bottom of the scroll view to tell you which image you are currently at.
To use it, create a UIView in your viewcontroller and set both class and module to ImageSlideshow. Then connect it to your ViewController.swift as IBOutLet.
Then create an array of image urls
let alamofireSource = [AlamofireSource(urlString: "imgurl1")!, AlamofireSource(urlString: "imgurl2")!, AlamofireSource(urlString: "imgurl3")!]
And finally in your viewDidLoad() function:
override func viewDidLoad() {
super.viewDidLoad()
slideshow.backgroundColor = UIColor.white
slideshow.slideshowInterval = 5.0
slideshow.pageControlPosition = PageControlPosition.underScrollView
slideshow.pageControl.currentPageIndicatorTintColor = UIColor.lightGray
slideshow.pageControl.pageIndicatorTintColor = UIColor.black
slideshow.contentScaleMode = UIViewContentMode.scaleAspectFill
slideshow.setImageInputs(alamofireSource)
}

How to add property to UIButton?

thanks for all help:)! fixed it using iboutlet collection and add properies on viewDidLoad
I'm trying to add properties to keyboard keys like layer.shadowColor or layer.shadowRadius.
I got an error
'Value of type '(UIButton)' -> () has no member 'layer'
how to fix this ?
this is my code keyboardViewController.swift
import UIKit
class KeyboardViewController: UIInputViewController {
var newKeyboardView: UIView!
#IBAction func keyPressed(sender: UIButton) {
}
#IBOutlet var nextKeyboardButton: UIButton!
override func updateViewConstraints() {
super.updateViewConstraints()
// Add custom view sizing constraints here
}
override func viewDidLoad() {
super.viewDidLoad()
loadInterface()
}
func loadInterface() {
// load the nib file
let keyboardNib = UINib(nibName: "newKeyboard", bundle: nil)
// instantiate the view
newKeyboardView = keyboardNib.instantiateWithOwner(self, options: nil)[0] as! UIView
// add the interface to the main view
view.addSubview(newKeyboardView)
// copy the background color
view.backgroundColor = newKeyboardView.backgroundColor
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated
}
override func textWillChange(textInput: UITextInput?) {
// The app is about to change the document's contents. Perform any preparation here.
}
override func textDidChange(textInput: UITextInput?) {
// The app has just changed the document's contents, the document context has been updated.
var textColor: UIColor
let proxy = self.textDocumentProxy
if proxy.keyboardAppearance == UIKeyboardAppearance.Dark {
textColor = UIColor.whiteColor()
} else {
textColor = UIColor.blackColor()
}
self.nextKeyboardButton.setTitleColor(textColor, forState: .Normal)
}
}
I think that in order to apply some style to the button, you need an outlet to this button.
Right now, from what I can understand, you are trying to apply styles to the button from the #IBAction to the sender, which is not the proper way to do it.
Try to make an outlet to the button in the view controller and then to apply the styles from within the viewDidLoad method.
I hope this is clear, but if you want a more specific answer you need to show us what you tried, for example pasting the code you have in the view controller
EDIT:
Based on the code you post, the keyboard is a Nib you instantiate from loadInterface(). I don't have a clear vision of the whole thing with only this piece of code, but it seems to me that you are trying to apply some styles to every key button of a keyboard view. Unfortunately this really depends on how the keyboard is implemented, can you provide some more details?
Anyway, from what I see I think you didn't write this code: probably you are following a tutorial or maintaining someone else's code. That's ok, but I suggest you to follow a an introduction course to iOS development with Swift, like the Udacity's one, which is fantastic IMHO (https://www.udacity.com/course/intro-to-ios-app-development-with-swift--ud585)
If you try to format your UIButton with QuartzCore framework, you'll need to import it first:
import QuartzCore
Then you will be able to access those members.
For example (latest swift3 code):
#IBAction func keyPressed(sender: UIButton) {
let button = sender as UIButton!
button?.backgroundColor = UIColor.red
button?.layer.shadowColor = UIColor.black.cgColor
button?.layer.shadowRadius = 1.0
button?.layer.cornerRadius = 4.0
}
In case you need to apply your styles sooner, try to consider to put this code into viewDidLoad or viewDidAppear methods:
self.nextKeyboardButton.backgroundColor = UIColor.red
self.nextKeyboardButton.layer.shadowColor = UIColor.black.cgColor
self.nextKeyboardButton.layer.shadowRadius = 1.0
self.nextKeyboardButton.layer.cornerRadius = 4.0
Seems like you're trying to "add property" not to a button, but rather to a closure which accepts a button as an argument.
Make it like this:
nextKeyboardButton.layer.shadowColor = UIColor.redColor.cgColor
nextKeyboardButton.layer.shadowRadius = 5.0

Get a control's original frame for both portrait and landscape

I am working on an application that has different UI constraints and control positions for portrait and landscape. These are all done on the storyboard. In addition to this, I am repositioning controls based on a user shutting off one of the controls. I am doing this by grabbing the frame for each of the controls in viewDidLoad. Once I have these values, then it is easy to reposition the controls and restore them to what they should be when unhidden. The thing is that I need all of the frames for both portrait and landscape. That way I can do the repositioning regardless of orientation.
How can I get the control positioning information for both portrait and landscape when coming through viewDidLoad? Is there any way to do this?
After adding constraints to a view, and the view readjusting its position and size according to device size and orientation. This readjusting of the view size is done in the method viewDidLayoutSubviews, which is called after viewDidAppear.
If you can log out the positions and size of the control in this method, you will get the updated (size and position as it is seen in the device).
But this method is called multiple times after viewDidAppear, so if you want to add anything i recommend adding the control in viewDidLoad and then updating the position in this method.
After working with this a bit more, I came up with this:
import UIKit
class ViewController: UIViewController {
var pButtonFrame: CGRect!
var lButtonFrame: CGRect!
#IBOutlet weak var testButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "screenRotated", name: UIDeviceOrientationDidChangeNotification, object: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func screenRotated() {
//Set this only once, the first time the orientation is used.
if lButtonFrame == nil && UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation)
{
lButtonFrame = testButton.frame
}
else if pButtonFrame == nil && UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)
{
pButtonFrame = testButton.frame
}
}
}
I set up a test button and positioned it using constraints on the storyboard. I added an observer to NSNotificationCenter to watch for screen rotation. I'm storing the frames for each of the orientations in CGRect variables. By checking each of the variables for nil, I can ensure that they only get set once, before I have done any modifications to the screen. That way, I can restore the values to their originals, if needed. I can set up the showing and hiding of controls here, or in viewDidLayoutSubviews.
import UIKit
class ViewController: UIViewController {
var pButtonFrame: CGRect!
var lButtonFrame: CGRect!
#IBOutlet weak var btntest: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
screenRotate()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func screenRotate() {
//Set this only once, the first time the orientation is used.
if lButtonFrame == nil && UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation)
{
lButtonFrame = btntest.frame
}
else if pButtonFrame == nil && UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)
{
pButtonFrame = btntest.frame
}
}
}

Resources