+[UIView transitionFromView:toView:...] with multiple views - ios

So here's the situation:
I have let's say 20 views who are all subviews of the same view. Now I want to remove and add new views in an animated matter.
I previously did this by using regular UIView animations and fading them out or in respectively. The problem is though that the animation isn't flawless when the new subview who is to be inserted overlaps with the subviews who are fading out. So I tried using the +[UIView transitionFromView:toView:...] animation block to make the animation cross dissolve. This works well, animation looks good.
This basically solves my issue. The only problem is that it might be that I want to replace 2 subviews with one bigger subview. This doesn't really work out as I can't just pas nil to the transition method.
So my question basically is how I can simultaneously cross dissolve multiple subviews no matter how many views are animated?
Thanks for your help!

Have you tried putting the views to remove inside a transparent bigger view? So you just call transitionFromViewToView using the container with the 2 little ones inside and the big one that is entering?

You can use + [UIView transitionWithView:duration:options:animations:completion:], passing the common superview (usually self.view of your view controller) to perform all animations at once.
Excerpt from the doc:
This method applies a transition to the specified view so that you can
make state changes to it. The block you specify in the animations
parameter contains whatever state changes you want to make. You can
use this block to add, remove, show, or hide subviews of the specified
view. If you want to incorporate other animatable changes, you must
include the UIViewAnimationOptionAllowAnimatedContent key in the
options parameter.

Related

How to bring subview to front in interface builder without changing its position

I want to ask a simple question how can I temporary bring a subview to front to view its element without changing its position by dragging and dropping. The problem i face all the time is i forgot to put the views back to there position and that causes lot of trouble specially if you are working on the view that have large number of subviews.
Question : Is there any shortcut or any functionality that can show the view temporary without dragging, changing its frame or making any changes in its hierarchy.
For a view controller like this :-
FYI, for those who are wondering, the view closest to the bottom of the list (on the left) will show in the front. So in the case below, view 'a' will be in front of 'b' and 'b' will be in front of 'c'
XIB:
If you need your views to be readily accessible for viewing/editing without having to rearrange them, I would actually recommend breaking them out into their own view and then stitching them together in the correct order in your code. This will ensure that all elements will be put in the proper order and will always be easily editable. Something like this:
And then in your code, in somewhere like viewDidLoad:
[self.view addSubview:view2];
[self.view addSubview:view3];

Insert blur layer between two existing view layers

I have a UIView with some buttons on it. What I would like to do, is add a full screen blur layer between the UIView and the buttons when the user does a long press on one of them. The visual appearance and location of the buttons shouldn't change.
What is the best way to do this? Also, if possible, I would like to avoid transfering the buttons from one view to another, as this might cause me a lot of trouble (the buttons are draggable).
You can use -[UIView insertSubview:belowSubview:] method to place blur view behind buttons.
I would suggest using Pop animation framework for animations.
As for creating blur view this looks good: https://stackoverflow.com/a/25706250/2754158
You could create a view with the blur effect, and use the method view.insertSubView(blurView, above|belowView: view)

How can I trigger an update to all the autolayout constraints?

I modified programmatically one autolayout constraint. It takes effect on one certain view, but other views that are bound with other constraints to that view, do not change their positions. Is there an "updateAllConstraints" method?
Call those two methods on the view you want to be updated:
-setNeedsLayout
-layoutIfNeeded
The first one says to the layout system that this view needs to be laid out, because it has some changes and, everything should be recalculated. The second force the layout system to be run now, layout system is triggered at specific times during runtime, with this method you are saying:"do it now".
Yes There is a method on UIView called - (void)updateConstraintsIfNeeded
https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/updateConstraintsIfNeeded
However I don't think this is your problem
The problem was that constrains were not set up properly, and in this case non of the setNeedsLayout or updateConstraintsIfNeeded can help.
Those of you that come across this topic, and are looking where to find this in the menus.
Best I have found is:
Select the items that you want to "pop" back to your constraints
Top menu: Editor/Update Frames (or/) shortcut: command + option + =
Hopefully this helps

When do I need to call setNeedsDisplay in iOS?

When creating an iOS app, I'm confused as to when exactly I need to call setNeedsDisplay? I know that it has something to do with updating/redrawing the UI; however, do I need to call this every time I change any of my views?
For example, do I need to call it:
After programatically changing the text in a text field
When changing the background of a view?
When I make changes in viewDidLoad?
How about in viewDidAppear?
Could someone give me some general guidelines regarding when to use this method?
You should only be calling setNeedsDisplay if you override drawRect in a subclass of UIView which is basically a custom view drawing something on the screen, like lines, images, or shapes like a rectangle.
So you should call setNeedsDisplay when you make changes to few variables on which this drawing depends and for view to represent that change , you need to call this method which internally will give a call to drawRect and redraw the components.
When you add an imageView or a UIButton as a subview or make changes to any subview, you need not call this method.
Example:
You have a view that shows a moving circle, either you touch and move it, or may be timer based animation.
Now for this, you will need a custom view that draws a circle at given center and with given radius.
These are kept as instance variables which are modified to move the circle by changing its center or make it bigger by increasing radius of it.
Now in this case either you will modify these variables(centre or radius) in a loop and timer Or may be by your fingers in touchesEnded and touchesMoved methods.
To reflect the change in this property you need to redraw this view for which you will call setNeedsDisplay.
You only really need to call -setNeedsDisplay on UIView subclasses that draw their contents with -drawRect:.
For labels and other standard controls, changing the text will automatically cause the label to redraw so you don't need to do this yourself.
setNeedsDisplay: should be called when you want to refresh your view explicitly. It just sets an internal flag, and the iOS UI system will call drawRect: at an appropriate time later.
It sounds like it should be always called when you updating any property which may change the presentation. But it's not. Almost all the standard UI controls already handled that. I believe whenever you modify the properties of standard UI components (views), setNeedsDisplay: would be triggered internally, and the affected region will be redrawn. (In all the situations you listed)
However, if you create your own view, implement its own drawRect:, and want to update that when something has been changed, you must call setNeedsDisplay: explicitly.
I think #Amogh Talpallikar make it clear. And I just wanna discuss one thing more.
In the fact that, you should avoid override drawRectunless you really need it because it can cause bad performance. You can refer this https://yalantis.com/blog/mastering-uikit-performance/
If you only wanna change frame, position of buttons, labels, ... you can call setNeedLayout or layoutIfNeeded
You will call setNeedDisplay when you are changing the property on which your view custom drawing depends. It will explicitly call drawRect: method forcefully.

Custom input views: how to prevent them from fading during orientation change?

I am having trouble with assigning a UIControl subclass I made as a text field's inputView.
It shows - as expected - when the text field becomes firstResponder and hides when it resigns it firstResponder status.
However, the thing I am having trouble with is handling different orientations:
I set an autoresizingMask to the control's subviews so that there is a smooth transition when changing its width.
The thing is, they appear to be ignored as soon as I set it as the inputView.
When enabling the simulator slow-motion animations via triple-hitting shift, you can see very clearly that the view fades between the two states.
This is not what I want. Firstly it looks odd, and secondly this does not fit my needs.
Since the inputView contains a UIScrollView-like element, it would stop its deceleration animation during the fade.
Now my question is: Is there a way to prevent the fade from happening?
I would really like to use the inputView property since it saves me from writing lots of lines of code.
Also, is it possible to specify different heights for different orientations?
Here are two demo projects showing how it is and how I want it to be.
Thanks in advance.
You can create a method to your DatePicker class, that changes the geometry and layout of the view for different orientations and the implement the method
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
in your view controller and call the method on your view to align it.
Until today I have found no way to prevent them from fading.

Resources