Changing TabView: Resize TabView & Window - objective-c

I made an application which have a preferences window with 2 tabs.
The first tab have a lots of prefs settings in it, but the second one is very small...
I'd like that the tabview & the window resize when we switch between these 2 tabs.
I act like that, but it doesn't seems to work, when I switch view the "Networks settings" tab is being reduced and disapear (like if the height was going from origin to 0 with animation).
Here is my code (.m):
- (void)tabView:(NSTabView *)tabView
didSelectTabViewItem:(NSTabViewItem *)tabViewItem
{
NSRect frame;
int height;
if ([[tabViewItem identifier] isEqualTo:#"Panel settings"]) {
height = 400;
} else if ([[tabViewItem identifier] isEqualTo:#"Network settings"]) {
height = 200;
}
frame = [[tabView window] frame];
frame.size.height = height;
frame.origin.y += height;
[[tabView window] setFrame:frame display:YES animate:YES];
}
Note that I linked the tab view to delegate.
My window is linked to the NSWindow * PrefWindow referencing outlet.
Thanks for your help!

I still think the problem is with the way your springs and struts are set in IB -- make sure you set them for not only for the tab view itself, but also for the individual objects in the view of the tab view item. I noticed that the default settings for my subviews had them all with the top strut set which made any subviews near the bottom of the view disappear when the window shrunk.

Related

Intercepting UIScrollView Scrolls

I have a UIScrollView and a UITableView inside the UIScrollView.
I would like to intercept scrolling of the UITableView and only allow scrolling if the super view (UIScrollView) have reached a specific contentOffset.
I have created subclass of both UIScrollView and UITableView, how do i catch scrolling event and intercepting the scrolling while the user is still scrolling?
Example of what i'm trying to accomplish:
The UITableView is going to have a header, if i scroll down the header will collapse to 30% of original size and and stay visible at the top. After i have scrolled back to the top of the UITableView i want the header to expand. In other word i want to extend the scrolling of a UITableView with a header that can collapse/expand.
There might be better way to accomplish this, i'm open for suggestions.
There may be a better way, but this solution is working for me.
UITableView (let's call it innerScrollView) inside of UIScrollView (let's call it scrollView) inside whatever the main view is (let's call it view).
Set an outlet in your view controller for the innerScrollView (self.innerScrollView).
Set bounce in XIB or code to: scrollView.bounces = YES and innerScrollView.bounces = NO.
Set scrolling to disabled initially for the innerScrollView.
In code (viewDidLoad:) set scrollView.contentSize.height to view.frame.size.height + the 70% of the header you want to disappear. Resize innerScrollView to fill the resized contentView to the bottom.
Set your view controller as the delegate for scrollView and implement scrollViewDidScroll: as follows:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat maxYOffset = self.scrollView.contentSize.height - self.scrollView.frame.size.height;
CGFloat minInnerYOffset = self.innerScrollView.contentInset.top;
CGFloat currentYOffset = scrollView.contentOffset.y;
CGFloat newYOffsetDelta = currentYOffset - maxYOffset;
CGFloat currentInnerYOffset = self.innerScrollView.contentOffset.y;
if (scrollView.contentOffset.y >= maxYOffset) {
self.innerScrollView.scrollEnabled = YES;
self.scrollView.contentOffset = CGPointMake(0, maxYOffset);
if (currentYOffset != maxYOffset) {
self.innerScrollView.contentOffset = CGPointMake(0, currentInnerYOffset + newYOffsetDelta);
}
}
else if (currentInnerYOffset > minInnerYOffset) {
self.scrollView.contentOffset = CGPointMake(0, maxYOffset);
self.innerScrollView.contentOffset = CGPointMake(0, currentInnerYOffset + newYOffsetDelta);
}
else if (currentYOffset < scrollView.contentInset.top) {
scrollView.contentOffset = CGPointMake(0, scrollView.contentInset.top);
}
else {
self.lowerScrollView.scrollEnabled = NO;
}
}
I just whipped this up and quickly tested it. It all seems to work, but there may be some improvements and tweaks needed. Regardless, this should get you started at least.
Well, you should use the following UIScrollViewDelegate method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// here perform the action you need
}

NSWindow's top position is jumping during resize (auto layout)

I do heavily use auto layout in my new project, but I've got one issue related to NSWindow during resizing ...
NSWindow is borderless window,
during initial setup, frame of this window is set based on status item position and initial content view size (intrinsicContentSize of contentView),
vertical anchor attribute is set to NSLayoutAttributeTop,
horizontal anchor attribute is set to NSLayoutAttributeCenterX
... so far, so good. NSWindow is placed correctly, size is correct and everything looks good.
Whenever contentView is resized automatically because of auto layout, etc. final window position is correct, size is correct, ..., so again, so far so good.
What's the problem? When animation is in progress (window is vertically resizing), top of my window is jumping +- 1 pixel down/up/down/up/down/up/down/up/... until animation is finished. It looks pretty ugly ...
It behaves like this pseudo code ...
NSRect frameRect = window.frame;
while ( frameRect.size.height != desiredHeight ) {
frame.origin.y -= 1; // Move window down by 1px
[self setFrame:frame display:YES animate:YES];
frame.size.height += 1; // Increase window height
[self setFrame:frame display:YES animated:YES];
}
... it looks like auto layout changes origin of window and then auto layout realizes that the height should be changed as well, ...
Anyone did see this behavior?
Mea culpa, how can I missed it, it's because I do use NSLayoutConstraint for height of one of my views and I'm animating it via animator and it produces non integer values - so the height sometimes does contain real numbers and this is the cause for jumping top of NSWindow. Problem solved.

How to add a scroll view to an ios app

I have a tabbed application that I would like to have a scroll view on. I already have a few text fields and labels on that tab. The problem is, the keyboard hides some of the text fields. How would I add a vertical scroll to prevent that?
You can accomplish what you are looking for without a scrollview.
In you delegate method for you textfield, You can change the frame of the viewController's view.
something like
- (void)textFieldDidBeginEditing:(UITextField *)textField;
{
CGRect newFrame = self.view.frame;
newFrame.origin.y = - 40; // move the view up to the point your textfield is visible
self.view.frame = newFrame;
}
Then in Set it back
- (void)textFieldDidEndEditing:(UITextField *)textField;
{
CGRect newFrame = self.view.frame;
newFrame.origin.y = 0;
self.view.frame = newFrame;
}
Usually I animate this with 0.33 seconds duration.
The solution requires quite a bit of code, but here's the general idea of what you need:
You will need to add the text fields (and everything else for consistency) to a scrollView.
You need to setup the scroll view to have vertical scrolling space only, but set the scrollEnabled to false so that the user can't scroll it manually.
Then you need to listen to UIKeyboardWillShowNotification and UIKeyboardWillHideNotification and manually scroll it up/down as required.

ObjC - Resizing and Getting Window Dimensions

In objective C, I'm trying to resize an application window after a button is clicked. If the window was 200x200, a (+) button is pressed to make it 200x210 or the (-) button is pressed to make it 200x190.
I'm just not sure how to set the size of windows after they're made in the editor.
Don't have sample code because it's simple and I'm not sure where to start.
Here you go:
- (IBAction)plusButtonClicked:(NSControl *)sender
{
NSRect frame = sender.window.frame;
frame.size.height += 20;
[sender.window setFrame:frame display:YES animate:YES];
}
Depending whether you want the top or bottom of the window to expand, you may also need:
frame.origin.y -= 20;
Have a look at setFrame:display: in the NSWindow Class Reference.

Scrollable UINavigationBar similar to Mobile Safari

My application uses a UINavigationController and the final view (detail view) lets you view an external website within the application using a UIWebView.
I'd like to free up some additional screen real estate when the user is viewing a webpage and wanted to emulate how Safari on iPhone works where their URL bar at the top scrolls up and off the screen when you're viewing content in the UIWebView that's below the fold.
Anyone have ideas on how to achieve this? If I set the navigationBarHidden property and roll my own custom bar at the top and set it and a UIWebView within a UIScrollView then there are scrolling issues in the UIWebView as it doesn't play nicely with other scrollable views.
Based on #Brian suggestion I made this code:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat height = navigationBar.frame.size.height;
CGFloat y = scrollView.bounds.origin.y;
if (y <= 0) {
CGRect frame = navigationBar.frame;
frame.origin.y = 0;
navigationBar.frame = frame;
} else if (tableView.contentSize.height > tableView.frame.size.height) {
CGFloat diff = height - y;
CGRect frame = navigationBar.frame;
frame.origin.y = -y;
navigationBar.frame = frame;
CGFloat origin = 0;
CGFloat h = height; // height of the tableHeaderView
if (diff > 0) {
origin = diff;
h = y;
}
frame = tableView.frame;
frame.origin.y = origin;
frame.size.height = tableView.superview.frame.size.height - origin;
tableView.frame = frame;
CGRect f = CGRectMake(0, 0, tableView.frame.size.width, h);
UILabel* label = [[UILabel alloc] initWithFrame:f];
tableView.tableHeaderView = label;
[label release];
}
}
My code has a UITableView but should work with any scrollable component. If you have other components than the navigationBar and the UIScrollView subclass, you should change the way the height of the scrollable component is calculated. Something like this:
frame.size.height = tableView.superview.frame.size.height - origin - otherComponentsHeight;
I needed to add a dumb tableHeaderView to have the desired behaviour. The problem was that when scrollViewDidScroll: is called the content has an offset, but the apparience in Mobile Safari is that the content is not scrolled until the navigationBar fully disappears. I tried first changing the contentOffset.y to 0, but obviously it didn't work since all the code relies on the scrolling mechanism. So I just added a tableHeaderView whose height is exactly the scrolled offset, so the header is never really seen, and the content appears to not scroll until the navigationBar fully disappears.
If you don't add the dumb tableHeaderView, then the scrollable component appears to scroll behind the navigationBar.
With the tableHeaderView, the scrollable component is actually scrolling (as seen in the scrollbar), but since there is a tableHeaderView whose height is exactly the same than the scrolled offset, the scrollable content appears to not be scrolling until the navigationBar fully disappears:
Have a delegate for the scrolling events in the UIWebView and when you initially start scrolling the UIWebView, have the UIWebView increase in height and have it's Y position decrease at the same time while simultaneously shifting the nav bar up in the Y direction. Once the nav bar has been completely shifted out of view, stop increasing the size of the UIWebView and just allow normal scrolling to occur.
This will give the illusion of the nav bar being part of the UIWebView as it scrolls off the screen.
Also, you'll need to do the reverse when you are scrolling in the opposite direction and are reaching the top of the content of the UIWebView.
Can't give you a straight answer, but have a look at iWebKit. Maybe that provides a solution. The demo, at least, contains a "full screen" item.