How to "turn off" transparency inheritance from UIView to controls inside the view in IB? - interface-builder

I have a UIView in Interface builder (Xcode 4.1)that has its alpha set to 0.1 .
On top of that view, there are some UIbutton objects. These buttons are children of that view, not simple positioned on top of it - this I clearly see in the object explorer.
The problem is, those buttons inherit the alpha settings from their parent view.
How can I turn this alpha inheritance off?

Old question, I know. I was just hoping for the same (although it does not make much sense) and tripped over this. No, it's not possible. The alpha value is always inherited from the parent value, overall transparency of the child view is a combination of own and parent's alpha.
I'm not sure but there should not be any problems caused by placing the buttons on top of the 'container' view instead of inside it. If you absolutely need a common handle for them you can wrap everything in e.g. another UIView.

Related

NSVisualEffectView disappears when using a layer-backed view

My goal
I would like to add a vibrancy effect to a collection view.
The setup
I have the following view hierarchy:
When I use this layout, the background has the vibrancy effect as expected, but the performance is not quite there.
NSCollectionView is optimized to work with layer-backed views, so I enable the CALayer on the collection view's enclosing scroll view.
The problem
If I do this, the visual effect view is no longer visible, and the collection view has a white background.
My question
Is there any way to make a layer-backed view work together with NSVisualEffectView?
So if anyone's wondering, here's the trick:
adding the NSVisualEffectView: correct
making the enclosing scroll view layer-backed: correct
enabling the scroll view to draw a background: wrong
Make sure to either set drawsBackground to false, or disable it in Interface Builder, and your collection view will have the vibrant background, and fast scrolling as well 👍

How can I turn Cocoa Auto Layout off for subviews of a NSView programmatically?

I have looked at the other similar questions, but none of them addressed the question of truly programmatically bypassing Auto Layout for subviews of a NSView.
I would need to tell Auto Layout not to layout subviews of a particular NSView. I've tried overriding layout(), but this only generates a warning and the subview that has no constraints on it (I have set translatesAutoresizingMaskIntoConstraints = false on it, as I don't want any constraints to be automatically generated or otherwise) gets it's frame set to all zero's anyway [x=0, y=0, width=0, height=0]. I find it hard to believe that there is no way to tell Auto Layout not to layout a view. translatesAutoresizingMaskIntoConstraints = true is not what I am looking for, as I want to disable Auto Layout completely for all subviews of a view. I have two cases where I need this:
A note taking app where the user can create and position basic geometric shapes and text views. These are all NSView subclasses. I could of course use constraints and manipulate those but what is the point in a view that is not supposed to be adaptive in any way?
A math app where I use Auto Layout to layout mathematics on separate lines. I would want to turn Auto Layout momentarily off for the lines that are not beeing edited because as you add more lines and math objects, the autolayout calculation starts to make the app progressively more unresponsive. Since the only thing needing layout calculation is the line the user is editing, the process could be optimized by turning Auto Layout off for the other lines.
There is no way to do what you want.
Auto layout is ON or OFF for the whole window, not individual views. If any view in the window has had constraints added or is of a class whose +requiresConstraintBasedLayout method returns true, then the window uses auto layout.
If you want to use the old way of positioning a view, by setting its frame and its autoresizing mask, then you want translatesAutoresizingMaskIntoConstraints to be true. Indeed, that's the default for programmatically-created views precisely for backward compatibility for auto-layout-unaware code to operate in a window which is otherwise using auto layout. Your rationale for turning it OFF is exactly backwards.
Just leave or turn translatesAutoresizingMaskIntoConstraints on and have your code take responsibility for setting the view's frame to whatever it desires. Be sure to also set the view's autoresizingMask as desired, too, perhaps to NSViewNotSizable. You will generally need to deactivate any other constraints on the view for the duration.
If you need to do this for a whole view subhierarchy, then you will have to, well, do it — enable translatesAutoresizingMaskIntoConstraints and set the frame and autoresizingMask — for the whole subhierarchy. However, this doesn't seem like a reasonable approach to me.

If a NSView uses autolayout, do all of its subviews also need to use autolayout for positioning?

I have a view in a window, the position and size of the view are calculated with autolayout. The view has a subview, a draggable NSView subclass. It is really easy to make a NSView "draggable" by overriding -mouseDown: and -mouseDragged: and changing the frame of the view directly.
The view hierarchy is as follows,
What is the best way of making the subview draggable in this case?
For example,
Is it possible for the subview to not use autolayout, so that it can be positioned by changing the frame directly? i.e. the window positions the main view, but then autolayout does not layout the subview inside the main view. Or do all views in the hierarchy need to use autolayout?
When I have used autolayout before, I have used it to make "fixed" layout that respond to resizing. But dragging a view with a mouse does't seems like a natural use-case for autolayout.
Is it possible for the subview to not use autolayout, so that it can be positioned by changing the frame directly?
Yes. If you keep translatesAutoresizingMaskIntoConstraints turned on, it automatically creates constraints from the values of frame and autoresizingMask.
In fact, this means it will use Auto Layout, but you can work with frame just like with manual positioning.
The best way is to not avoid auto layout.
Making a view draggable is pretty easy with auto layout constraint IBOutlets and getting the mouse delta from NSEvent short circuit mouse tracking.

Xcode - Visually identify custom views in interface builder / storyboard

If you build a custom UIView, and integrate it inside of a parent view/view controller in interface builder, the graphical element representing your custom view is invisible, if you don't specify a background color (I don't).
Is there any way, solely during development, to identify different custom views? Any hacks/tricks to distinguish them?
The closest I could come up with is setting the background color in IB, then removing the background in the implementation of the custom view.
Bounds Rectangles
You might find bounds rectangles useful. You can turn them on by going to the menu bar and choosing Editor > Canvas > Show Bounds Rectangles.
Here's an example. I have a view (a UICollectionViewCell subclass) laid out in a nib. It has a single-line label, a two-line label, and a custom subview. The custom subview itself contains a smaller custom subview. Here's the nib with bounds rectangles off:
Here's the same nib with bounds rectangles on:
Background Color Override
Here's another technique that builds on the idea of setting the background color. This technique requires your deployment target to be iOS 5.0 or later.
As you described, set the background color to make the view visible in the nib:
Then switch to the Identity Inspector and add backgroundColor in the User Defined Runtime Attributes section. Set it to the background color you want the view to have at runtime. For example, if you want it to be white at runtime:
If you want the background color to be clear, you can set backgroundColor to a color with opacity 0, or you can set it to “Nil” instead of any color:
That approach of setting the background color in Interface Builder, but resetting it in code is a simple, but effective technique. Two refinements:
If you have multiple custom views on a single storyboard scene, you can save yourself from having to programmatically clear the background color for all of them individually by using IBOutletCollection. So, in Interface Builder, give them all background colors and then add all of your custom views for a given scene to a collection. You then can set the background color for all of them in a single statement. So, for example, if you have a dozen controls on one scene all in a single IBOutletCollection is named viewsCollection:
#property (strong, nonatomic) IBOutletCollection(UIView) NSArray *viewsCollection;
you can clear the background color of all of them in a single statement:
[self.viewsCollection setValue:[UIColor clearColor] forKey:#"backgroundColor"];
You can also make the identification of your custom views in Interface Builder a little easier by setting the "Label" in the "Document" properties on the "Identity inspector":
Once you've done that, when you look at the document outline in the left side of the main panel, you'll see your labels show up:
Then, using the document outline makes it easier to identify your individual views in the scene. You can use a random label like I did here, or you could use the name of your custom view class, or whatever.

Removing Border from NSBrowser

As the title says, I actually want to remove the border from an NSBrowser control. The parents are NSView and NSControl. There's no available methods in NSBrowser itself, and neither in the parent controls. This one seems completely undocumented.
As to the reason for removing the border, because it's programatically docked into another view, so the view hierarchy means there's a border already.
Any ideas?
Just embed it a plain NSView ("Custom View" in IB) and make the browser's frame "outset" by 1 point in all directions from the containing view's bounds. The containing view will clip the browser to eliminate the border. Then place that containing view into the surrounding view hierarchy, rather than adding the browser directly.
NSBrowser uses NSBrowserCell to implement its interface.
That inherits from NSCell.
NSCell should provide the methods you need.
From NSCell class reference...
Managing Display Attributes
– setBezeled:
– isBezeled
– setBordered:
– isBordered
– isOpaque
– setControlTint:
– controlTint
– setBackgroundStyle:
– backgroundStyle
– interiorBackgroundStyle
Remove the border on the NSScrollView that it is enclosed in.
Neither of existing answers worked for me.
Embedding in NSView looked like an acceptable workaround, but it clips the browser.
NSScrollView isn't superclass of NSBrowser.
Layer is not used for this border, it's nil.
NSBrowserCell has nothing to do with NSBrowser's border.
Use borderType: NSBorderType property (same as in some other classes), setting it in Interface Builder. In Identity Inspector (⌘+⎇+3) add to User Defined Runtime Attributes:
Key Path: borderType
Type: Number
Value: 0 (corresponds to NSBorderType.noBorder)
For those, who still looking for a solution. NSBrowser is the subclass of NSView. You can set an NSView layer's border width to 0:
(Swift)
self.layer?.borderWidth = 0

Resources