I have an image view in my view controller but weirdly I can't show my image inside of the imageview. It is located in the middle of the page or somewhere else in the other view controllers. My code of both image view and image picker are below.
And this is the output. Arrow image doesn' t show in expected area:
profileImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profileImageView.bottomAnchor.constraint(equalTo: nameTextField.topAnchor, constant: -12).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 150).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 150).isActive = true
profileImageView.image = UIImage(named: "arrow_long_left")
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView)))
profileImageView.isUserInteractionEnabled = true
view.addSubview(profileImageView)
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var selectedImageFromPicker: UIImage?
if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage {
selectedImageFromPicker = editedImage
} else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage {
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker {
profileImageView.image = selectedImage
}
dismiss(animated: true, completion: nil)
}
func handleSelectProfileImageView() {
let imagePicker = UIImagePickerController()
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
//picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
/*else if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = UIImagePickerControllerSourceType.camera;
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}*/
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("canceled picker")
dismiss(animated: true, completion: nil)
}
Your code is off here:
profileImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profileImageView.bottomAnchor.constraint(equalTo: nameTextField.topAnchor, constant: -12).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 150).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 150).isActive = true
My guess is you want something more like this:
profileImageView.leadingAnchor.constraint(equalTo: nameTextField.trailingAnchor, constant:10).isActive = true
profileImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant:10).isActive = true
profileImageView.topAnchor.constraint(equalTo: nameTextField.topAnchor).isActive = true
profileImageView.bottomAnchor.constraint(equalTo: emailTextField.bottomAnchor).isActive = true
If you want to fix the width and height to 150, you'll need to adjust a bit. But, right now you're anchored to the centerX of the view, so its horizontally centered. And anchored by the bottom to the top of the nameTextField - so of course its above the nameTextField
Related
According to documentation,
In a horizontally compact environment, popovers adapt to the
UIModalPresentationOverFullScreen presentation style by default.
See below image. In compact environment, popover appear from bottom and animate to top until it covers the entire screen.
Is it possible to override this behaviour and have the popover only covering certain height of the screen as shown below?
Following code demonstrate the default behaviour of popover adapting to FullScreen presentation style in compact environment.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .systemBackground
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(UIImage(systemName: "square.grid.2x2.fill"), for: .normal)
button.addTarget(self, action: #selector(displayPopover), for: .touchUpInside)
self.view.addSubview(button)
NSLayoutConstraint.activate([
button.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100),
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
button.widthAnchor.constraint(equalToConstant: 40),
button.heightAnchor.constraint(equalToConstant: 40),
])
}
#IBAction func displayPopover(sender: UIButton!) {
let popoverVC = PopoverViewController()
popoverVC.preferredContentSize = CGSize(width: 300, height: 200)
popoverVC.modalPresentationStyle = .popover
popoverVC.popoverPresentationController?.sourceView = sender
popoverVC.popoverPresentationController?.permittedArrowDirections = .up
self.present(popoverVC, animated: true, completion: nil)
}
}
class PopoverViewController: UIViewController {
override func viewDidLoad() {
self.view.backgroundColor = .systemGray
}
}
Output:
Thank you 🙇♂️
This feature is now available with iOS 15.
Watch WWDC2021 short video
Download WWDC sample project from here
#IBAction func showImagePicker(_ sender: UIBarButtonItem) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.modalPresentationStyle = .popover
if let popover = imagePicker.popoverPresentationController {
popover.barButtonItem = sender
let sheet = popover.adaptiveSheetPresentationController
sheet.detents = [.medium(), .large()]
sheet.largestUndimmedDetentIdentifier = .medium
sheet.prefersScrollingExpandsWhenScrolledToEdge = false
sheet.prefersEdgeAttachedInCompactHeight = true
sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
}
present(imagePicker, animated: true, completion: nil)
}
I'm trying to play an video from photo library with AVPlayer but for some reason I can't get it to work. I've been trying to read every question about this but none of the suggested answers seems to work.
Is my code wrong or do I need to do something else to make it work? Enable it in capabilities or something similar?
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let videoPickerController = UIImagePickerController()
// MARK:- UI Elements
let SelectVideoBtn : UIButton = {
let a = UIButton(type: .roundedRect)
a.translatesAutoresizingMaskIntoConstraints = false
a.setTitle("Select Video", for: .normal)
a.backgroundColor = UIColor.systemOrange
a.layer.cornerRadius = 10
a.addTarget(self, action: #selector(SelectAVideo(sender:)), for: .touchUpInside)
return a
}()
let MasterPreviewView : UIView = {
let a = UIView()
a.translatesAutoresizingMaskIntoConstraints = false
a.backgroundColor = #colorLiteral(red: 0.9098039269, green: 0.4784313738, blue: 0.6431372762, alpha: 1)
a.layer.cornerRadius = 10
return a
}()
let HorizontalToolStack : UIStackView = {
let a = UIStackView()
a.translatesAutoresizingMaskIntoConstraints = false
a.axis = .horizontal
a.distribution = .equalSpacing
a.alignment = .fill
a.spacing = 20
return a
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1)
// Do any additional setup after loading the view.
// delegates and data stuff
videoPickerController.delegate = self
// Selection Button
self.view.addSubview(SelectVideoBtn)
SelectVideoBtn.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 30).isActive = true
SelectVideoBtn.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 100).isActive = true
SelectVideoBtn.widthAnchor.constraint(equalToConstant: 200).isActive = true
SelectVideoBtn.heightAnchor.constraint(equalToConstant: 50).isActive = true
// Master Preview View
self.view.addSubview(MasterPreviewView)
MasterPreviewView.topAnchor.constraint(equalTo: SelectVideoBtn.bottomAnchor, constant: 30).isActive = true
MasterPreviewView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 10).isActive = true
MasterPreviewView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -10).isActive = true
MasterPreviewView.heightAnchor.constraint(equalToConstant: 400).isActive = true
MasterPreviewView.isUserInteractionEnabled = false
let videoURL = NSURL(string: "assets-library://asset/asset.MP4?id=A0FBB444-15D7-4ED2-9EB2-922E4FB11F7A&ext=MP4")
PlayVideo(inView: MasterPreviewView, pathToVideo: videoURL!)
}
internal func VideoPicker(){
videoPickerController.sourceType = .photoLibrary
videoPickerController.mediaTypes = ["public.movie"]
videoPickerController.allowsEditing = true
present(videoPickerController, animated: true, completion: nil)
}
// MARK:- Delegate Methods
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let videoURL = info[UIImagePickerController.InfoKey(rawValue: "UIImagePickerControllerReferenceURL")] as? NSURL
print(videoURL!)
videoPickerController.dismiss(animated: true, completion: nil)
// Now Play the Selected Video
PlayVideo(inView: MasterPreviewView, pathToVideo: videoURL!)
}
public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("Selection Cancelled")
self.dismiss(animated: true, completion: nil)
}
// MARK:- Button Selectors
#objc func SelectAVideo(sender : UIButton){
VideoPicker()
}
//MARK:- Custom Functions
/**
A function to play a video in the View of our choice.
- Parameter inView : Specify the view in which youo want the video player to play your video
- Parameter pathToVide : The path of the video you want to play
*/
private func PlayVideo(inView parentView : UIView, pathToVideo urlPath : NSURL) {
// Downcasting the NSURL to URL
let player = AVPlayer(url: urlPath as URL)
let playerController = AVPlayerViewController()
playerController.player = player
let playerLayerAV = AVPlayerLayer(player: player)
//now we set the size of frame to be like the view ("backview")
playerLayerAV.frame = parentView.bounds
parentView.layer.addSublayer(playerLayerAV)
player.play()
player.rate = 0.5
}
}
i want to create an imageview with photo selected from photo library and display in the scrollview by pushing a button. But the image is not displayed after selection but only display when I push the button again. Can someone help me with this one please?
#IBAction func imageBtnPressed(_ sender: Any) {
imagePicker()
let imageView = UIImageView(frame: CGRect(x: (scrollView.bounds.size.width-200)/2, y:(scrollView.bounds.size.height-100)/2, width: 200, height: 100))
imageView.image = imageOnCanvas
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
scrollView.addSubview(imageView)
}
func imagePicker(){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
present(imagePicker, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
{
dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let selectedImage = info[.originalImage] as? UIImage
imageOnCanvas = selectedImage
dismiss(animated: true, completion: nil)
}
Your code does not pause just because the UIImagePickerController is presented. So, let's look at your code:
#IBAction func imageBtnPressed(_ sender: Any) {
imagePicker()
let imageView = UIImageView(frame: CGRect(x: (scrollView.bounds.size.width-200)/2, y:(scrollView.bounds.size.height-100)/2, width: 200, height: 100))
imageView.image = imageOnCanvas
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
scrollView.addSubview(imageView)
}
func imagePicker(){
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
present(imagePicker, animated: true, completion: nil)
}
So that is exactly like saying (substituting the contents of the imagePicker function for the function call):
#IBAction func imageBtnPressed(_ sender: Any) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = false
present(imagePicker, animated: true, completion: nil)
let imageView = UIImageView(frame: CGRect(x: (scrollView.bounds.size.width-200)/2, y:(scrollView.bounds.size.height-100)/2, width: 200, height: 100))
imageView.image = imageOnCanvas
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
scrollView.addSubview(imageView)
}
Well, as you can clearly see, you are referring to imageOnCanvas when it has not been set yet. The imagePicker is still showing; the user has not chosen a photo yet. But your code has completely come to an end. You've gone on to add a subview consisting of the image view containing the image that was in imageOnCanvas before the code started.
I have one problem when I see my view being presented with black BG color. Here is my code:
class Loader: UIViewController, NVActivityIndicatorViewable {
override func viewDidLoad() {
super.viewDidLoad()
self.modalPresentationStyle = .currentContext
self.view.backgroundColor = .clear
self.view.isOpaque = false
let width = UIScreen.main.bounds.width
let height = UIScreen.main.bounds.height
let frame = CGRect(x: width / 2, y: height / 2, width: 100, height: 100)
let activityIndicatorView = NVActivityIndicatorView(frame: frame, type: NVActivityIndicatorType.lineScale, color: GlobalVariables.stacksBlue, padding: 20)
self.view.addSubview(activityIndicatorView)
activityIndicatorView.startAnimating()
activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
activityIndicatorView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
activityIndicatorView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
And the extension where is call function:
extension UIViewController {
func showLoader() {
let loader = Loader()
self.modalPresentationStyle = .currentContext
self.present(loader, animated: false, completion: nil)
}
func hideLoader() {
self.dismiss(animated: false, completion: nil)
}
}
Can you try
let loader = Loader()
loader.providesPresentationContextTransitionStyle = true;
loader.definesPresentationContext = true;
loader.modalPresentationStyle = .overCurrentContext
self.present(loader, animated: false, completion: nil)
You are saying:
self.view.backgroundColor = .clear
self.view.isOpaque = false
So the view itself is clear, and you are seeing the blackness of the window behind it.
I'm currently working on a application that allows a user to take a multiple images and it'll display it on a iCarousel. I'm not very strong at swift so I don't really know how to do it. My question is, "How do I append and display the image after the user takes a photo?" I'm only allowing a maximum of 3 photos. Here's my codes below:
var imageArray : NSMutableArray = NSMutableArray()
#IBOutlet weak var displayView: iCarousel!
override func viewDidLoad() {
super.viewDidLoad()
imageArray = ["1.jpg", "2.jpg", "3.jpg"]
displayView.type = iCarouselType.coverFlow2
displayView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func carousel(_ carousel: iCarousel, viewForItemAt index: Int, reusing view: UIView?) -> UIView {
var imgView : UIImageView!
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
//let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.imageTapped(_:)))
if view == nil {
imgView = UIImageView(frame: CGRect(x: 0, y:0, width: 250, height: 250))
imgView.contentMode = .scaleAspectFit
}
else
{
imgView = view as! UIImageView
}
imgView.image = UIImage(named:"\(imageArray.object(at: index))")
imgView.addGestureRecognizer(tapGesture)
tapGesture.numberOfTapsRequired = 1
imgView.isUserInteractionEnabled = true
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imgView.contentMode = .scaleToFill
imgView.image = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
return imgView
}
func carousel(_ carousel: iCarousel, valueFor option: iCarouselOption, withDefault value: CGFloat) -> CGFloat {
if (option == .spacing)
{
return value * 1.8
}
return value
}
func numberOfItems(in carousel: iCarousel) -> Int {
return imageArray.count
}
func imageTapped(_ sender: UITapGestureRecognizer)
{
let alert = UIAlertController(title: "Pick Image Source", message: "", preferredStyle: .alert)
let takePhotoBtn = UIAlertAction(title: "Take Photo", style: .default, handler: {(_ action: UIAlertAction) -> Void in
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
})
let galleryBtn = UIAlertAction(title: "Select from Gallery", style: .default, handler: {(_ action: UIAlertAction) -> Void in
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary)
{
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
imagePicker.mediaTypes = ["public.image", "public.movie"] //Remove public.movie later
}
})
let cancelBtn = UIAlertAction(title: "Cancel", style: .default, handler: {(_ action: UIAlertAction) -> Void in
// print("Cancel")
})
alert.addAction(takePhotoBtn)
alert.addAction(galleryBtn)
alert.addAction(cancelBtn)
present(alert, animated: true, completion: { _ in })
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if imageArray.count == 3{
return //you can jump to Show the Carousel here
}
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imgView.contentMode = .scaleToFill
imgView.image = pickedImage
// Add image to Array Here
imageArray.add(image)
}
// you can also show refresh carousel from here so new image is availabe in carousel
picker.dismiss(animated: true, completion: nil)
}
if you are allowing maximum of 3 images then you can also write the checking condition in imageTapped function.