How to fix UISearchBar flick animation while transitioning view controllers? - ios11

From iOS 11 (and above) i try to incorporate large titles (with UISearchController). One of my screen doesn't have a UITableView as first child on the hierarchy (but rather UIPageViewController, this cause that the navigationBar is not collapsed because the scrollView is not the first child.. but due to structure design can't.. anyway that's not an issue).
When another screen is pushed (and that screen has navigationItem's largeTitleDisplayMode set to never), the transition animation looks weird (the UISearchBar is closed from the center and is not in sync with the navigationBar animation).
Note: If the controller that is pushed has largeTitleDisplayMode set to .automatic (or always) the transition is ok.
Background
When the prefersLargeTitle is enabled, navigationItem's searchController is set and the first view on the hierarchy is not a tableView (or i guess scrollView descendent), the navigationBar shows the searchBar open.
Options Tried
I tried modifying the translucent property of the UINavigationBar and UISearchBar. Also set the UINavigationBar's clipToBounds.
Code
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
self.navigationItem.largeTitleDisplayMode = .always
navigationItem.searchController = UISearchController(searchResultsController: nil)
}
}
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.largeTitleDisplayMode = .never
}
}

Related

How does using dynamic colors in viewDidLoad automatically switch the colors for Dark mode?

Per my understanding of the WWDC 2019 video "Implementing Dark Mode in iOS", dynamic colors are resolved using UITraitCollection.current. The updated trait collection is ready only in certain methods such as draw, viewWillLayoutSubviews etc.
So, if I use dynamic colors inside viewDidLoad, for example, the colors should not update automatically upon mode switch. However, they are being updated
Below is my code:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.backgroundColor = .systemBackground
let label = UILabel(frame: CGRect(x: 100, y: 100, width: 100, height: 20))
label.textColor = UIColor.label
label.text = "Label text"
view.addSubview(label)
}
}
The way I switched the mode in the simulator was Settings -> Developer -> Dark appearance. Then I brought my app to the foreground.
How did the color get auto-updated?
Note: I did not test in my device.
The colors you are using, systemBackground and label, are actually dynamic colors that adopt automatically when the trait collection changes. (Ok, under the hood it's more likely that the views that apply the colors react to trait environment changes and re-evaluate the colors.) That's why you don't need to do anything manually when using the system colors.
If you want the same behavior for your own colors, you have two options:
You can create a color set in an asset catalog. In color sets, you can define different colors for different appearances (light & dark mode and high-contrast accessibility colors). You can them get the color by the name of your color set in code (UIColor(named:)) or use them in interface builder.
Alternatively, you can use a dynamic provider block when creating the color in code, where you can determine the actual color based on the trait collection:
let color = UIColor { traitCollection -> UIColor in
switch traitCollection.userInterfaceStyle {
case .light, .unspecified: return .white
case .dark: return .black
}
}

Top Safe Area Constraint Animation

Setup
A simple view controller with a UISearchController set in the navigation item to use iOS 11's search functionality in the search bar.
Any view with it's top constrained to the SafeArea.Top
Problem
When presenting the search controller, the navigation bar is animated because of it's size change, but the constraint to top area does not follow the animation.
If anyone have an idea of what I can do (right now I guess my only choice is to disable the hidesNavigationBarDuringPresentation to avoid the animation at all)
See example below where I activated the slow animations for easier understanding:
You could animate the constraint change with UIView.animate. Since your constraint is based on the view's safe area, the viewSafeAreaInsetsDidChange method could alert you of changes in the constraint value :
override func viewSafeAreaInsetsDidChange() {
UIView.animate(withDuration: 1) {
self.view.layoutIfNeeded()
}
}
I faced the same issue on iOS 13.3.
This code fixed it.
override func viewDidAppear(_ animated: Bool) {
     super.viewDidAppear(animated)
     navigationController?.view.backgroundColor = .white
     navigationController?.navigationBar.isTranslucent = false
}
If you disable isTranslucent on viewDidLoad, searchBar would be hidden when the view appears.
You can also utilize navigationItem.hideSearchBarWhenScrolling to avoid putting the code in viewDidAppear.

Make custom item in UIActivityViewController icon colorful?

I follow the steps in How can I create a custom UIActivity in iOS? It works as expected. It looks like iOS force a metallic look&feel for all custom icons as well as its own "Bookmark", "Print", etc. Anyway to make my icon colorful?
As of iOS 6, it is not possible to do this.
All color data for the UIImage that is returned by UIActivity's activityImage method will be ignored.
In iOS 10, set the activityCategory class property to .share. This will cause the activity icon to appear in color in the top row of the UIActivityViewController.
In your UIActivity subclass:
In iOS 10, set the activityCategory class property to .share. This will cause the activity icon to appear in color in the top row of the UIActivityViewController.
In your UIActivity subclass:
class MyCustomActivity: UIActivity
{
...
override open class var activityCategory: UIActivityCategory
{
get
{
return UIActivityCategory.share;
}
}
...
}

Custom Segue with CollectionView for iPad

I have an iPad App I am working on. I have a UICollectionViewController with images displayed in the Cell.
On the MainViewController I placed a ContainerView that segues to a UIViewController that has a UIImageView.
This all (Above) works fine.
I want to set things up so I have a Custom Segue from the CellViewController to the UIViewController housing the UIImageView. I want this UIImageView to change based on the Image I select from the Cells displayed in the CollectionView
Can I create a Custom Segue to do this? I can't get any of the other segues to work because they are for SplitViews or Popovers, or Pushes.

Present Modal View in iOS 6

I want to display a modal view but I have two problems:
There is no presentModalViewController in iOS 6 and I have to use presentViewController which is just display my second ViewController like a modal segue not a modal window without full screen option,
My second problem is how can I show the modal window from UICollectionViewController. I tried to use presentViewController but it just works with ViewController not CollectionViewController.
The best example of what I want to do is this (Instagram). How they made this modal window? Is it because it's still working with older iOS versions and it's not iOS 6 yet? Or there is another way to display modal window like this from UICollectionViewController?
Thanks
If I understood you correctly what you are trying to achieve is to present one of your ViewControllers over the parent and still see the parent ViewController in the background.
First solution:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.view.backgroundColor = [UIColor clearColor];
self.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext; //self.modalPresentationStyle might do a better job here
[self presentViewController:vc animated:NO completion:nil];
Make sure your SecondViewController content is smaller than your current ``ViewController` and that you can see the background color of it in StoryBoard \ xib. The background color will be clear and will create the transparency effect.
Second Solution:
Create a Container (iOS 6 and up if you are planning to use the Storyboard IB, lower than that will let you create Containers but only progrematicly).
Set the container size 3/4 of the parent size and connect the second viewcontroller to it. Instead of segueing \ pushing to your second viewcontroller you can just
myContainer.alpha = 1;
to show it on screen.
I would take a look at the docs for UIContainerView which is used for displaying a view controller as a child of another view controller in a similar way to a non-fullscreen modal presentation.
As you are saying that presentViewController is only works with UIViewController not UICollectionViewController.
Then simply import UIViewController class in header file of CollectionViewController as displayed below:
#import <UIKit/UIKit.h>
#class UIViewController;
#interface MyCVController : UICollectionViewController
#end

Resources