How do I change CCScrollLayer content size? (cocos2d extension class) - iphone

I am currently using the CCScrollLayer (in the cocos2d extension classes) class to implement a menu system. It's working great but I would like to have other buttons on the screen and the scrollable area is the entire screen by default.
I tried messing with content size but no dice. After doing some reading, I found that the content size is set to the screen size per CCLayers behavior. A user suggested wrapping it in a CCNode and scaling, but this did not help.
Any suggestions or sample code? I'd have to think this should be possible.

CAScrollLayer is surprisingly simple, which may be confusing.
Just add the content layer to it:
[_scrollLayer addSublayer:_contentLayer];
To set the rect you want to be visible on the screen set bounds or frame of the scroll layer:
[_scrollLayer setBounds:visibleBounds];
Set the content's size respectively. The content's size can be bigger or smaller, it does not matter.
[_contentLayer setBounds:currentContextBounds];
If the content is bigger and you want to scroll to a certain point use scrollToPoint: or scrollToRect: methods of the scroll layer.
You need to implement your own scrolling indicators, bars, etc. if desired.

Although I am using table view and not the scroll view, both share the same parent [scroll view doh].
Have you turned on clipToBounds after setting content size?
I would recommend using this constructor:
/**
* Init this object with a given size to clip its content.
*
* #param size view size
* #return initialized scroll view object
*/
- (id)initWithViewSize:(CGSize)size;

Thanks everyone for the help, unfortunately it seems you cannot change the size of a CCLayer (or the contentSize has no effect on touch events) without basically rewriting a lot of code.
However, I found a workaround that seems to be working. In the ccTouch events began and moved, I check my desired bounds after converting my UITouch to cocos2D space. If they are not in the my bounds I return, and in the case of move I manually call TouchEnded. TouchEnded also checks the initial touched point, and if it is was out of bounds it ignores it.
Things seems to be working as desired. I will post more information if I find it. Thanks again everyone.

Related

How to resize an NSImageView in an NSStackView?

I'm working on a project where I want the following in an NSTableViewCell:
Image
Text
Subtitle text
The NSTableView is in a window which the user can expand or contract. When the window expands and contracts, the text wraps as needed.
That much is working.
When it comes to the image view, I can't get the thing to resize at all. I don't understand how the text automatically wraps, but images don't automatically scale. I've been working on iOS so long that I might have missed something in how stack views differ between iOS and macOS, but I never had this problem in iOS.
I don't have much code because the text wraps properly without any code at all, so instead I posted a minimal project showing the problem on Github:
NSImageTableViewTest
Some things I tried:
I have to set the width/height of the image view, or the text won't wrap. It seems to me that the reason why is that if I keep the image view unbound, the table view starts at the width of the image.
I tried setting the leading and bottom constraints of the image view to no avail.
I tried setting the constraints of the NSStackView, but that doesn't help constrain the frame of the image view.
Question: do I have to change the frame of the image view in code? I did try that, to no avail.
At this point, I'm stumped and I'm sure the fix is something easy that I overlooked.
Thanks.
The image view doesn't shrink because the default Content Compression Resistance Priority is too high. Set the Content Compression Resistance Priority to (a bit lower than) "Low (250)".

Combine text and buttons in scroll rect

I'm attempting to create a scrollable UI object that has 2 sections with one on top of the other: a text section and a button list section. My main problem is that the text and list of buttons change in size depending on what content the player is viewing.
It seems that just throwing the text and buttons into an empty UI object doesn't work, because the empty game object does not take on the size of its children, and since the empty object does not have its own size, scrolling through its contents is not possible.
Is there maybe an element that I am not aware of that could help me out?
Here's the setup I use for Scroll. It seems you are missing the third object, the content object. It is what decides the physical size of your content size using a Content Size Fitter and a Layout Group. I decided to include the entire setup just in case you are missing something else.
Parent Object (Mask OR Rect Mask 2D) - Object that is the visual bounds of your UI
-> Scroll Object (ScrollRect) - Actual scroll component that drives the UI scroll
-> Content Object (Horizontal OR Vertical Layout Group AND Content Size Fitter) - Is the parent of your actual data in your scroll
To explain this a bit better, the Mask is used when you have a nonrectangular asset that you still want to be your max viewing bounds. Anything outside of this Mask will not be rendered. A Mask is more expensive than a Rect Mask 2D, so if your viewport is a square or rectangle, then use the 2D component.
The Scroll Rect is the driver of the scrolling of UI elements in Unity. Make sure to check the box if it is horizontal or vertical. I assume in your use case you are using vertical. Make sure to set the Content field to be the child of this object and the Viewport to be the parent (the mask).
The Content Object has two components on it. The first being the Content Size Fitter which will force this object to be the size of its content. If your scroll is a vertical scroll, set the Vertical Fit to Preferred Size and leave the Horizontal Fit to be Unconstrained size. If it is the opposite, then set the opposite of what I just said. The other component on this object is a Horizontal Layout Group OR a Vertical Layout Group. The difference being which direction your scroll is. The checkboxes in the settings of this object matter quite a bit. Check out the docs on what each one does.
If you attach the components as I specified and set the proper settings on the layout group, you should be able to have as many dynamic objects with variable size swapping between text and buttons.
If you have any other questions let me know. UI can be a bit daunting at first but once you figure it out, it gets much easier.
Edit:
To achieve an object that can change size with a text object and a button, you will need to use a combination of content size fitters and layout groups.
Here is an example hierarchy
Here is the result
Using a combination of the layout groups and content fitters forces the container the text is in to be the size it needs to be. If you are making these assets static meaning none of it is data-driven at runtime, then this should work right away. If you are changing this data at runtime, you will need to use LayoutRebuilder on the parent objects to assure that the layouts rebuild properly. Let me know if you have questions.

Expanding content within UIScrollView

I'm building a cell-based game that essentially works like dominoes: you start with one tile in the center, then connect additional tiles to it that can branch out in all directions. I have my game table all set up and working great... now I just need to make it scroll to accommodate the expanding content.
So, this doesn't seem to fit easily into a UIScrollView's built-in behavior. For one thing, cells expand in all directions – potentially going into the negative coordinate space of the UIScrollView. As far as I can tell, UIScrollView does not allow an actual CGRect with size AND origin to be defined for the scrolling content area. It appears you can only define a width and height for the content area that extends from point (0,0). Is this true, or am I missing something?
Assuming my understanding of the content area limitations are correct, how would one ideally handle this problem? My go-to idea would be to shift all subviews into positive coordinate space as the game board expands, then update the ScrollView's contentOffset property to counter the shift and make the transition invisible. I just want to make sure I'm not reinventing an inferior wheel before I start developing this.
Thanks in advance for any and all ideas!
I believe your idea is the good one, every time a tile is added, you may need to adjust your content view in order to be able to center on the tile that just was added.
Hence if this is "backward" (-x or -y) and your on top of your view (or nearly), you'll have to extend your contentView (surely the same way you do for +x, +y) and thus, adjust every of your tiles with the translation you did to your contentView's down-right corner.
Following up... yep, that did it. I set up the display so that it redraws the grid of cells from the upper-left corner. Whenever a new row or column of cells is added to the top or the left, the UIScrollView's contentOffset shifts by the newly added pixels to hide the change in content position.

UIScrollView carousel menu

I'm trying to figure out if I can get what I want out of UIScrollView through some trickery or whether I need to roll my own scroll view
I have a series of items in row that I want to scroll through. One item should always be centered in the view, but other items should be visible to either side. In other words, I want normal scrolling and edge bouncing, but I want the deceleration when the user ends a touch to naturally settle at some specified stop point. (Actually now that I think of it, this behavior is similar to coverflow in this respect.)
Take a look at this project: SwipeView
Good luck
I'd check out https://github.com/nicklockwood/iCarousel, it's awesome.
You should take a look at the "pageingEnabled" property of a UIScrollView. Basically you can define a size of a segment and the number of segments. Then it will automatically stop to adjust to that specific segment like you want. If you set the segments to be smaller than the actual width of the screen I think you should get the behaviour you are looking for.

Really, really big UIScrollViews

I'm trying to make a level-of-detail line chart, where the user can zoom in/out horizontally by using two fingers, and grow the contentSize attribute of the the UIScrollView field. They can also scroll horizontally to shift left or right and see more of the chart (check any stock on Google Finance charts to get an idea of what I'm talking about). Potentially, the scroll view could grow to up to 100x its original size, as the user is zooming in.
My questions are:
- Has anyone had any experience with UIScrollViews that have such large contentSize restrictions? Will it work?
- The view for the scroll view could potentially be really huge, since the user is zooming in. How is this handled in memory?
- Just a thought, but would it be possible to use UITableViewCells, oriented to scroll horizontally, to page in/out the data?
This is kind of an open ended question right now - I'm still brainstorming myself. If anyone has any ideas or has implemented such a thing before, please respond with your experience. Thanks!
This is quite an old topic, but still I want to share some my experiences.
Using such a large UIView (100x than its origin size) in UIScrollView could cause Memory Warning. You should avoid render the entire UIView at once.
A better way to implement this is to render the only area which you can see and the area just around it. So, UIViewScroll can scroll within this area smoothly. But what if user scrolled out of the area that has been rendered? Use delegate to get notified when user scroll out of the pre-rendered area and try to render the new area which is going to be showed.
The basic idea under this implementation is to use 9 UIViews (or more) to tile a bigger area, when user scrolled (or moved) from old position to new position. Just move some UIViews to new place to make sure that one of UIView is the main view which you can see mostly, and other 8 UIViews are just around it.
Hope it is useful.
I have something similar, although probably not to the size your talking about. The UIScrollView isn't a problem. The problem is that if you're drawing UIViews on it (rather than drawing lines yourself) UIViews that are well, well off the screen continue to exist in memory. If you're actually drawing the lines by creating your own UIView and responding to drawRect, it's fine.
Assuming that you're a reasonably experienced programmer, getting a big scroll view working that draws pars of the chart is only a days work, so my recommendation would be to create a prototype for it, and run the prototype under the object allocations tool and see if that indicates any problems.
Sorry for the vagueness of my answer; it's a brainstorming question
But still, this approach (in the example above) is not good enough in some cases. Cause we only rendered a limited area in the UIScrollView.
User can use different gestures in UIScrollView: drag or fling. With drag, the pre-rendered 8 small UIViews is enough for covering the scrolling area in most of the case. But with flinging, UIScrollView could scroll over a very large area when user made a quick movement, and this area is totally blank (cause we didn't render it) while scrolling. Even we can display the right content after the UIScrollView stops scrolling, the blank during scrolling isn't very UI friendly to user.
For some apps, this is Ok, for example Google map. Since the data couldn't be downloaded immediately. Waiting before downloading is reasonable.
But if the data is local, we should eliminate this blank area as possible as we can. So, pre-render the area that is going to be scrolled is crucial. Unlike UITableView, UIScrollView doesn't have the ability to tell us which cell is going to be displayed and which cell is going to be recycled. So, we have to do it ourselves. Method [UIScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:] will be called when UIScrollView starts to decelerating (actually, scrollViewWillBeginDecelerating is the method been called before decelerating, but in this method we don't know the information about what content will be displayed or scrolled). So based on the UIScrollView.contentOffset.x and parameter targetContentOffset, we can know exactly where the UIScrollView starts and where the UIScrollView will stop, then pre-render this area to makes the scrolling more smoothly.