iOS custom keyboard changing constraints - ios

I am trying to create a custom keyboard in swift programmatically and have so far been able to create the constraints I want for portrait and landscape on iPhone, but only when I start the keyboard in the respective orientation.
The problem comes when I flip the device myself: Portrait, Landscape. I have stored my constraints in two arrays and am running this block of code in my viewDidLoad and viewWillTransition functions:
if UIScreen.main.bounds.height >= 568 {
NSLayoutConstraint.deactivate(constraintsLandscape)
NSLayoutConstraint.activate(constraintsPortrait)
}
else if UIScreen.main.bounds.height <= 414 {
NSLayoutConstraint.deactivate(constraintsPortrait)
NSLayoutConstraint.activate(constraintsLandscape)
}
Any help with this is appreciated.
Current portrait and landscape

if this is inside a method, do u call it after the screen rotates ? if dont you can check device rotation overriding this method:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if UIDevice.current.orientation.isLandscape {
print("Device is in Landscape mode")
NSLayoutConstraint.deactivate(constraintsPortrait)
NSLayoutConstraint.activate(constraintsLandscape)
} else {
print("Device is in Portrait mode")
NSLayoutConstraint.deactivate(constraintsLandscape)
NSLayoutConstraint.activate(constraintsPortrait)
}
}
if you are already doing this, then you just need to call self.view.layoutifNeeded() after making changes to your constraints.

Related

Update view after orientation change

I created a blurred view on top of a scroll view (from a collection view) who is displaying on all the screen when user go to the settings but when orientation change when this blurview is active, it doesn't cover all the screen. I implemented the same function to update the frame size and origin when orientation change is catched but it still doesn't work.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
self.detailBlurView.removeFromSuperview()
if UIDevice.current.orientation.isLandscape {
print("Landscape")
detailBlurView.frame = myCollectionView.bounds
self.myCollectionView.addSubview(detailBlurView)
} else {
print("Portrait")
detailBlurView.frame = myCollectionView.bounds
self.myCollectionView.addSubview(detailBlurView)
}
saveToCoreData()
myCollectionView.reloadData()
loadData()
}
I tried to remove the view from the superview and add it again after changing orientation but still not work.
Someone can tell me why it doesn't update the blurview frame and how to fix it please ?

UICollectionView - redesign in Landscape mode

I am working on a UICollectionView to show list of items in Portrait mode as shown in below screen shot and implemented using UICollectionViewController.
Now I want to re-design same thing in Landscape mode as shown in below screen shot.
How can I get such a design using UICollectionView and UICollectionViewFlowLayout in Landscape mode by re-using same code base of portrait? Is it possible? can you please advice me?
Thanks in advance.
You can also do by using stackview. Create a stackview with two views then change the axis when orientation change. Set proper constraints for your requirement.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
handleOrientationForLandscape(isLandscape: UIDevice.current.orientation.isLandscape)
}
func handleOrientationForLandscape(isLandscape: Bool) {
if isLandscape
{
containerStackview.axis = .horizontal
topViewWidthConstraint.constant = 700
}else
{
containerStackview.axis = .vertical
topViewWidthConstraint.constant = UIScreen.main.bounds.width
}
}
please check https://github.com/karthikprabhuA/stackOverflowAnswer

How to set Notification if view size changed when using multitasking | Swift

When testing my app on an iPad using multitasking and I change the app size on the app, the collection view cells need to be resized or else they don't fit in the view window.
I have took some measures such as
detecting device to change the size of the cells
measure view size to make sure cells fit within the window
Add an observer if user changes device orientation
This is all great but however when actually changing the window size when using multitasking, or going back to the full screen app, the cell sizes don't change and look out of place. This is until forced by switching orientation or switching view controllers so viewWillLoad or viewDidLoad gets executed again.
So how can I set a notification if the view.frame size changes ?
I think the right function to override is viewWillTransition(to:, with:). It is called whenever the container size is about to change.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.collectionView?.collectionViewLayout.invalidateLayout()
}
I think you are over complicating the issue, just use the following so when the device is rotated or resized the collection view also changes accordingly.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
guard let collectionLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else {
return
}
if UIApplication.shared.statusBarOrientation == UIInterfaceOrientation.landscapeLeft ||
UIApplication.shared.statusBarOrientation == UIInterfaceOrientation.landscapeRight {
//here you can do the logic for the cell size if phone is in landscape
} else {
//logic if not landscape
}
collectionLayout.invalidateLayout()
}
I tried RileyDev answer but the app entered in an infinite loop.
There is no delegate that is executed just when the App's window bounds change, so I've made my own version of the viewWillTransition(to size and traitCollectionDidChange.
With the code below you can detect the window bounds resizing change even if the traits don't change, and resize your collection view cells accordingly invalidating the collection view layout.
var previousWindowBounds: CGRect?
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if let currentBounds = view.window?.bounds,
let previousWindowBounds = previousWindowBounds, currentBounds != previousWindowBounds {
collectionView?.collectionViewLayout.invalidateLayout()
}
previousWindowBounds = view.window?.bounds
}

How can I get the height of a view after screen rotation in swift?

There is a view, which I add constraints in storyboard so it will change its size after screen rotation, then how can I get its height and width after screen rotation? I tried this in a rotation event function like this:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
println("h:\(view.bounds.size.height)")
println("w:\(view.frame.size.width)")
}
but it only give me the size before rotation happen. I would like to get something like:
"now is landscape, height is...width is..."
"now is portrait, height is ...width is..."
in a rotation event function
The function you are using says "Will transition", that means the transition is not completed, so you can not fetch the new size.
You need to use :
dispatch_async(dispatch_get_main_queue()) {
println("h:\(view.bounds.size.height)")
println("w:\(view.frame.size.width)")
}
This code will be executed after the rotation was completed (in the main queue) and the new sizes are available.
Regards.
Swift 3
crom87 answer updated for Swift 3:
override func viewWillTransition( to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator ) {
DispatchQueue.main.async() {
print( "h:\(self.view.bounds.size.height)" )
print( "w:\(self.view.frame.size.width)" )
}
}

Automatically update preferredContentSize upon rotation

I am looking for a way to enforce a UIPopoverPresentationController automatically resize to fill most of the screen, minus say 50 units of padding.
I first tried settings the preferredContentSize in viewDidLoad, and then detect when rotation occurs and update that CGSize to the new size I could calculate. But for some reason, this isn't working in my context. I was using UIDeviceOrientationDidChangeNotification which normally calls the method, but it's not called when the popover exists within a photo editing extension.
I am wondering if there's any other way to change the popover size besides manually updating the preferredContentSize after detecting a size change? If not, is there a way to detect rotation from within this popover in this context?
Try this:
func isLandscape() -> Bool {
// your logical here
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let myNewSize = isLandscape() ? mySizeLandscape : mySizePortrait
self.preferredContentSize = myNewSize
super.viewWillTransition(to: myNewSize, with: coordinator)
}

Resources