How could I create a horizontal UIPickerView style control? - objective-c

I want to create a custom UIView that would be equivalent to a horizontal UIPickerView. The data elements, such as "Mountain View, Sunnyvale, Cupertino, Santa Clara, San Jose" would move left to right. The view would be long and thin. 50px in height, 350x in width sort of thing.
I will need to use protocols to obtain my datasource elements likely, but what I'm more interested in figuring out is the visual aspect of this.
How would I animate things left and right? Should I just make one incredibly long view (off screen), and change the frame left and right. This seems like a bad idea, as likely only 3-5 options need to be visible in the control at one time. If the datasource is 100 elements, there is no point in loading the other 95 off screen in a long view.
So perhaps I should load ~9 or something. The 3-5 on screen, plus an additional ~3 left and right. Each time the control is triggered to move left and right, it will load up another element on the view(?).
Is this a good way to achieve this? A long thin view with ~9 UILabel's. As the control moves to the right, I would shift the further left UILabel to move hidden to the far right, and change the UILabel to be the next in the data source.
I also likely want to change the text size based on its position. If it's currently selected, I either want to bold it and possibly increase the font size. How can I gradually achieve this as the view is moved? It would be weird if the text only changed once it was moved perfectly center inside the view. It should likely gradually grow as it gets closer to the middle.
How can I achieve this?

A collection view would do the trick, obviously there's some coding involved.
I'd suggest you to take a look at the code of, or use, the following library.
I've used it once,does almost exactly what you need and works very well:
AKPickerView

Related

NSTableView section banner column with custom height

I am trying to create the following layout with a NSTableView:
A big banner per section on the side and regular text content rows on the right side.
The Image on the left side is the problem. It should behave like a floating section when scrolling (stay below the section header). It seems impossible to have the view part of the NSTableView as each column of a row needs to have the same height.
I already tried a lot of things, but I need some input which is the right direction.
What I tried:
Add the image view as a floating view into the NSScrollView? That seems like a good approach, but it doesn't stick on top while scrolling and the (re)positioning within the table is... tricky. Any hints here?
Add the view into the section header and disable clipping somehow (to make them larger than the section)? Couldn't make that work.
Having a table with NSStackViews per row that host itself tables - that did work, but: Independent selections per table is not what I want.
Ok, I finally found a solution.
The view is added to the floating view container of the NSScrollView that holds the NSTableView. I use the bounds of the row views and translate that to coordinates of the floating view container.
I also modified the selection drawing to make it look good and recalculate the coordinates on animations.

Resizing & Layout: How to implement this design?

OK, this might seem very simple but I've been struggling for too long, so I decided to ask for some help.
Basical, I've got a container NSView.
The contents are (from left to right):
an NSSegmentedControl
an NSTextField
an NSSegmentedControl
And they are all aligned horizontally (= they're in the same "line").
What I'm trying to do is:
Fixed width for the first element, and fixed on the left
resizeable textfield
Fixed width for the last element, and fixed on the right
I guess it's pretty self-explanatory.
And here are my autoresizing settings for the 3 views:
View 1
View 2
View 3
And here's the issue: the whole resizing works fine. Until the textfield is resized at such a point where it is collapsed. When the superview/container is resized at a normal size again, the whole design is messed up (with the textfield overflowing the container and lots of such weird issue).
What's going on? Any suggestions?
Note: I got it to work with Auto Layout (merely setting "Auto Layout" and "Add(ing) missing constraints"), but I most definitely want to avoid it since the performance impact is huge -- the overall design is rather complicated, with lots of nesting, so let's stick to the old-fashioned way. :-)
The old springs-and-struts model using autoresizing masks is based on proportional distribution of the change in size based on the current sizes of the subviews being resized. Once any subview gets to zero size, it goes haywire. Either there's division by zero or multiplication by zero and you get bogus results. This is a long-standing issue with the system.
You must set minimum window size to prevent that from happening.
Auto layout is the solution to that and many other limitations of the old model, for all of its flaws.

UITableView w/ paging & momentum

OBSERVATIONS
I've discovered some "weird" things about how UITableViews / UIScrollViews scroll in Objective-C for iOS after you've lifted your finger:
A scroll view's "velocity" (as in scrollViewWillEndDragging:withVelocity:targetContentOffset:) is not based in time but rather based in "render" or "frame refresh" or the like; i.e., a "velocity" of 3.0 means that the scroll view will scroll 3.0 points before the next refresh, at which point it will scroll yet another 3.0 points if the "velocity" is still 3.0. (in contrast to an absolute time-based velocity)
"Refreshes" occur approx. 950 times per second, but this varies and is not dependable. (again, in contrast to an absolute time-based refresh rate)
Because UIScrollViews decelerate exponentially rather than linearly, decelerationRate is a geometric constant. This means that on every "refresh" of the scroll view, its "velocity" is set to its previous velocity times the "deceleration rate".
At some point, the scroll view's velocity is close enough to zero that it stops scrolling. I am not sure what this threshold is yet.
DESIRED BEHAVIOR / PROBLEM
I've derived an equation that can theoretically be solved to adjust the deceleration rate so that the scroll view can scroll naturally with momentum and settle close enough to the top of a table view cell to mimic "paging." (I also have an animation added to scrollViewDidEndDragging:willDecelerate: to adjust the content offset minimally. Adjusting content offset w/o adjust decelerationRate looks weird; the scroll view either jumps ahead or lurches backwards suddenly.)
This equation is: Ad^n + Bd + C = 0 where d = decelerationRate. Ideally I'd like something in the form of d(n, A, B, C), but my math PhD friend tells me that's not deterministically possible. He pointed me towards the following page: http://en.wikipedia.org/wiki/Root-finding_algorithm
I've also found that I can't animate a scroll view to a predetermined content offset using animation style UIViewAnimationCurveEaseOut because setContentOffset:animated: doesn't take an options: parameter. Otherwise I would "fake" scrolling to my precalculated content offset.
(I found this on SO but it didn't work for me: UIScrollview setContentOffset with non linear animation ?)
I'd like to use a table view because all of my elements in my scroll view will be cells essentially, and table views are best for displaying a list of cells. However, based on my difficulty getting my desired behavior, I might just make a paging scrollview, which will probably be easier. I can then just limit the number of "cells" visible in my custom "table view" or else load them post-hoc as necessary.
What are your ideas / thoughts / suggestions?
So far I have not found existing examples of what I would like.
ILLUSTRATION
OR
So this answer was obtained via a snarky but brilliant user on the #iphonedev IRC channel!
From within scrollViewWillEndDragging:withVelocity:targetContentOffset: you can just re-set the targetContentOffset to whatever you desire via *targetContentOffset = newTargetOffset;! Incredibly simple and elegant.
My mistake was trying to call [scrollview setContentOffset:newTargetOffset animated:YES] from within scrollViewWillEndDragging:withVelocity:targetContentOffset:, which didn't work at all, and therefore I set out to "solve" my problem in a more convoluted way that also didn't work at all.

How does the Reeder Mac app animate lists when switching folders?

Initially I was under the impression that it uses the table row slideup/down animations while inserting/deleting new rows but I doubt if it's doing that as it does it so fluidly even with thousands of items in the list (otherwise it would take a lot of time for the deletions/insertions to work).
Am I right in my assumption that it's simply attaching a new instance of the News list at the bottom of the screen, shrinking the above one while the one at the bottom expands to fill up space?
UPDATE:
Please see this video of what I mean: http://dl.dropbox.com/u/4960327/ReederAnim.mov
I can not tell you exactly how Silvio Rizzi made this, but as you see in the playback, a list view is added behind the shown list view, and the front list view fades out (.alpha = 0.0;) while the list view behind it expands its height per row.
When you desicate it frame by frame it becomes quite clear what he does, and it is really not that advanced. But I have to admit, with the white "milky" polished interface, it looks quite neat.
In addition, you can see that while animating, the background list view only renders the top 7 entries (hopefully calculated by dividing the view height with the average height of the cells shown) making the list view quick to load. Then afterwards, he can load an extended array of cells once you start scrolling, or in a background thread starting once the animation is complete.

How to center NSSegmentedControl

I've added an NSSegmentedControl to a pane on an horizontal split view on a normal window. I thought that adjusting the springs would make the segmented control centre itself automatically, but it doesn't. How can keep it centred?
I was told to add an observer for when the parent view's frame changes, and manually adjust the position of the centered view, but I've no idea how to go about that.
Any ideas are very welcome.
The layout you describe sounds totally plausible in IB.
Just testing it out, I dropped a segmented control in one of the views in a split view, and it stays centered, so I'm sure there's just a configuration issue.
Be sure that:
Your split view is set to stay centered and resize appropriately with the window as appropriate (just to make sure the behaviour you're seeing is not related to the segmented control's container not resizing properly).
You position your segmented control dead centre, and then leave all 3 horizontal "springs" unclicked (ie: no left anchoring, no right anchoring, no horizontal growing).
I don't know if it's been "fixed" in recent OS versions, but if I recall correctly, NSSegmentedControl does a -sizeToFit each time segments change. If the control isn't changing at all, Jarrett's instructions should work.