Changing what is loaded by a nib file - objective-c

in my iPad application I have a panel of buttons, I have used an UIImageView as this panel and put buttons on top of it and created my nib file. in some views some button of this panel should not be displayed. so what i do is removing those buttons and decreasing the height of the panel (a UIImageView) then reposition the button to take up the space of the removed button. I have created outlets to all of these.
Is this the way to do this? My problem is if I want to change the order my buttons are displayed at some point I can't do it by simply changing the nib file. I'll have to do some changes in the code as well.

In this case don't use the nib to position the buttons in the first place. It sounds like this is one of the occasional cases where you would be better off working solely from code.
Instead of having to worry about some sort of abstraction that protects your layout if you decide to reposition the buttons and about removing and repositioning buttons, you can just do the layout at runtime once your particular view knows what buttons it needs. Your code is already doing much of the work of layout already (removing and repositioning).

Related

Can't seem to achieve the same effect on my slide menu as Any.Do

I am trying to create the same type of slide-up/pull-up menu (from the bottom) as the Any.do iPhone app, but not having any success.
The issue I am running into is the app was built with storyboards so I am thinking I might have to scratch that idea and use just code.
Any ideas?
There is no need to get rid of your storyboard to recreate this, that's what IBOutlets are for. Any way, it looks like this was made by creating a UIScrollView that takes up the entire screen. Then add a UITableView to the upper section of the scroll view. Mind you in order for this to work, you'll need to disable scrolling on the scroll view in the background.
From there you can programmatically add the other elements to the scroll view to be rendered off screen, since there are only three they can probably just be buttons. And finally, since scrolling is disabled on the background scroll view you can add an image with a UISwipeGestureRecognizer at the bottom of the screen to manually change the scroll view's content offset property.

How to prevent a UIView from consuming user input

I have a simple view hierarchy example.
Obviously the main view space is the primary space the user will interact with. At the bottom I have tabs that can pop up to indicate to the user where he/she is in the progression of the app. Normally, these tabs only take up the space indicated by the "Custom Tabs" rectangle at the bottom, but they can expand all the way up to fill the "Empty Space" box.
In order for the tabs to still be clickable, I had to make the tab view's frame the full rectangle containing both the "Custom Tabs" space and "Empty Space" space. What this results in is that "Empty Space" not being interactive to the user when the tabs aren't popped up, because the input is basically being consumed by that UIView, and not forwarded through the rest of the hierarchy.
I suppose the root of this problem is that both "Main View Space" and the "Empty Space + Custom Tabs" are both subviews of the main window.
Is there a way I can tell the system to forward the user input to the sibling views if the user didn't actively tap on an interactive element? For example, doing something with the touchesBegan, touchesEnded etc. methods that would indicate to the OS that this view did not use the input.
EDIT
Here's another version of the view, demonstrating the tate of one tab being open:
EDIT2
After some simple testing, it would seem that the default behavior is that the top most view gets the input first. This applies even if you have a clear UIView on top of a UITextField. The clear UIView will consume the input, preventing the UITextField from being editable
EDIT3
The way the tabs are supposed to work is the user can tap on a tab (sized as in the first picture), and then it will expand to display a thumbnail view associated with that tab (as in the second picture). The user can then optionally tap the tab once more to close it, and return the size to the original picture. In order for the tab to be clickable when it is open, I have to have the containing view be basically large enough to contain all 4 tabs as if they were open. This results in a lot of empty space in the containing view. This empty space results in essentially dead input space on the screen. If there were a button in the main view space that is covered by the empty space, the user would not be able to click on it. I would like to be able to avoid that behavior, and have that button covered by the empty space still be clickable.
Rather than trying to "forward" touches, I would modify your layout so that the tab view is only as big as the tabs, and change it's .frame to be the larger rectangle in code only when you need it. For example, when a tab is clicked:
CGRect tabFrame = tabView.bounds;
tabFrame.origin.y = top_of_emptySpace;
tabFrame.size.height = height_of_emptySpace + height_of_tabView;
tabView.frame = tabFrame;
then you can add the content you need. when you need it to go away, remove the content then do :
CGRect tabFrame = tabView.bounds;
tabFrame.origin.y = top_of_tabView;
tabFrame.size.height = height_of_tabView;
tabView.frame = tabFrame;
There might be some tweaking required to make the content show up as you like, but this way, when the tabs are minimized, you won't have to do anything extra to make the main view respond to touches correctly.
Ok, this is the way I would do it:
The RootViewController has two views, its main view which takes the whole screen, the one that is added to the window. And the tab view.
Then I would add another view controller (a UINavigationController ideally) to the RootViewController and I would have its view added as a subview of the RootViewController's view.
Any change performed, such as pushing new view controller or anything, would be done to the child view controller.
That way, your tab view would always be showing. To open a tab, you could create a new view that would show on top of the tab bar using an animation or something similar.

Is there another way than presentModalViewController to show a UITabBarController on just part of the screen?

I have a UITabBarController displaying a number of settings-screens in my app. I want them to be shown on just a part of the screen for layout reasons. In fullscreen, the lists become unreadable (too wide), there are just a few controls per page making the page feel very empty, and the tabbar buttons are far away from the content (Fitts law).
Using presentModalViewController with the UIModalPresentationFormSheet style gives me the size I want. I do this on top of an empty background, since in my case it doesn't make sense to display anything behind it. The "real" working area is displayed with another presentModalViewController in fullscreen mode on top of it all.
This works but feels like a hack. One problem is, I can't make the background behind the settings dialog move in the transition to fullscreen with the UIModalTransitionStyleFlipHorizontal style.
TL;DR
Can I embed a UITabBarController non-fullscreen in another "background"-view? I can't find any information of how I would do this.
Can I embed a UITabBarController non-fullscreen in another "background"-view? I can't find any information of how I would do this.
Why don't you try it out?
Create a container view of the size you want the tab bar controller to have.
Create the tab bar controller.
[containerView addSubview:tabBarController.view];

adding an invisible button to the background in IB

I'm working with Xcode doing a Ipad app.
i simply want user to click anywhere on screen (not counting text fields) to perform some IBAction.I'm using an invisible button that covers my whole view.
Since I have some text fields in my view,i need to add this invisible button to the background of my user interface. I cant seem to find this option in the button attributes? any help?
Just set the button's type to custom.
Did you try setting the opacity of the button to zero?
I guess i got your point. You just want to put the UIButton(invisible) on the back of all the UITextField. The simple solution to this is open the Document Window in the IB. Now expand the view tree in the list view. Just drag your UIButton above the UITextFields and set the alpha value for the button in the property to be zero.
Hope this helps!!
iPad users don't "click". They "tap" or "touch".
In Interface Builder, I believe views are constructed with a z-index from top to bottom as they appear in the document window, so dragging your button so that it appears as the first subview of your main view should be a quick fix for this.
Have you considered other approaches? This doesn't sound like standard behaviour for an app and will probably cause havoc with anybody using Voice Over. What are you trying to accomplish?

NSCollectionView as NSPopUpButton "drawer"

I would like to have something similar to the "List mode" of the stacks in the Dock.
But it should have the behavior of NSPopUpButton, in terms of displaying the selected object still, when the "drawer" is collapsed.
Each row should contain an image and to text columns.
How would you realize this?
Maybe subclassing NSPopUpButton, to display a CollectionView?
Or having an ordanary button and attaching a window containing a CollectionView to it, when clicked?
Oh and this up and down bars, instead of scrollbars on the side - how's that done?
Why not use a regular NSPopUpButton whose menu assembly is replaced with subclassed NSMenu/NSMenuItem that draws things the way you want? You get all the scrolling behavior for free.
If you insist on using NSCollectionView, however:
1 - Don't subclass NSPopUpButton if you're planning on popping up anything other than a menu. It's built to display a menu. Just use a regular NSButton and manage its -state (NSOnState while the collection view is displayed; NSOffState otherwise) manually.
2 - You could show a borderless transparent window (many examples available online) with a standard collection view / scroll view assembly minus the scroll bars. The borderless window could host the up/down areas (which can be simple views with NSTrackingAreas to detect mouse over). These areas could manually scroll the NSScrollView a bit every n milliseconds using an NSTimer while hovered.