How to make NSSplitView collapsing animation smooth? - swift

I have a "two-panel selector" or "shoe box" implemented with an NSSplitView and two NSOutlineViews, one for each split item in the NSSplitView. Basically it looks like this:
[Window Toolbar]
| side | main |
The sidebar can be toggled by
func toggleSidebar() {
self.splitViewItems[0].animator().isCollapsed =
!self.splitViewItems[0].animator().isCollapsed
}
The problem
The animation is not smooth, especially when the "main"'s content are scrolled up below the toolbar (with the translucency effect).
Attempts
I have a customized subclass of NSTableHeaderCell with an overriding draw(withFrame:in:). I noticed the draw(withFrame:in:) method is called (per frame I guess) during the animation.
I also set the headerView of the NSOutlineView to be layer-backed, and set it as:
self.outlineView.headerView!.layerContentsRedrawPolicy = .onSetNeedsDisplay
self.outlineView.headerView!.layerContentsPlacement = .left
Other LayerContentsRedrawPolicys have been tried, not effective to the problem.
macOS's Finder
Finder has a sidebar hiding functionality. The animation is butter smooth. When in the outline mode, the column header has some suspicious transition going on.
Though we can't see how Finder optimized the animation, at least it shows that smooth animation is possible.
Any suggestions or answers will be appreciated.

Related

How to turn vibrancy off for a specific subview - Swift

I'm using swift. iOS 10.
I have blur/vibrancy views in the storyboard and I have another view (which contains labels, and a collection view) that I'm putting inside the vibrancy view.
The problem is that the collection view's cells (which are red buttons) look really lame when they're inside a vibrancy view (they get all discolored and faded and it doesn't look good). The label's look great though.
Is there some way I can turn vibrancy off for the collection view, but leave it on for the labels, etc?
I tried adding the collection view to a UIVisualEffectView with effect = nil. But that didn't turn it off.
Maybe there's some way to get the buttons to look better, so that could possibly be a solution too. But to keep it simple, I was just looking to see how I can turn vibrancy "off" for a specific subview of the vibrancy view.

Navigation bar title jumping right after flip transition

I have a simple UIViewController with a simple view. As a result of a user interaction, a new UINavigationViewController is instantiated and its view is being added as a subview to the view of the UIViewController. This takes place as part of an aninmation transition (flip).
This works quite well and the first view is flipped over in favor of the second view. But when the animation comes to an end (the UINavigationViewController's view fills the whole screen) the navigation bar items jump, i.e. the title jumps about 5-10 pixel from right to left, the buttons' jump depending on which side (left / right) they are positioned. During the animation you can see that the buttons are misplaced and that the jumping movement is kind of a repositioning.
Could anyone tell me the reason for this and give me some advice how to avoid this?
This is a little late, but there's no accepted answer and I've encountered this issue even fairly recently (albeit with an older app running on iOS 8).
If you encounter this issue and also see a warning along the lines of the following, it may be that you haven't properly set your root view controller in the app delegate:
Application windows are expected to have a root view controller at the
end of application launch
Modifying the app delegate as follows recently remedied the issue for me:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Other logic goes here
// ...
self.window.rootViewController = myRootViewController; // This was missing
[self.window makeKeyAndVisible];
return YES;
}
(I previously had some nearly-equivalent code that was setting up the view so everything displayed correctly on launch, but was not specifically setting the window's root view controller.)
I know it's annoying, but I have no idea why it happens, but in my experience, it happens in one of two cases:
Translucent navigationBar: maybe it had something to do with the fact that a translucent navigationBar sometimes sets a view's wantsFullScreen property (the view will then extend below the navigationBar).
During transitions: as you have described.
To avoid it, maybe a nice animation to fade it on an off screen before and after animation so as not to give the illusion of low quality.
OR
In viewWillAppear, assign the pixel value it's jumping to the navigationBar's origin.y. It's sad that it happens, but sometimes it just can't be fixed any other way.
This can be caused by partially-corrupt PNGs used for navigation bar buttons when the UIImages are resizableWithEdgeInsets:. If you're using custom button item images, try exporting them again using techniques known to produce reliable images (See blog posts by Marc Edwards at Bjango for a good start).
I recently had a problem that sounds identical to what you were experiencing. I found that using the [UIView performWithoutAnimation:^{}] block inside of transitionWithView fixed it.
During custom segue transition, view's navigation bar items are misplaced.

UISearchBar: how can I stop it resizing when clicked?

I have a UISearchBar (with UISearchDisplayController) as title view of UINavigationBar. There are also two buttons on either side of the searchbar within the navbar.
When clicking on UISearchBar, it becomes wider and covers the button on the right of it.
How can I stop it from becoming wider?
Things tried but didn't work -->
The widened search bar then becomes the original size if the device is rotated.
So, tried calling [searchBar setNeedsLayout] in -searchBarTextDidBeginEditing
All different auto-resizing mask options in IB
Edit: Didn't mention, but this is on iPhone (as we can put searchbar inside toolbar in iPad..)
Actually, taking hint from this answer if the search bar is put in UIView of desired size then this is set as title view of NavBar, it doesn't go wider !
But... Since you can't make cancel button to show/not show as you wish, I realized it's not so useful.
(As seen in this question/answer etc)

iPhone - how may I hide a view and let it's space be used by other view (like android visibility = GONE)

Do you know a simple (or not simple) way to hide a view (or anything like a view) and let the other views of the screen use the place left blank ? And make the opposite when showing back that view. Something like Android Visibility = GONE for layers.
As far as I know, using setHidden=YES only hide the view from the screen but does not rearrange anything around it.
On Android, there are 2 hidding method. One like visibility = HIDE, and the other : visibility = GONE.
Let's say we have 3 views each with an height of 100px.
On Android :
If you set view2 visibility = HIDE, it just hides, and nothing else happens.
If you set view2 visibilty = GONE, the view2 hides from the screen and the view3 automaticaly takes the place freed by view2.
That's what I'm looking to on the iPhone.
I imagine there no auto way to do this but do you know any snippet or code making this possible ?
Thank you
There's no auto-tiling in iOS, so the only way to do this is to resize each of the views to how you want them to be yourself, perhaps by implementing layoutSubviews on their superview.

UISwitch within UIScrollview nearly impossible to use

I'm using a UISwitch-Component at the bottom of a view that sits within a UIScrollView.
Now the problem that appeared, is that the switch is nearly impossible to swipe because the UIScrollView seems to dominate the userinput.
Switching works very well by tapping the switch, but from my point of view, most users "switch" the UISwitch instead of tapping.
Did anyone of you face the same / or similar problems and managed to come up with a solution?
thx in advance
sam
You have a design decision to make: if your content is meant to scroll horizontally, then a user swipe over a switch is ambiguous -- does it mean they want to scroll, or toggle the switch?
The easiest solution is to modify your UI so that this ambiguity disappears. For example, if the scroll's contentSize is not wider than the bounds of the scroll view, then it can't scroll horizontally, and a horizontal swipe will always activate the switch.
If you do want to allow horizontal scrolling, then it makes sense to replace the UISwitch with a UIButton that toggles on touch, similar to a play/pause button.
On the other hand, if you don't want to modify your UI, you could always just do:
myScrollView.delaysContentTouches = NO;
This will cause your switch to "get" the touches immediately, rather than have them go to the UIScrollView first. More info here. (You can also set this boolean in Interface Builder, as pointed out by Squeegy.)