My addSubview for an image adds a larger view than expected - swift

I have an image inside a table view cell where the user can user tap on the image the app adds a subview with that image in it. The table view can be longer than the screen. The issue is that if I have the table view scrolled up a bit and the user taps on the image, the image in the subview is scrolled up. My guess is that calling newImageView.frame = UIScreen.main.bounds isn't what I need?
#IBAction func imageTapped(_ sender: UITapGestureRecognizer) {
let imageView = sender.view as! UIImageView
let bookImage = UIImageView(image: imageView.image)
bookImage.frame = UIScreen.main.bounds
bookImage.backgroundColor = .black
bookImage.contentMode = .scaleAspectFit
bookImage.isUserInteractionEnabled = true
let bookImageTap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
bookImage.addGestureRecognizer(bookImageTap)
self.view.addSubview(bookImage)
self.navigationController?.isNavigationBarHidden = true
self.tabBarController?.tabBar.isHidden = true
}
this is what it’s suppose to look like wherever I tap it
this is what happens if I scroll the table view up and tap the image

self.view is a table view, which is a kind of scroll view. If you add a subview to that, it will scroll with the table view. I suppose you don't want that.
Therefore, you should not add the bookImage as a subview of self.view. You can instead add it as a subview of the window:
let window = (UIApplication.shared.delegate as! AppDelegate).window
window?.addSubview(bookImage)

Related

table views only scrolls to textfields bottom edge

The bottommost cell of my table view is a cell with a textField. When the user taps it, I want to scroll it so that the cell is right above the keyboard.
When I call the scrollRectToVisible(...) with animated false everything works as expected, but when animated is set to true the table scrolls the cell only so far, that the bottom of the textField is right above the keyboard (See left picture). Yet the bottonInsets should be correct, since I can scroll the cell the last bit manually and the cell sits right how it should (See right picture).
I think the table view scrolling the textField's bottom edge above the keyboard is the default behavior of a table view, but I'm afraid I don't know why it seems to override my own scrolling when I want it animated.
Left picture:
The textFields bottom edge right above the keyboard (I kept the border style so you can see it better).
Right picture:
How I want it. Cell's bottom edge right above the keyboard.
func repositionTextfieldCell(in tableView: UITableView) {
guard let textFieldCell = tableView.bottommostCell() else { return }
guard let keyboardRect = activeKeyboardRect else { return }
// - Adjust insets
var bottomInset = keyboardRect.size.height
tableView.contentInset.bottom = bottomInset
tableView.scrollIndicatorInsets.bottom = bottomInset
// - Make cell visible
let x = textFieldCell.frame.minX
let y = textFieldCell.frame.maxY
tableView.scrollRectToVisible(CGRect(origin: CGPoint(x: x, y: y),
size: CGSize(width: 1, height: 1)), animated: true)
}
add this in viewDidLoad() and create a NSlayout constraint for tableview bottom.
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow),
name: NSNotification.Name.UIKeyboardWillShow,
object: nil
)
create the function
#objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
tableBottomConstraint.constant = self.view.frame.height - keyboardHeight
}
}
repeat the process to reset the tableBottomConstraint.constant = 0 in keyboardWillHide() method.
I could fix the problem.
The behavior seems to be depended on were scrollRectToVisible(...) is called. The behavior I described in the question occurs when scrollRectToVisible(...) is called in keyboardDidShow(...).
However when you call scrollRectToVisible(...) in keyboardWillShow(...) and set animated to false the cell / rect is pushed up by the keyboard sliding in. Which I think looks great.

UIImage gets clipped when using UiTapGesturerecognizer

I am using the code below to display my image in full screen when a user taps on the image. This image is inside a tableview.
func imageTapped(_ sender: UITapGestureRecognizer) {
let imageView = self.moreImageView
let newImageView = UIImageView(image: imageView?.image)
newImageView.frame = UIScreen.main.bounds
newImageView.backgroundColor = .black
//newImageView.sizeToFit()
newImageView.contentMode = .scaleAspectFill
newImageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
newImageView.addGestureRecognizer(tap)
self.addSubview(newImageView)
}
But when I tap the screen the image renders full screen, but the upper and lower parts of the image always gets clipped. How do I make sure the image resizes and fits in correctly? Thanks
You want .scaleAspectFit
Fit will make it fit inside the space (and show the background color on parts that don't fill)

Make UIImage full screen overlaying Nav & Tabbar too

I have a picture that becomes full screen with black bars to preserve ratio. The problem I'm running into is that it doesn't go over the navbar and tabbar as well. I'm guessing the part of the code I need to change is in here
let imageView = sender.view as! UIImageView
let newImageView = UIImageView(image: imageView.image)
newImageView.frame = self.view.frame
newImageView.backgroundColor = .black
newImageView.contentMode = .scaleAspectFit
What can I set the newImageView frame to so it covers everything?
The problem is that the full screen image is behind the navigation bar and tab bar.
To set it to the full screen size, use UIScreen.main.bounds:
newImageView.frame = UIScreen.main.bounds
When presenting the full screen image, hide the navigation bar and tab bar:
self.navigationController?.isNavigationBarHidden = true
self.tabBarController?.tabBar.isHidden = true
When dismissing the full screen image, restore the navigation bar and tab bar:
self.navigationController?.isNavigationBarHidden = false
self.tabBarController?.tabBar.isHidden = false
Alternate solution
As #LeoDabus mentioned in the comments, you can solve this by presenting a new viewController which contains the imageView that covers the entire view. Present this viewController modally with:
self.present(newViewController, animated: false, completion: nil)
Note: Setting animated to false will allow the full screen image to appear without animation.

Bringing a subview to the front of a UIVisualEffect view?

I've got a view at the top/bottom of my screen that's a blurred view. Ontop of the view I'm wanting to show my buttons unblurred, so I would assume the buttons need to be ontop of the blurred view.
in viewDidLoad I'm running this code :
if !UIAccessibilityIsReduceTransparencyEnabled() {
self.blurOutletTop.backgroundColor = UIColor.clear
self.blueOutletBot.backgroundColor = UIColor.clear
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
let blurEffectView2 = UIVisualEffectView(effect: blurEffect)
//always fill the view
blurEffectView.frame = blurOutletTop.frame //self.view.bounds
blurEffectView2.frame = blueOutletBot.frame
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view.addSubview(blurEffectView)
self.view.addSubview(blurEffectView2)
logoOutlet.bringSubview(toFront: self.view) //This is where my issue is
} else {
blurOutletTop.backgroundColor = UIColor.black
blueOutletBot.backgroundColor = UIColor.black
}
So this makes the two views I have top/bottom blurry. Where I'm running into an issue is where I'm trying to have my logoOutlet infront of the blurred view so it doesn't get blurred. I've tried brining it to the front of the blurrEffectView, the blurOutletTop view, and self.view and everything has the same effect.
I wouldn't assume a button that is not behind a blur view would get effected by the blur. How do I get this to work? I'm also unable to even press the buttons that are now under the view so bringing it to the front doesn't seem to be working. (logoOutlet is an outlet for a button).
edit: I also have tried setting the outlet's zPosition to 9999, no change.

Why is my image not showing up Fullscreen?

I have the following problem. I have about 10 different images which are in a view controller. Now I want the image to switch to fullscreen when they are tapped on. I already set the allow user interaction option to yes, and put in the following code i found on this website:
import UIKit
class ImageViewController: UIViewController {
#IBAction func imageTapped(sender: UITapGestureRecognizer) {
let imageView = sender.view as! UIImageView
let newImageView = UIImageView(image: imageView.image)
newImageView.frame = self.view.frame
newImageView.backgroundColor = .blackColor()
newImageView.contentMode = .ScaleAspectFit
newImageView.userInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: "dismissFullscreenImage:")
newImageView.addGestureRecognizer(tap)
self.view.addSubview(newImageView)
}
func dismissFullscreenImage(sender: UITapGestureRecognizer) {
sender.view?.removeFromSuperview()
}
Does anyone know why my images are not tappable and turning fullscreen?
Make sure both the image view have userInteractionEnabled = YES and
here's an example for what you are trying to do here https://github.com/abhinavsingh77/ImagePreview