What is the right way to create scrollable table in SKSpriteKit? - ios

I need a way to display a leaderboard - best user scores (local user, local scores).
Do I need to create my "own" node for this kind of thing, or its better to use UITableView above SKView with transparent background?

An approach I use is:
In the scene's didMoveToView: method, set up a UIScrollView instance. Set all the properties you need, and make sure to also set its delegate, set hidden=YES and add its panGestureREcognizer to the view gesture recognizer collection.
In willMoveFromView: tear it down and clean it up.
In the scrollview delegate, implement scrollViewDidScroll:. Here you can use the scroll view's contentOffset point to adjust a node's position.
I have implemented an offsetable node that I use as a root node for things I need to scroll. All it does is implement a contentOffset property - you can see it here: CATOffsetNode Gist.
So in scrollViewDidScroll: all I need to do is:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// I don't need to flip scrollView.contentOffset.Y because my scrollview
// Y coordinate is flipped. See below.
self->_gameListNode.contentOffset = scrollView.contentOffset;
}
Then I add all the items I need to scroll as children for _gameListNode.
The result is a scrollable game list, which offers a native scrollview experience, including bounciness and swipe acceleration etc.
Here is an example implementation you can check out: ScrollKit on GitHub.
Edit: note about scrollview contentOffset Y direction:
UIView and SpriteKit Y coordinates go in opposite directions (UIView's origin is top left, and Y increases downwards), and I prefer to stick to one coordinate system. So I've made a custom scrollview class that flips the Y direction in the initializer. E.g.:
-(id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
CGAffineTransform verticalFlip = CGAffineTransformMakeScale(1,-1);
self.transform = verticalFlip;
}
return self;
}
This is not necessary (and you don't even need to subclass UIScrollView to achieve this) but without this you would have to manually flip contentOffset.Y in the scrollview delegate.

Game center offers leaderboards. Maybe you can use those? Game Center Programming Guide

Related

Easy zooming UIScrollView

I have an UIScrollView with many buttons and some labels. My question is: How can I easily zoom UIScrollView content (with two fingers)?
Thank you very much.
UIScrollViews already support zoom using pinch gesture, you just need to implement the delegate method
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
// Return the view that you want to zoom
return self.viewZoom;
}
Returning the view you want to zoom.
As Andrea pointed out the UIScrollView already supports zoom feature.
Follow these steps:
Add a UIView (say viewZoom) to the scrollView by giving same width and height as that of scroll view.
Add all UI components (Buttons etc) to viewZoom.
Set maximumZoomScale property of scroll view to '2' (or any other value as per your requirement).
Set your view controller as delegate to ScrollView(scrollView.delegate = self).
Implement - (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollViewin view controller and return the "viewZoom" you added to the scroll view from this method.

How can I find the x coordinate of the contentView that is equal to the center x of a UIScrollView's frame

I have a UIScrollView that scrolls horizontally. I have about 10 views lined up horizontally in that scrollview. I want to find the view that contains the center point of the scrollview's frame (not contentView.frame) as it scrolls. I am thinking to use the - (void)scrollViewDidScroll:(UIScrollView *)scrollView UIScrollView delegate method, but I am not sure how to find this.
Thanks!
You can get the start-point of a frame of a view (myChildView) in the reference of another view (scrollView) using the following code:
CGPoint origin = [myChildView convertPoint:CGPointMake(myChildView.bounds.origin.x, myChildView.bounds.origin.y) toView:[self scrollView]];
Use the scrollViewDidScroll: delegate method to pick your views and perform the calculations there.

Check if a UIScrollVIew's contentOffset is equal to a certain x value

I have a UIScrollView inside a UICollectionViewCell an I'm trying to perform an action when a UIScrollView scrolls to a certain -x value.
I've tried
CGPoint lastOffset;
if (lastOffset.x < -50 && scrollView.contentOffset.x >= -50) {
// Animate the star
NSLog(#"Animate");
}
but the problem is that it only gets called when the scrollVIew is returning to its normal state.
for the heck of it, I've also tried
if (scrollView.contentOffset.x >= -50) {
// Animate the star
NSLog(#"Animate");
}
but this doesn't always get called.
Basically, what I am trying to create is something like the pull to refresh, but on the scrollViews's x access.
Another example if what I am trying to do is what Tweetbot 3 for iPhone does. If you swipe right on a cell you get the options to reply, star, etc etc.
Whats the best way to solve this?
Update: I'm using a UICollectionViewCell.
The way the scrollview is set up is something like this:
What I'm trying to do is to bring the gutter view in :
and animate a little star when the scrollView reaches -50 on the x axis.
The reason why I'm placing this view and the animating the star in the negative part of the scrollView's content bounds, is to allow the scrollView to snap back into place.
Update 2: I've figured it out. I'll accept my answer soon as I am allowed to. Thanks for everyone's input!
I've also have the same problem,this is my solution。
1:addsubview into scrollview,not full screen. because scrollview and tableview will call touch event(ps: U can get touch object in touch event).
just like this :## Heading ##
2:U can detect user touch time,such as >=3s call scrollview another call tableview. but that is less than method。
About Tweetbot3
U just add uiview and uipangesturerecognizer into coustom tableview cell. and try this SWTableViewCell
You can get the value during scroll using the UIScrollViewDelegate method scrollViewDidScroll:
self.scrollView.delegate = self;
-(void)scrollViewDidScroll:(UIScrollView*)scrollView {
if (scrollView.contentOffset.x >= -50) {
// Animate the star
NSLog(#"Animate");
}
}
Just be careful with your animation because the user could scroll back and forth between a contentOffset of 50 which may mess up your animation depending on how you've set it up.
if (lastOffset.x > -50 && scrollView.contentOffset.x <= -50) {
// Animate the star
NSLog(#"Animate");
}
I wasn't checking to see if the lastOffest.x was greater than -50, I was checking if it was less.

Mirror scrolling of UICollection

I have created a UICollection with a custom layout to allow for scrolling both vertical and horizontal. It is a grid of equal sections and items in each section (ie 10 x 10, 20 x 20, etc). I would like to be able to put two headers that remain in view, one along the top and one along the left side. I have not found a way to do this within the UICollection itself. So, I set up UICollection along the left and another along the top. However, as the user scrolls the grid left and right and/or up and down, I want these two collections to mirror those movements.
So, my question is: Is there a way to mirror the horizontal movement of the main UICollection to the top UICollection and then mirror the vertical movement of the main UICollection to the side UICollection?
Thanks!
UICollectionView is a subclass of UIScrollView. It sends its delegate all of the messages defined in the UIScrollViewDelegate protocol.
The message you want to respond to is scrollViewDidScroll:. When your main collection view sends this message, you want to respond to it by getting its contentOffset and applying the offset to your margin collection views as appropriate.
// Implement this in your main collection view's delegate.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self synchronizeCollectionViewContentOffsets];
}
- (void)synchronizeCollectionViewContentOffsets {
CGPoint offset = self.mainCollectionView.contentOffset;
self.leftMarginView.contentOffset = CGPointMake(0, offset.y);
self.topMarginView.contentOffset = CGPointMake(offset.x, 0);
}
So, I figured it out. Using self.mainCollectionView.contentOffset always returned (0,0), so tried to use the object name I actually assigned to it through the Storyboard and the view controller. This worked.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self synchronizeCollectionViewContentOffsets];
}
-(void)synchronizeCollectionViewContentOffsets {
CGPoint offset = myCollectionView.contentOffset;
myLeftMargin.contentOffset = CGPointMake(0, offset.y);
myTopMargin.contentOffset = CGPointMake(offset.x, 0);
}
Where myCollectionView, myLeftMargin and myTopMargin are linked to the UICollectionViews through the Storyboard.

UIScrollView with fixed contents inside

my question is:
In my app I want realize somethings like this using UIScrollView
A UIScrollView whit all his contents inside. But when I reached the top of the screen (or maybe the bottom of the screen) I want to anchor some contents like in the AppStore (iOS 6).
In this case the "Detail", "Review" and "Related" buttons stop scrolling and remains fixed at the top.
Anyone have any idea how to do?
Give your scroll view a delegate if it doesn't already have one. This would probably be your view controller.
Also give the delegate a reference to the floating view. (In the example, the floating view contains the “Dettagli”, “Recensioni”, and “Correlati” buttons, and the floating view is transparent where the triangular notch is, and the shadow is also part of the floating view.) The floating view must be a subview of the scroll view.
Save the “normal” Y coordinate of the floating view's frame in an instance variable. For example, if the delegate is a view controller, you should probably do it in viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
originalFloatingViewY = floatingView.frame.origin.y;
}
In the delegate's scrollViewDidScroll: method, check whether the scroll view has been scrolled below the top of the “normal” position of the floating view. If so, move the floating view to the top edge of the visible area:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self updateFloatingViewFrame];
}
- (void)updateFloatingViewFrame {
CGPoint contentOffset = scrollView.contentOffset;
// The floating view should be at its original position or at top of
// the visible area, whichever is lower.
CGFloat y = MAX(contentOffset.y, originalFloatingViewY);
CGRect frame = floatingView.frame;
if (y != frame.origin.y) {
frame.origin.y = y;
floatingView.frame = frame;
}
}
You could also do it by subclassing UIScrollView and overriding layoutSubviews. Watch the “Advanced ScrollView Techniques” video from WWDC 2011 for more information on this technique.
You need to handle this in the UIScrollView's delegate method( scrollViewDidScroll:) for scrolling. When the y of scrollview reaches that particular value you need to disable scrolling in this direction alone. You just need to add an if condition there to check and reset the y point while scrolling. For this you might have to keep this particular portion as a separate scrollview outside the below content and move it along with the below scroll view's upward movement.

Resources