How to set the UIImageView's layer position relative to sibling views?
I mean like the swapDepths() / setChildIndex() in flash
many thanks for reading
It would be useful to describe what you are attempting in absolute terms, not by referring to another framework people may not be familiar with (particularly since "Layer" has its own special meaning in Cocoa.
If by "layer" you mean its position relative to sibling views then you can use the following functions.
bringSubviewToFront
sendSubviewToBack
exchangeSubviewAtIndex
Note that these are called on the PARENT of the UIView / UIImageView you wish to reposition. E.g. this would bring the imageview infront of its siblings;
[imageView.superview bringSubviewToFront: imageView];
Related
I will be creating a custom control (based on UIView).
Is there a way it could work with UIViewControllers using auto layout as well as UIViewControllers that do not?
The control should work in both cases. The difference is that in one case you will use constraints to layout it and in the other one, setting the frame programmatically.
If your control contains other subviews, it is important how you configure these. For example, if you do the setup of the subviews in initWithFrame: and you use the given frame to layout them (meaning static frames, instead of constraints), in the auto layout viewControllers, the frames will no get updated.
However, layouting the subviews with constraints will have no impact on the non-autolayout viewControllers. The subviews will have the layout according to your constraints, in the given static frame of the custom control.
It is a general explanation since I don't know that much about your particular controller. Hope this makes sense and you can find helpful.
I need to draw a line across a custom UIView(i.e. from top-left to bottom-right). However, as far as I know, the coordinate systems are different.
How can I translate between those two coordinate systems?
As long as we are talking about UIView objects that are subview of some other UIView object - the quite normal case - each View is positioned in relation to its next super view. The top left corner of the superview is (0,0).
For most applications that simply works fine. In rather rare cases there may be a need to transform coordinates from one views's sub-view-coordinate-system to that of another view. UIView provides the methods
– convertPoint:toView:
– convertPoint:fromView:
– convertRect:toView:
– convertRect:fromView:
for that usage. They work quite fine. Before you make use of them you should re-think whether that is required and evaluate whether your current view hierarchy could do with a re-desin. :)
Why don't you just draw it no matter what the coordinate systems is? Don't care about the coordinate systems.
I have a NSTableView that holds a name to all of my NSImageView's, and depending on the order that the NSImageViews were added, the last one would be in the front.
But in the case that I want the user to be able to bring a NSImageViews in front of another, how would I do that?
Thanks in advance.
As explained on the NSView reference page, the z-order of a view's subview is given by their oder in the view's subviews array. You can insert a new subview relative to the others using -addSubview:positioned:relativeTo:, and you can reorder the existing subviews by getting the subviews property, reordering the views therein as you like, and then calling -setSubviews: to set the new order.
Specifically, the docs say:
The order of the subviews may be considered as being back-to-front,
but this does not imply invalidation and drawing behavior.
What you are asking about, I think, is how to control the z-order of views.
For historical performance reasons this is not well supported in AppKit (unlike UIKit in iOS), since until somewhat recently you couldn't actually have sibling views that overlap.
A common approach to this (on recent OS X releases) is to use Core Animation (in particular, CALayer) which does support z-ordering natively, but this is probably overkill for what you need (and in any event is going to have a learning curve for you).
What are you actually trying to do? Are these images (image views) precisely on top of one another? If so, the easiest (and much better performing) approach is to have a single NSImageView and to just send -setImage:... to it to change the displayed image.
I noticed today, when adding 1 CALayer and 2 subviews to my view, when I run the following code in my UIView instance:
[self.layer.sublayers count]
This returns 3. Does this mean that a subview is also considered a sublayer? If I only wanted the CALayers that I've drawn in my sublayers call, how would i do that?
Yes, each UIView has an underlying CALayer which is added to its superview's layer when the view is added to the superview.
I don't know the ideal way to find only your own layers. Since sublayers is an NSArray (as opposed to an NSSet), it means it's an ordered list, which means you can be sure that the order in which you add views to the superview is the same order they will appear in said array.
Thus, if you add your UIViews first, and then add your own drawn CALayers afterwards, you can probably get your own by accessing the objects starting at index 2 (skipping 0 and 1) in sublayers.
Of course, if you then add or remove views to the superview you'd have to modify this value, so presuming this actually works, you'll want to somehow dynamically generate it.
You can ascertain the index for a layer as you add it, using indexOfObject: on the sublayers property. A safer route might be to simply store this index somewhere in a list and to access the sublayers with indices from that list only.
If I only wanted the CALayers that I've drawn in my sublayers call,
how would i do that?
You can do this by making the view that is currently a subview of self into a sibling view by having them both be subviews on a containing view. Then your current self.layer.sublayers would just contain the CALayers you added manually.
One way to think about it is that it is the layer hierarchy, not the view hierarchy which defines the render hierarchy. The view hierarchy is just a wrapper to handle interactivity that UIView adds to its underlying CALayer graphics. Thus, when you add a subview to a view, it simultaneously, though in some sense independently, adds its layer as a sublayer to the view's layer. You could probably override this functionality in a subclass or category on UIView...
From the CALayer documentation:
delegate
Specifies the receiver’s delegate object.
#property(assign) id delegate
Discussion
In iOS, if the layer is associated with a UIView object, this property must be set to the view that owns the layer.
Availability
Available in OS X v10.5 and later.
Related Sample Code
Afternoon, I have a UIImageView that I progmatically add to the window. Infact I have multiple UIImageViews that do so and when I click on any specific UIImageView I want it to become 'top-dog' so to say and be drawn over all other objects on the screen. Basically like the priority drawing for MSWindows operating systems when it comes to their windows. I've scoured all the options built in for UIImageViews when it comes to layering but I cannot seem to find any! I know it exists because in UIBuilder there is a command for sending back/front toBack/toFront. How do I access these progmatically?
Edit*
Also I fear that you might have to access the order in which the subViews are pushed into the 'subView stack' and manually move these around to achieve the result that I want and if so, how would I go about doing this?
Edit2*
Perhapse these are the functions I'm looking for?
bringSubviewToFront
sendSubviewToBack
exchangeSubviewAtIndex
Does this allow for easy Index shuffling?
UIView class has bringSubviewToFront: and sendSubviewToBack: for changing subviews z-order (see "Managing the View Hierarchy" section in class reference for more).