Can Xcode8 customize a toolbar depending on size classes? - uibarbuttonitem

I want, using the storyboard, to add a UIBarButtonItem to a UIToolbar, but only for width:Regular and height:Regular devices.
In the bottom of the storyboard, I activate „Vary for Traits“, and select width and height, so that only iPad devices remain.
If I draw an UILabel to the canvas, the attributes inspector shows me, as expected, 2 „installed“ fields, one for all devices (unchecked), and one for wRhR devices (checked):
However, if I draw a UIBarButtonItem to my toolbar, these fields are not shown.
Does this mean that a toolbar cannot be customized depending on size classes?

Briefly speaking, size classes, or vary for traits, only work for UIView objects, but UIBarItem/UIBarButtonItem inherits from NSObject, not UIView.

Related

How do I drag a UIView subclass into Interface Builder?

I'm following Apple's tutorial on adding a custom UIView sublcass to Interface Builder. They tell me to first label my UIView subclass. I have done that:
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface LoggedOutView : UIView
#end
Then they tell me to drag that UIView subclass from the Object Library in Interface Builder. I don't know where exactly is the Object Library. I am guessing it is the box in the lower right of the screen that shows all the standard UIViews. I search for my class in all 4 sections of that box and cannot find it.
Keep in mind that this is the first time I've ever used Interface Builder. I usually code all my UIView subclasses. However, I was forced to create a XIB for iOS 8's dynamic launch screens. (At least I think XIB's are required to flexibly layout launch screens on iOS 8).
Quick answer: you don't.
The launch screen does not load any code at all. It is merely a nib file that allows you to use auto layout to layout views on a screen. You can use text in labels, images, etc...
It's there so you can create launch screens for all different sizes of device and they will all be laid out correctly by AutoLayout.
You can't run any code though. Just use a plain UIViewController and standard UI elements UILabel, UIImageView, etc...

Autoresize the root view when device is rotated

I am developing PDF reader. I am facing problem while rotating the simulator. What I am doing is, when view is loaded by the ViewController(i.e. in the loadView), I am creating the UIScrollView which contains UIImageView and UIView of the same size(i.e. size of the PDF page). It is working perfectly in the portrait mode. But when I rotate the simulator in the landscape mode, the view is not autoresized according to device. I have tried
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
in the viewDidLoad() of the ViewController
But it's not working. I am confused how the above two properties work. I guess these properties will autoresize the UIScrollView to the size of root view in which I am loading UIScrollView. But what should be done to autoresize the main view in which UIScrollView is loaded??
I've experienced the same problem when trying to utilise the auto resizing methods. So, I hope this will help. (P.S. I'm assuming you're creating the UI programmatically and not via IB)
So have you tried this?
Inside your viewcontroller add the following:
// Set the View Controller to fit the whole screen.
-(BOOL)wantsFullScreenLayout{
return YES;
}
Inside the loadView method amend your scrollView to:
// set the initial size of your scrollView object.
[scrollView setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
// Set the auto resizing attributes.
[scrollView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
In addition to this you might need to set the autoresizingmask margins for either the UIView or UIImageView depending on the type of layout you require when the device is rotated.
This is late reply... It may help if you didn't Fix it yet.
When you create any app in portraid mode and if you want it to rotate (resize) to landscape mode, you should do it in User Interface Builder or .xib (or in Storyboard iPad or iPhone)file.
So to check or to check rotate in the Simulator:
Go to "USER INTERFACE BUILDER", or ".XIB" (or "Storyboard iPad or iPhone") file.
Then select "UIImageView" and go to "SHOW THE ATTRIBUES INSPECTOR".
In the fourth tab (Attributes Inspector) set the mode to “Aspect Fit”, and in the third tab (Size Inspector) and in the fifth tab (Size Inspector) set the autosizing attributes to the following:
Set the arrows to all directions. Sorry can't load image.
Do the same for "UIView" (3).
Before you move on, you can double check that you’ve gotten all of the autosizing attributes right by selecting the Detail View Controller, and changing the orientation from Portrait to Landscape: Sorry can't load image for now...
You can Check or Change to "Landscape or Portrait" on the top right side "Simulated Metrics" select under "Size" the "Orientation".
If something isn’t right, don't worry: Just change it back to Portrait and double check the settings.

UIScrollView created in Interface Builder scrolls out of the view

I'm trying to create a scrollable area in the middle of the screen - above it are a few non-scrolling labels, and below it are some non-scrolling buttons, so I only placed the UIScrollView in interface Builder in the middle of the window. I set the outline of the UIScrollView to be the full width of the iPad, 768 pixels, and about 700 pixels high.
I can place other UI elements within the UIScrollView as children of it, and I can scroll those by setting (in the view controller):
#define SCROLL_AREA_VERTICAL_HEIGHT 1200
...
[myScrollView setContentSize:CGSizeMake(768, SCROLL_AREA_VERTICAL_HEIGHT)];
[myScrollView setNeedsDisplay];
When I look at this in Interface builder, it seems to work, I can see only the UI elements that happen to fit with in the 700-pixel or so frame of the UIScrollView as set in Interface Builder. When I actually run it, though, I can see the UI elements that should be hidden below the lower boundary of the UIScrollView frame, and when I scroll up, the elements at the top don't become hidden by the top edge, but rather move up and over the labels on the top that are supposed to be static. In other words the boundary of the scroll area isn't actually hiding the elements that scroll off of it. What am I doing wrong?
Well i had a problem that was a bit like yours, don't know if it would work for you but try selecting the view in interface builder, and in the atributes inspector there is a box with a checkmark that sais clip subviews, check it and try. That was the solution for me. Hope it helps.

iOS. How Do Enable a Transparent Image to Pass Touches to a UIButton Below it?

For an iPad app I am writing I have a container UIView with two subview that are UIView subclasses:
A UIImageView whose image has a portion of it cut away to reveal what is below it.
A UIButton below the UIImageView that is revealed through the cut away portion of the UIImageView.
Since the UIImageView overlaps the UIButton spatially it is preventing touches from reaching the UIButton even though the UIButon is fully visible due to the alpha matte cutout in the UIImageView. How do I allow the UIImageView to pass touches to it's sibling UIButton?
Thanks,
Doug
UIImageView usually won't block touches, UIViews do.
You can set the userInteractionEnabled property on the overlapping views to NO, then touches should go through them.
An other approach would be writing a custom hitTest that redirects the thouches to the button.
In addition to Bastian's answer it was also necessary for me to uncheck the Opaque drawing attribute in interface builder for my UIImageView
Even with user interaction enabled, which is the default value when placing a UIImageView in Interface Builder, the touches should pass through to your button underneath, even if your image view has a solid background. Something else must be going on like a UIView sitting on top of the button.
If you are trying to do something more complex to get touches to pass through to underlying views or a separate view controller whose view is underneath, I created this simple open source library:
https://github.com/natrosoft/NATouchThroughView
The REAMDE and demo show how to use it.

NSTextField over NSOpenGLView

I have made a window with an NSOpenGLView that I am rendering openGL content into.
I want to add some buttons and text fields to the view: I can add NSTextFields and NSButtons using interface builder (or code) but they do not appear.
NSOpenGLView is documented as not being able to have sub views, so I then made my own CustomGLView by deriving directly from NSView and implementing the code to create and use a NSOpenGLContext in it. But the subviews are still not appearing :- the OpenGL context paints over them.
On Windows this problem does not exist:- Windows used to host OpenGL MUST have the WS_CLIPCHILDREN and WS_CHIPSIBLINGS styles set ensuring that any peer, or sub children (views) will not be obscured by the OpenGL surface.
How do I get subviews to display over a NSView thats drawing using OpenGL ?
You have 2 choices:
Create a window just for the text field. Add as a child window of the one hosting the OpenGL view. Major downside is you have to manage positioning it correctly if the Open GL view is moved.
Set up your view hierarchy like so:
Layer-backed view
Layer-hosting view whose layer contains an OpenGL layer
Text field
Simply call -setWantsLayer:YES on the subviews of the NSOpenGLView.
NSOpenGLView cannot have subviews according to the documentation. Even if you subclass the NSOpenGLView, that will change nothing.
What you can do is to create a NSView that will hold both the NSOpenGLView and the NSTextField. You then overlap them in the right order to make one draw atop the other.
I'm not heavily into OpenGL yet, but it's my understanding that you can accomplish the visual effect of subviews with Quartz Extreme using layer-backed views; however, those may be problematic. Since subviews are not supported directly, any solution is liable to be a hack.
Indeed, the solution in that link actually hacks a second window to appear over your OpenGL display, the second window displaying the Cocoa views you desire.
The following code (from the above link) is something I've not tested (again not being an OpenGL guy by nature -- yet), but appears like a fairly clever approach:
// This is the GL Window and view you already have
glWindow = [[GLWindow alloc] initWithContentRect:windowRect];
glView = [[[GLView alloc] initWithFrame:NSMakeRect(0, 0, windowRect.size.width, windowRect.size.height)] autorelease];
[glView translateOriginToPoint:NSMakePoint(glView.bounds.size.width/2, glView.bounds.size.height/2)];
[glWindow setContentView:glView];
// And here's your transparent UI window
uiWindow = [[TransparentWindow alloc] initWithContentRect:windowRect];
uiView = [[[NSView alloc] initWithFrame:NSMakeRect(0, 0, windowRect.size.width, windowRect.size.height)] autorelease];
[uiView translateOriginToPoint:NSMakePoint(uiView.bounds.size.width/2, uiView.bounds.size.height/2)];
uiView.wantsLayer = YES;
[uiWindow setContentView:uiView];
[glWindow addChildWindow:uiWindow ordered:NSWindowAbove];
Again, I've not tested this, but it looks like it will get you the visual effect you desire.
The text can be rendered into a texture -- I just used this for a project, did a lot of looking for sample code, and ultimately found Apple's GLString demo code, which was an absolute trove of how-to:
http://developer.apple.com/library/mac/#samplecode/CocoaGL/Listings/GLString_m.html
I haven't tried adding buttons, but you can, of course, draw your own and comparing the positions of click events with those of your buttons...
This was my solution:
1) Create a parent NSView (let's call it parentView).
2) Add an NSOpenGLView Child to parentView.
3) Add an additional NSView Child to parentView (make sure this is after the OpenGLView within the hierarchy). You can add additional TextFields, etc. to this view.
4) In the ViewController for the parent make sure you call [parentView setWantsLayer: TRUE]; I did this within -(void) viewWillAppear
1) The NSOpenGLView can have a subview. It can have plenty even.
2) The reason some views, controls and other elements are being bullied by NSOpenGLView is due to the loading process when the Application launches. I.e If you add a slider or textfield above and into the content view of the window where the NSOpenGLView also resides, upon Application-Launch that textfield will most likely wind up beneath the NSOpenGLView.
This is an Apple Bug. And they know about it.
You can solve it quite easily even without adding a subview to NSOpenGLView...
In Interface Builder drag i.e. a CustomView into the canvas (Not the view). And set it the way you want it with sliders, text and what not. Then create an outlet (Call it i.e topView) in your view controller. Then somewhere in your code... Perhaps (applicationDidFinishLaunching) add this line...
[_window.contentView addSubview:_topView];
(Do your positioning & layout)
This will do the exact same thing as if you had dragged it into the contentView yourself inside IB. Only it will draw the darn thing in the correct Z position.
You loose IB's constraints this way and have to it manually
One could also just subclass and CAOpenGLLayer and use that as a backing layer inside of a regular NSView. There too it is drawn correctly...
Here is Apple's way of wanting to do that. CALayers are a Godsend ;)
Enter following String ** NSOpenGLLayer** in search and hit enter to get to where it is...
NSOpenGLLayer
Hope this helps....

Resources