I am making an application that contains few layers on the image. This effect layers are children of UIView - EffectsLayerView. Effect1View, Effect2View and Effect3View are inside and few of them has UITextView. Those text views has UIPanGestureRecognize - I want to move them around the screen.
The structure looks like that
<EffectsLayerView>
<Effect1View>
<UITextView>
<Effect2View>
<Effect3View>
<UITextView>
Unfortunately only that last one (Effect3View) receive touch and move the textView. UIGestureRecognizers are added to those text views. How it should be done to make it working? Every EffectView and EffectsLayerView has their classes.
I will be glad for help.
There are 2 requiremets:
1) For every view: self.isUserInteractionEnabled = true
2) Every view mush have an unique instance of UIGestureRecognizer
Related
Below are how my views are organized in IB, top->bottom when the app is started.
The user can do something to make "Category Table View Header" temporarily expand over "Name View" - however once doing so, the .TouchDown action assigned to "Category Table View Header" no longer works wherever it overlaps with "Name View" (i.e., the user can tap the header anywhere it doesn't overlap with name view and it still works).
I know that may be confusing, so I drew out some boxes. On the left is the original, right is after user action - problem is on the right the action on the red box only works if the user taps the bottom half, not the top half.
My guess is its because the header is lower in the view hierarchy than the name view, but it would be hard for me to change that without messing around with a bunch of constraints.
I also tried setting nameView.hidden = true, but that doesn't work.
If you want to bring a subview to the front, you can use:
SWIFT 4 + UPDATE
self.view.bringSubviewToFront(yourView)
SWIFT 3 UPDATE
self.view.bringSubview(toFront: yourView)
Send view to back:-
SWIFT 4+ UPDATE
self.view.sendSubviewToBack(yourView)
SWIFT 3 UPDATE
self.view.sendSubview(toBack: yourView)
SWIFT 4+ UPDATE - INSERT VIEW ON SPECIFIC LOCATION IN THE STACK
parentView.insertSubview(yourView, belowSubview: requiredViewOnStack)
parentView.insertSubview(yourView, aboveSubview: requiredViewOnStack)
Swift 5.1+
UIKit draws views back to front, which means that views higher up the stack are drawn on top of those lower down. If you want to bring a subview to the front, there's a method just for you: bringSubviewToFront(). Here's an example:
parentView.bringSubviewToFront(childView)
This method can also be used to bring any subview to the front, even if you're not sure where it is:
childView.superview?.bringSubviewToFront(childView)
In Swift 5
To bring a subview to front
self.view.bringSubviewToFront(yourView)
To send a subview to back
self.view.sendSubviewToBack(yourView)
You can take a control over the order of subviews using methods: bringSubviewToFront and sendSubviewToBack from the superview.
You can access all the subviews contained by superview using self.view.subview array.
The method has been updated since swift 3
What has worked for me and hopefully for you is using :
YourView.bringSubview(toFront: yourelementA)
YourView.bringSubview(toFront: yourelementB)
Alternatively you could use the following to send the object that is in the front:
YourView.sendSubview(toBack: yourelementC)
I hope this helps
Swift 5.4
views in UIKit are drawn from the back towards the front (like adding icing onto a cake). This means that the new views will be placed on top/over the previously placed views. (e.g. Icing is the new view and the base of the cake being the old view.
You can use the following to manipulate the views Z-position using,
Forward
parent.bringSubviewToFront(child)
Backward
parent.sendSubviewToBack(child)
bringSubViewToFront did not work in my case, Take a look
As I wanted this notification count comes before image, bringSubViewToFront did not work, So I just drag this label below to stack view of my imgae and bottom label, it worked for me.
I hope this will work for all
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)
Context
I am using this simple library to make an intro/walkthrough for my app (TL;DR, horizontal paging view controllers). I currently have 3 pages setup.
In the 3rd walkthrough page, I have a custom CALayer that animates a circle in an endless loop. I'd like to add that layer to a UIView in order to lay it out the way I want in IB (via auto layout).
In viewDidLoad (for the 3rd page) I create the circle layer and set its frame to be the same as the view I positioned, assuming the circle would be in the same spot as the view:
for v:UIView in [view1!, view2!] {
var pulse = PulseLayer()
pulse.frame = v.frame
pulse.cornerRadius = v.frame.width / 2.0
pulse.masksToBounds = false
view.layer.insertSublayer(pulse, above: v.layer)
}
Problem
When I run the app in the iPhone 6 simulator, the CALayers show up OUTSIDE their UIViews (see below).
One thing I noticed immediately is the layers are not misplaced the same way--one is above its view, and the other is to the left. I am assuming this is related to the constraints on the views, but I cannot figure out how to fix it.
Equally baffling to me is that when run on the iPhone 5 simulator, the layers appear exactly as I expect them to (see below).
I feel like I am misunderstanding some of the concepts at work here. How can I get the positioning to act the same? (Like the iPhone5 gif.)
Or, is there a better way to do what I am trying to do?
viewDidLoad is too soon. Remember, viewDidLoad is way early; the view is not in the interface yet and nothing has its ultimate size/position. If you're going to add the layers to view rather than as sublayers of the little views, you will have to run your layer-creation code much later, in order to get the position right. viewDidAppear: or viewDidLayoutSubviews will be safe - but of course you must use a bool flag so you don't do it too many times.
Personally I don't see why you don't add the layers to the little views. So you would just set pulse.frame = v.bounds and add as a sublayer to v, not to your view. It solves the positioning and gets the relationships right. And doing it in viewDidLoad would work, because when the views move, the layers move with them.
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.
I want to have one large button on the screen that performs an action when single-tapped. I also want there to be 6 buttons within the large button that perform different actions when double-tapped.
I am thinking of making the large button a simple UIView, adding a UITapGestureRecognizer to it, and then adding the 6 buttons within that view with UIControlEventTouchDownRepeat and checking if tapCount == 2. Any thoughts on the best way to do this?
Be aware of the [UIView handleTouches:] method. You can use it to determine which view handles the touch based on the tapCount, instead of having to figure out which button the user tapped from the position within the superview