so I've been working on this project that involves the whole app's view to be flipped by scaling( if its even possible). I've done this before with a label but I have no idea where to start with the whole app.
I plan on pressing a button and then the whole screen flips by scaling.
here is my attempt:
#IBAction func Flip(_ sender: Any) {
UIView.animate(withDuration: 2.0,animations: {
self.UIView.transform = CGAffineTransform(scaleX: -1, y: 1)
As I said, I dont know where to start, but I was just wondering if it was even possible to have a whole app just flip and if so, is there any way I could get through this problem.
About Duplicate: My Previous question (that was marked as a duplicate) talks about MapBox, and how I can change the Turn-by-Turn UI, but I thought it was better off knowing how to flip the whole app because adding Navigation and Mapbox to the situation makes it a whole different story.
Since UIWindow inherits from UIView, you might be able to just apply a transform to it:
// Assuming your AppDelegate has a "window" property.
UIApplication.shared.delegate!.window!.transform = CGAffineTransform(scaleX: -1, y: 1)
Related
I'm trying to create a customized NavigationViewController where the Navigation bar is a swipeable bar at the top that controls the transitions (think UITabBarController but with swipe gestures not buttons). Here is a quick mockup. I apologize for the crudeness
I have the header bar set up as a ScrollView. I have been able to successfully detect the scroll amount using the scrollViewDidScroll method. So I have the header bar portion rigged up. I now need to implement the transition movement in the scrollViewDidScroll method.
I have looked up the Apple Documentation on how to embed view controllers inside each other but it hasn't really helped explain how to do this. The documentation mentions calling the addChildViewController: method and a bunch of other methods which are fine if I want to make the viewControllers disappear and reappear instantly, but in this scenario I'm finding hard to do it interactively.
Do I create a snapshot of the current VC and then move it? But then what exactly am I moving? In the picture for example, am I moving the entire RedVC's to the left? But then how do I get a snapshot of the BlueVC if it starts moving from outside the frame? What if I want to load in images asynchronously in the BlueVC? Will I have to use a placeholder snapshot with placeholders until the BlueVC snaps in place?
This is all becoming so convoluted... I've done stuff like this separately (snapshots, custom VC transitions, etc..) but I'm not comfortable enough in combining them all in a case like this. I'm sure I can hack up some way given enough time, but I want to learn what is the best, cleanest way.
I appreciate any help! Thanks.
Edit after accepting #MilanNosáľ's answer:
I ended up using his framework as linked in this repo. It's not interactive yet, but I can figure out the rest using what they've very graciously done for me. I wish I could post the full code here, but that's not very practical. The repo will remain up indefinitely for future SO travelers.
I'm gonna shamelessly advertise my own open-source project, in which I am dealing with similar tasks - InteractiveTransitioningContainer. It's goal was to prepare a framework for implementing custom containers that allow interactive transitions between its child controllers. While this may not be a direct answer to the question, I spent many hours try to provide the same environment for the child controllers as standard containers do - e.g., make sure their view(Will|Did)(A|Disa)ppear callbacks are called in right order - I had to experiment with the UINavigationController to analyze its behavior, etc.
So if nothing else, maybe you'll find some inspiration/knowledge there.
What you really needs is creating custom segue to move from the current VC to the destination VC and override perform method like that , in this code snippet current VC moves up and destination animates from bottom to top , feel free to change any way
override func perform() {
// Assign the source and destination views to local variables.
var firstVCView = self.sourceViewController.view as UIView!
var secondVCView = self.destinationViewController.view as UIView!
// Get the screen width and height.
let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
// Specify the initial position of the destination view.
secondVCView.frame = CGRectMake(0.0, screenHeight, screenWidth, screenHeight)
// Access the app's key window and insert the destination view above the current (source) one.
let window = UIApplication.sharedApplication().keyWindow
window?.insertSubview(secondVCView, aboveSubview: firstVCView)
// Animate the transition.
UIView.animateWithDuration(0.4, animations: { () -> Void in
firstVCView.frame = CGRectOffset(firstVCView.frame, 0.0, -screenHeight)
secondVCView.frame = CGRectOffset(secondVCView.frame, 0.0, -screenHeight)
}) { (Finished) -> Void in
self.sourceViewController.presentViewController(self.destinationViewController as UIViewController,
animated: false,
completion: nil)
}
}
see more info is here custom-segue-animations
I initially had Milan's answer selected as the final answer to the question. But, after I tried working on it for the past few weeks, with a lot of help from him, we both agreed it was too difficult to integrate his framework into a format useable for this task. I'm now working on just using a UIScrollView for the ViewControllers below, and let the HeaderView above (the thing with the labels) control the ViewControllers' scroll view below.
I am attempting to implement a "Share" feature in my iOS app with a similar look and feel to that of the Google Photos iOS app:
The bottom two rows of icons are what I care about. They look nearly identical to those displayed when using the UIActivityViewController.
In the Google Photos app, these icons appear inline with the "select photos" portion of the screen (e.g. you can still interact with the upper portion of the screen). However, the documentation for the UIActivityViewController states that "On iPhone and iPod touch, you must present [the view controller] modally."
This is the difference that is really important to me -- I'd like for the "share" icons to display inline with the rest of my content, rather than having a modal that is displayed on top of my content.
Is it possible to use the UIActivityViewController to achieve a similar effect shown in the screenshot above? If not, is there a recommended approach that I might use to implement this sort of functionality?
As discussed in another answer, reverse engineering UIActivityViewController is the only option in order to be able to achieve a similar effect. I tried this using iPhone 6s - 10.3 Simulator. The following findings may not be accurate for iOS 9.x or 11.x or above.
A. Find out all internal variables for UIActivityViewController
var variablesCount: UInt32 = 0
let variables = class_copyIvarList(UIActivityViewController.self, &variablesCount)
for i in 0..<variablesCount {
if let variable = variables?[Int(i)] {
let name = String(cString: ivar_getName(variable))
let typeEncoding = String(cString: ivar_getTypeEncoding(variable))
print("\(name)\n\(typeEncoding)\n\n")
}
}
free(variables)
The ones those got my attention at first sight are (in order) -
_activityViewController
#"UIViewController"
_contentController
#"_UIActivityViewControllerContentController"
_activityAlertController
#"UIAlertController"
On inspecting them further, I found out that _contentController is the one we should be looking for. We need to look one level deeper in hierarchy for UICollectionViewController to get to where we want to be.
if let activityContentController = activityVC.value(forKeyPath: "_contentController") as? UIViewController {
print("Found _contentController!")
for child in activityContentController.childViewControllers {
print(String(describing: child))
if child is UICollectionViewController {
print("Found UICollectionViewController!")
break
}
}
}
Why did I look for UICollectionViewController?
Debug View Hierarchy has the answer for this.
I tried adding this as a childViewController to my UIViewController -
self.addChildViewController(child)
child.didMove(toParentViewController: self)
self.view.addSubview(child.view)
child.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
child.view.topAnchor.constraint(equalTo: self.view.topAnchor),
child.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
child.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
child.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
])
IT SHOWS UP CORRECTLY ONLY IF YOU HAVE LOADED/PRESENTED UIActivityViewController FIRST.
I was able to achieve this using a silent present/dismiss call -
self.present(activityVC, animated: false, completion: {
self.dismiss(animated: false, completion: nil)
})
IS THIS APP STORE SAFE? - Most likely not.
As soon as you start stealing the view(s) or viewController(s) from UIKit's standard components, the behavior is not stable and it will break with upcoming updates for sure.
What Google Photos has is the result of way more advanced reverse engineering. In above implementation, you can't see More option screen. The hierarchy UIActivityViewController expects is broken.
Hope this helps.
Okay, I thought about this and I did some intensive research on the web but nobody ever seemed to needed to modify it like you want. So here are my guesses how Google engineers solved this:
They reverse engineered the UIActivityViewController and call some private APIs to get the same icons to show up and the reordering controllers
They use the UIViewController transitioning API and hack the view hierarchy of a modally presented UIActivityViewController, removing the cancel button and adding some custom views on top of its view
An indicator for the second option could be that the top of the presented "sheet" has a white background while the bottom has the greyish color.
Unfortunately I'm not very fit with the transitioning API as I'm just about to learn it but my understanding is that you can provide a custom object as the transitioning delegate.
This object then gets called when you present/dismiss or push/pop a UIViewController. It will get a reference to both, the presenting and the presented view controller and you can have fun with both of their views.
This should make it "quiet" easy to remove and add some subviews, change frames and colors etc while still having all the default behavior.
I hope this answer helps you to achieve what you want. However, be aware that the structure of the controller could change at any time so always make sure to also test agains betas so that you don't get caught by surprise when apple releases an update which breaks your UI. :)
I added multiple UIImageView to a Viewcontroller with Swift Code like that:
let imageView_pergament = UIImageView(image: UIImage(named: "pergament.png")!)
...
...
view.addSubview(imageView_pergament)
And I would like that they shows up with an transition like effect (pixel in etc.)
Can someone please help with that did not find a solution yet. Same would be good for removing / hiding them. Maybe, I just need to put a view around it?
Thanks a lot for any help.
In iOS, the easy way to perform animation as a view is added or removed is by calling animate:
https://developer.apple.com/reference/uikit/uiview/1622451-animate
One typical strategy is to add the view with alpha of 0 and animate the change of alpha to 1, thus causing the view to "fade in". However, by animating the transform you can achieve vastly more interesting effects if you wish.
Built-in Photo application fades in/out navigationBar when you tap on an image . This way Photo app allows to see it full screen.
How does it do this (fade efect)?
As I understand navigationController?.navigationBar.alpha doesn't work anymore (so you can't animate it this way).
Sharing all my finding.
Complain mode on
Frankly, I feel half pissed/like a dummy that I had to fight a good day to implement simple thing existing in Apple app.
Complain mode off
First of all here is some context. I am working with navigationBar which are provided by navigationController (vs just standalone bars which are manually dropped in your view)
There are several approaches which I found. I will mention all of them (even if I had no success using them)
1) Animate change of alpha of navigationBar
UIView.animateWithDuration(0.1, animations: {
navigationController?.navigationBar.alpha = 0
}, completion: nil)
#rmaddy mention here that it works for him. However, I believe he has a standalone bar (vs a bar managed by navigationController).
I used a tool Reveal to check UI hierarchy and found couple of things.
- There is a navigationBar which is hidden (and navigationController?.navigationBar is referencing it). So you can change alpha to your hearts joy, but these changes won't be visible.
There is however another navigationBar . I assume it's referenced in some private members of navigationController (let's call it private navigationBar). It's visible and that's what is displayed at the top of your view.
2) Use setNavigationBarHidden:animated:
This is a standard way to hide/show navigation bar. It's animated different way (it slides/up and down). However, if it's ok for you, just go with this is, because it's simple and clean.
navigationController?.setNavigationBarHidden(true, animated: true)
Additionally you can wrap it in UIView.beginAnimations, UIView.commitAnimations to animate it together with some other stuff (to make it smoother)
3) Animate change of alpha of private navigation bar.
This worked for me:
let privateNavigationBar = self.superview?.superview?.superview?.superview?.superview?.superview?.subviews[1]
UIView.animateWithDuration(0.1, animations: {
privateNavigationBar.alpha = 0
}, completion: nil)
I am going way up through the hierarchy to get a view which contains private navigationBar (which is second subview for that view).
However, this approach has multiple downsides:
I believe # of superviews? depends on your app hierarchy (vs you are using split view and so on). I think you can generalize or may be you just walk the whole hierarchy to find non hidden UINavigationBar to solve this.
I have a feeling that Apple may frown at this (your app be not accepted to AppStore)
4) Make navigationBar transparent and set background image to be transparent and change alpha channel on it.
I can't find where I read about this idea. There was couple of mentioning.
There is Apple example app which shows how to customize NavigationBar, including making it transparent.
It's interesting that this example app works for me (the navigation bar is transparent in it). However, when I tried this code in my app it didn't work (I still didn't figured out what is going on with this). As usual there are bunch of variables (may be something in Info.plist, also they subclass NavigationController, also may be something in view hierarchy)
5) Adding standalone navigationBar
You can hide a bar provided by navigationController. Add your own to the UIView, wire it to #IBOutlet and use alpha animation on it (most likely that's what #rmaddy was referring too).
I checked and this is work.
This approach is used in this tutorial.
However, it has a downside:
I believe it won't handle well rotation, increase of statusbar height while call or GPS
Each time when I see a code like this (written in the article) I know that there will be problems with resizing: CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 64.0)
You can potentially replace it with constrains. I went this route, but stumble upon some issues.
6) Other methods
I saw two more methods. I don't know whether they will work or what will be downsides:
One of them in this question: How to hide/show status bar and navigation bar by fading in/out at the same time like the Photos app in iOS 7?
And this answer: https://stackoverflow.com/a/18063898/422080
Note: Using Monotouch and doing all the UI Programatically.
Hello everybody,
I have a question.
I have this main UIViewController object, and I have 2 UIVIews inside it. This views will perform commands in some devices, etc. I'm planning to do some menu with a slider effect appearing from the left side as it's drawn below. In this menu the user will select some buttons, and this is gonna make to change the another two UIViews.
Here's my question:
I'm planning to use Modal View Controller as UIModalPresentationPageSheet, but how can It appear at the center of the screen horizontaly. I'd like to put it on the center on the left side. How can I change it?
If it's impossible, should I use the UIPopover?
Image Below
Thank you.
Lyniker
I don't think either will get you the animation effect you want. In general I would choose to slide in a view using UIView animation:
if(IsDrawerVisible == false) {
UIView.Animate(0.5, () => {
DrawerView.Frame = new RectangleF(
this.View.Bounds.Left + 300,
DrawerView.Frame.Y,
DrawerView.Frame.Width,
DrawerView.Frame.Height);
}, UIViewAnimationOptions.CurveEaseIn);
}
else {
// Move the frame of the DrawerView by subtracting from Frame.X
}
Of course you need a reference point (usually the parent UIView's left bounds) and do the appropriate calculations to move the "Drawer" component into view. This can be arbitrary though :-)
NOTE: If DrawerView is of type UIViewController / DialogViewController please use the new iOS 5 custom containment APIs or you'll get some seriously wonky behavior. See my blog post on child view controllers here:
http://blog.devnos.com/wont-somebody-please-think-of-the-children