Video
Hey :) Im kind of new to Stack and not sure if i should have edited this instead of adding a whole new question but i figured out a way to make it more clear. So in my code i want my textImages to only show up on the front of the UIimageViews, and the "back" image to show up on only the back side of my ImageView when flipped. Right now both Images are showing up on both parts. Is there a way to addSubview() to only the back of the ImagView :/ I do not want to use UItablevView if possible. Also in the video the last looped UIimageView works just like i want but not the ImageViews before it.
import UIKit
import Foundation
class ViewController: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
#IBOutlet var open: UIBarButtonItem!
var myImageArray = [UIImage]()
var back: UIImageView!
var front: UIImageView!
var showingFront = true
override func viewDidLoad() {
super.viewDidLoad()
let singleTap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapped))
singleTap.numberOfTapsRequired = 1
mainScrollView.addGestureRecognizer(singleTap)
mainScrollView.isUserInteractionEnabled = true
mainScrollView.frame = view.frame
myImageArray = [textImg1, textImg2 ,textImg3, textImg4, textImg5]
for i in 0..<myImageArray.count {
front = UIImageView()
front.image = myImageArray[i]
front.contentMode = .scaleToFill
let yPosition = self.view.frame.height * CGFloat(i) + self.view.frame.height/2 - (self.view.frame.height / 1.1)/2
let xPosition = self.view.frame.width/2 - (self.view.frame.width / 1.1)/2
front.frame = CGRect(x: xPosition, y: yPosition, width: self.view.frame.width / 1.1, height: self.view.frame.height / 1.1)
front.layer.borderWidth = 5
mainScrollView.contentSize.height = mainScrollView.frame.height * CGFloat(i + 1)
mainScrollView.addSubview(front)
back = UIImageView(image: UIImage(named: "back.png"))
back.contentMode = .scaleToFill
back.frame = CGRect(x: xPosition, y: yPosition, width: self.view.frame.width / 1.1, height: self.view.frame.height / 1.1)
back.layer.borderWidth = 5
mainScrollView.addSubview(back)
}
}
func tapped() {
print("Hello")
if (showingFront) {
UIView.transition(from: front, to: back, duration: 1, options: UIViewAnimationOptions.transitionFlipFromRight, completion: nil)
showingFront = false
} else {
UIView.transition(from: back, to: front, duration: 1, options: UIViewAnimationOptions.transitionFlipFromLeft, completion: nil)
showingFront = true
}
}
}
Related
I want my swift code to copy the object which is a brown view. So the user hits the copy button then the user hits the object they want to copy and then they point to the area where they want to place the object. Basically the gif below is exactly what I am look at I don't know if you would do something like a clone of something like this.
import UIKit;import CoreData
class ViewController: UIViewController {
var addBoxes = [UIImageView]()
let subview = UIImageView()
var currentView: UIView?
var box = UIButton()
var copyButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
[box,copyButton].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
box.backgroundColor = .red
box.setTitle("Add", for: .normal)
copyButton.setTitle("Copy", for: .normal)
NSLayoutConstraint.activate([
box.leadingAnchor.constraint(equalTo: copyButton.trailingAnchor),
box.bottomAnchor.constraint(equalTo: view.bottomAnchor),
box.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
box.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
copyButton.leadingAnchor.constraint(equalTo: view.leadingAnchor),
copyButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
copyButton.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
copyButton.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
])
copy.addTarget(self, action: #selector(copyBox), for: .touchDown)
box.addTarget(self, action: #selector(addQuarter), for: .touchDown)
copyButton.backgroundColor = .blue
}
override var prefersStatusBarHidden: Bool {
return true
}
#objc func copyBox() {
}
#objc func handlePanGestured(_ gesture: UIPanGestureRecognizer) {
currentView = gesture.view
let draggedView = gesture.view!
view.bringSubviewToFront(draggedView)
let translation = gesture.translation(in: view)
draggedView.center = CGPoint(x: draggedView.center.x + translation.x, y: draggedView.center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
#objc func addQuarter(){
let subview = UIImageView()
subview.isUserInteractionEnabled = true
addBoxes.append(subview)
view.addSubview(subview)
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
subview.addGestureRecognizer(pan)
subview.frame = CGRect(x: view.bounds.midX , y: view.bounds.midY + CGFloat(100), width: CGFloat(100), height: 100)
subview.backgroundColor = .brown
addBoxes.append(subview)
}
}
Achieve your requirement with code
class ViewController: UIViewController {
var addBoxes = [UIImageView]()
let subview = UIImageView()
var currentView: UIView?
var location: CGPoint = CGPoint.zero
var box = UIButton()
var copyButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
[box,copyButton].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
box.backgroundColor = .red
box.setTitle("Add", for: .normal)
copyButton.setTitle("Copy", for: .normal)
NSLayoutConstraint.activate([
box.leadingAnchor.constraint(equalTo: copyButton.trailingAnchor),
box.bottomAnchor.constraint(equalTo: view.bottomAnchor),
box.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
box.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
copyButton.leadingAnchor.constraint(equalTo: view.leadingAnchor),
copyButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
copyButton.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.04),
copyButton.widthAnchor.constraint(equalTo:view.widthAnchor ,multiplier: 0.5),
])
copyButton.addTarget(self, action: #selector(copyBox), for: .touchDown)
box.addTarget(self, action: #selector(addQuarter), for: .touchDown)
copyButton.backgroundColor = .blue
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:))))
}
override var prefersStatusBarHidden: Bool {
return true
}
#objc func copyBox() {
if let copyObject = currentView?.copyView as? UIImageView{
copyObject.center = location
copyObject.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:))))
view.addSubview(copyObject)
}
}
#objc func handlePanGestured(_ gesture: UIPanGestureRecognizer) {
currentView = gesture.view
let draggedView = gesture.view!
view.bringSubviewToFront(draggedView)
let translation = gesture.translation(in: view)
draggedView.center = CGPoint(x: draggedView.center.x + translation.x, y: draggedView.center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
#objc func handleTapGestured(_ gesture: UITapGestureRecognizer) {
if self.view == gesture.view{
let loc = gesture.location(in: self.view)
location = loc
}
}
#objc func addQuarter(){
let subview = UIImageView()
subview.isUserInteractionEnabled = true
addBoxes.append(subview)
view.addSubview(subview)
let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestured(_:)))
subview.addGestureRecognizer(pan)
subview.frame = CGRect(x: view.bounds.midX , y: view.bounds.midY + CGFloat(100), width: CGFloat(100), height: 100)
subview.backgroundColor = .brown
addBoxes.append(subview)
}
}
extension UIView{
var copyView : UIView?{
if let archiv = try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false){
if let view = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archiv) as? UIView{
return view
}
}
return nil
}
}
a way to achieve copy.
You can do it in the Model level.
In your case, to copy View, is to get the View property ( Frame Size, Color ),
then create a new one.
here is the code instruction
model part
// you can add info , in your needs
struct ViewModel{
let color: UIColor
let size: CGSize
}
Logic Part:
add an UITapGestureRecognizer to the base view (add part view)
in copy mode, the view isUserInteractionEnabled false,
in add mode, the view isUserInteractionEnabled true,
var selectModel: ViewModel?
#objc func copyBox() {
// now in the copy mode
}
func selectView(){
// get current model
selectModel = ViewModel(color: yourView.backgroundColor, size: yourView.frame.size)
}
#objc func AddBox() {
// now in the add mode / paste mode
}
func touchToAdd(_ gesture: UITapGestureRecognizer){
// get the tap location,
// the location point is the new view's center
// use the model from `func selectView(){`
// now you got center . frame size 、color, enough to create a new one ( a copy)
}
I have a scroll view that has an image view embedded into it. The user clicks the "Take Photo" button, takes a picture, and then those photos are stored in an array and then displayed on the scrollable imageView. My issue is that after the didFinishSelectingMedia is called and the camera closes, the imageView always shows the first image in the array. I want the imageView to show the most recent image added to the array and scroll backward through the images until the user comes to the first image in the array. How do I make this happen?
Btw: Idk if this is even plausible, but I tried reversing the for loop and that didn't work.
I'm a new programmer, so please explain your answers.
Here's my code:
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
#IBOutlet weak var scrollImageView: UIScrollView!
var imageTaken: [UIImage] = []
var imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
scrollImageView.frame = scrollImageView.frame
}
#IBAction func takePhotoButton(_ sender: Any) {
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
present(imagePicker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
imageTaken.append((info[.originalImage] as? UIImage)!)
imagePicker.dismiss(animated: true, completion: nil)
for i in 0..<imageTaken.count {
let imageView = UIImageView()
imageView.image = imageTaken[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.scrollImageView.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.scrollImageView.frame.width, height: self.scrollImageView.frame.height)
scrollImageView.contentSize.width = scrollImageView.frame.width * CGFloat(i + 1)
scrollImageView.addSubview(imageView)
}
}
}
Two options I guess you can take which ever one is seems easier.
OOP — Create an array of objects example:
struct TakePhotos {
var image : UIImage
var timestamp : Date
}
Then sort the array by the timestamp.
Use PHAsset
import Photos
Using PHAsset you should be able to retrieve the images taken from the user's album. Set a count when the user takes a new image.
Then you can run a query and sort the images in reverse order, they will already have the timestamp.
let photoOptions = PHFetchOptions()
photoOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
This is what I did in my application.
// FIXME: - Query only happens once this needs to be refactored so it happens when the album is updated on the device.
// Query only happens one time.
if imageArray.isEmpty {
let photoOptions = PHFetchOptions()
photoOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let allPhotos = PHAsset.fetchAssets(with: photoOptions)
let fetchOptions = PHImageRequestOptions()
fetchOptions.deliveryMode = .highQualityFormat
fetchOptions.resizeMode = .exact
fetchOptions.normalizedCropRect = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width)
// Must be a synchronous call otherwise the view loads before images are retrieved (result is an empty view).
fetchOptions.isSynchronous = true
let imageSize : CGSize = CGSize(width: view.frame.width, height: view.frame.height)
//Retrieves Images using assets.
allPhotos.enumerateObjects { (assets, index, pointer) in
DispatchQueue.global(qos: .background).sync {
PHImageManager.default().requestImage(for: assets, targetSize: imageSize, contentMode: .aspectFit, options: fetchOptions) { (image, hashDictionary) in
guard let image = image else {return}
self.imageArray.append(image)
self.albumImages.append(ImageAlbum(images: image))
}
}
}
selectedImage.image = imageArray.first
selectedImage.contentMode = .scaleAspectFill
}
Im grabbing the photos from library using a cocoa pod called BSImagePicker. The Images are then stored into a photoArray. I want to take those images from the array and present them in an image view that's held inside the scrollView. However the images aren't showing up at all.
This is what I've currently tried.
This is the code that the cocoa pod uses to store images into the array:
func openImagePicker() {
let vc = BSImagePickerViewController()
self.bs_presentImagePickerController(
vc,
animated: true,
select: { (assest: PHAsset) -> Void in },
deselect: { (assest: PHAsset) -> Void in },
cancel: { (assest: [PHAsset]) -> Void in },
finish: { (assest: [PHAsset]) -> Void in
for i in 0..<assest.count {
self.SelectedAssets.append(assest[i])
}
self.convertAssetToImages()
},
completion: nil
)
print(photoArray)
setupImages(photoArray)
}
this is the code that converts asset to image
extension addImages {
func convertAssetToImages() -> Void {
if SelectedAssets.count != 0{
for i in 0..<SelectedAssets.count{
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
let width = scrollView.frame.width
let height = scrollView.frame.height
manager.requestImage(for: SelectedAssets[i], targetSize: CGSize(width: width, height: height), contentMode: .aspectFill, options: option, resultHandler: {(result,info) -> Void in
thumbnail = result!
})
let data = thumbnail.jpegData(compressionQuality: 1)
let newImage = UIImage(data: data! as Data)
self.photoArray.append(newImage! as UIImage)
}
}
}
}
this code takes image from photo array into scrollview
func setupImages(_ images: [UIImage]){
for a in 0..<photoArray.count {
let theImage = UIImageView()
theImage.image = self.photoArray[a]
let xPosition = UIScreen.main.bounds.width * CGFloat(a)
self.scrollView.frame = CGRect(x: xPosition, y: 0, width: self.scrollView.frame.width, height: self.scrollView.frame.height)
theImage.contentMode = .scaleAspectFit
self.scrollView.contentSize.width = self.scrollView.frame.width * CGFloat(a + 1)
self.scrollView.addSubview(theImage)
}
}
I have no idea why it isn't working.
I am trying to generate a section of image views which will sit at the top of an application and update as the user progresses through the quiz.
My array variable is Qs, the code I have to generate an imageView is as follows:
var imageView: UIImageView!
var i = 0
var total = Int(Qs.capacity) // Just testing what .capacity does.
for i in 0..<(Qs.count-1){
imageView - UIImageView(frame: CGRect(x: 0, y: 75, width: 50, height: 50))
imageView.image = UIImage(named:"InfoIcon")
imageView.contentMode = .scaleAspectFit
self.view.addSubView(imageView)
}
I already have a variable which tracks the users progress through the quiz with just an integer if that would be any help, its declared along with the quiz functionality.
Here is a fantastically draw visual of what I am trying to accomplish:
Any help is appreciated,
thanks
Lets assume you have a container view attached at the top, then you can use this method to add any number of imageView's.
func addProgressImages(to view: UIView, count: Int) {
let screenSize = UIScreen.main.bounds.size
for i in 0..<count {
let spacing: CGFloat = 2
let tag = i + 888
let width: CGFloat = screenSize.width/CGFloat(count)
let height: CGFloat = width
if let view = view.viewWithTag(tag) {
view.removeFromSuperview()
}
let x = spacing + CGFloat(i) * width
let imageView = UIImageView(frame: CGRect(x: x, y: 100, width: width - spacing, height: height))
imageView.image = UIImage(named:"InfoIcon")
imageView.tag = tag
imageView.contentMode = .scaleAspectFit
view.addSubview(imageView)
}
}
You can play with y value for vertical alignment.
Here is my code to do that:
import UIKit
import Photos //Photos.h del framework Photos
import MediaPlayer
import AssetsLibrary
let reuseIdentifier = "PhotoCell"
let albumName = "My App"
class PhotosViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var assetCollection:PHAssetCollection!
var photoAsset:PHFetchResult!
var imageManager = PHImageManager.defaultManager()
var albumFound:Bool = false
#IBOutlet weak var collectionView: UICollectionView!
#IBAction func creaFilmato(sender: AnyObject) {
println("Crea il tuo filmato")
/* With a static array works perfectly
let img1:UIImage = UIImage(named: "image1.jpg")!
let img2:UIImage = UIImage(named: "image2.jpg")!
let img3:UIImage = UIImage(named: "image3.jpg")!
var array:Array<UIImage> = [img1,img2,img3]*/
let img1:UIImage = UIImage(named: "image1.jpg")!
let settings:NSDictionary = CEMovieMaker.videoSettingsWithCodec(AVVideoCodecH264, withWidth: img1.size.width, andHeight: img1.size.height)
let prova = CEMovieMaker(settings: settings)
prova.createMovieFromImages([self.photoAsset.copy()], withCompletion: {(success:Bool, fileURL:NSURL!) in
if(success){
self.viewMovieAtURL(fileURL)
/*// Salvo il filmato in cameraRoll
let library:ALAssetsLibrary = ALAssetsLibrary()
library.writeVideoAtPathToSavedPhotosAlbum(fileURL, completionBlock: {(assetURL:NSURL!, error) in
if((error) != nil) {
println("Errore nel salvataggio del filmato %#",error)
}
})*/
}
})
println("Esportato!")
}
func viewMovieAtURL(fileURL:NSURL!)->Void {
let playerController:MPMoviePlayerViewController = MPMoviePlayerViewController(contentURL: fileURL!)
playerController.view.frame = self.view.bounds
self.presentMoviePlayerViewControllerAnimated(playerController)
playerController.moviePlayer.prepareToPlay()
playerController.moviePlayer.play()
self.view.addSubview(playerController.view)
}
In my opinion the wrong code is [self.photoAsset.copy()] because photoAsset return PHFetchResult and not an Array of UIImage. What is the code to obtain an array of images starting from a PHFetchResult in Swift?
var images = [UIImage]()
let targetSize: CGSize = // your target size
let contentMode: PHImageContentMode = // your content mode
// photoAsset is an object of type PHFetchResult
photoAsset.enumerateObjectsUsingBlock {
object, index, stop in
let options = PHImageRequestOptions()
options.synchronous = true
options.deliveryMode = .HighQualityFormat
PHImageManager.defaultManager().requestImageForAsset(object as PHAsset, targetSize: targetSize, contentMode: contentMode, options: options) {
image, info in
images.append(image)
}
}
This is how I do it with Swift 4.2
let fetchOptions = PHFetchOptions()
let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)
let targetSize = CGSize(width: 100, height: 100) // your target size
allPhotos.enumerateObjects {
object, index, stop in
var thumbnail = UIImage()
let options = PHImageRequestOptions()
options.isSynchronous = true
options.deliveryMode = .highQualityFormat
PHImageManager.default().requestImage(for: object, targetSize: targetSize, contentMode: .aspectFill, options: options, resultHandler: { image, _ in
thumbnail = image!
})
}
Hope this help!