How to do smooth scrolling in UIScrollView? - objective-c

I am using Apple's page control sample and showing three different types of views.
The scrolling is very slow on the device because I am using a UITableView and 5-7 labels on my view. Everything is updating from a database. How do I increase the performance of my scrolling behavior?

Fast Scrolling in Tweetie with UITableView

Or you could make sure all components on your UITableViewCells are opaque. UITableView doesn't handle well transparency when scrolling.

As Nick noted, the link back to the original Tweetie article, but I found it in the Wayback Machine - here
In researching this issue for myself, I found two other articles that were useful:
Glassy Scrolling with UITableView
Fun Shadow Effects Using Custom CALayer Shadowpaths (this is actually what solved my problem - I was using drop shadows in my views)

Related

UICollectionView: How to define a UICollectionViewLayout that supports horizontally and vertically scrolling?

At the moment I'm trying to create an UICollectionView, that should display a simple excel-like-spreadsheet, with rows and columns. This should be an easy task with UICollectionViews, I believed. And I really would like to do the implementation in UICollectionView, not in any grid framework.
But at the moment I'm hanging a little bit. What I've figured out is, that I unfortunately can't use a UICollectionViewDelegateFlowLayout, because this only supports scrolling in either horizontally or vertically direction. But I need scrolling in both directions.
Therefore I have to use a UICollectionViewLayout, but for this I didn't find good examples, how to use it. Has anyone of you an example, how to subclass an UICollectionViewLayout to support rows and columns?
Thanks in advance.
UICollectionViewFlowLayout definitely can't - "The grid layout scrolls along one axis only, either horizontally or vertically."
It is a subclass of UICollectionViewLayout. Seems like you could create your own subclass of UICollectionViewLayout and scroll in both directions.
What do you mean by page, you want to do paging like a scrollview? I'm wondering about using UICollectionViewFlowLayout in a UICollectionView for vertical scrolling, inside a UIScrollView for horizontal scrolling.
I've added an example of using a custom layout to implement a simple horizontal & vertical scrolling grid here https://github.com/neildavis/MyCollectionView
My example uses PSTCollectionView since I needed iOS 5 support, but it's API compatible with built in UICollectionView. (Actually it uses the compatibility classes (PSUICollectionView etc) provided to ensure it uses a UICollectionView on iOS 6 and falls back to using PSTCollectionView etc on iOS 5.) Just remove the 'PS' prefix on these to revert to iOS 6 only UIKit implementation.
I needed something similar. I created a Custom CollectionViewLayout.
https://github.com/akashraje/BidirectionalCollectionViewLayout
Answer that doesn't require dissecting a 3 sample projects
In your UICollectionViewLayout subclass:
Implement -(CGSize)[collectionViewContentSize] and return a size larger in height and width than the UICollectionView's size. (Accessible via: self.collectionView.frame.size)
Calculate layout for your UICollectionViewCells within the content size rather than the frame size.
Note: Make sure scrolling is enabled in the UICollectionView. (It's on by default.)

How to draw in code an imageview

I have a problem. I want for each record in my core data database to draw an UIImage view on screen. But the problem is that I want to make a sort of grid. On the link below you see what I want to achieve.
picture
So my question is, how do I draw an image on screen in code. And place those images in a sort of a grid. using a collection view is no option, because the app should be running on all IOS devices.
While you could implement a custom UIView and implement the drawRect: method and draw UIImages there, I suggest just using multiple UIImageViews as subviews on your "main" view. Your view might be embedded in a UIScrollView, or you could use a UITableView with custom UITableViewCells. Whichever is easier is probably related to how you can interact with the view.
Building that one huge image view is something that I'd definitely try to avoid - it costs many many (probably unnecessary) memory, and it might be slow as well. Definitely not very flexible to handle, and a pain to update dynamically.
A quick cheat for something like this is to use a Table View and then in each cell to place another TableView but rotated at 90 degrees.
You can then use this second TableView to display the pictures etc...
This will give you a table that scrolls up and down and then each cell can scroll left to right.
I'd suggest subclassing UITableViewCell and setting it up as a UITableViewDelegate and UITableViewDatasource.
You will also have to remember to rotate the content of these "sub"tables by 90 degrees also so that they are the right way up.
This sounds like a lot of work but if you push the management of the sub Tables into the cells then it actually becomes quite easy.

Nested scrollviews getting problematic

My problem is that I am using nested scrollviews. One for the horizontal paging and second to show the content with vertical scrolling (cuz content, which is text, is more than the available space). Actually there are multiple copies of this vertical scrollview like:
MainScrollView (Horizontal)
VerticalScrollView1
VerticalScrollView2
VerticalScrollView3
Besides these the vertical scrollviews contains label that are draggable, I implemented dragging using touchesBegan: and moved: events. I developed the whole thing using only one vertical scrollview and it's working just fine and I thought, to my dismay, that it'll work exactly the same for the rest but when I added more vertical scrollviews, only the last one is allowing dragging of the labels. The first two ain't allowing dragging, besides, they are also not responding to the vertical scrolling event, which was perfect earlier. I tried it with two vertical scrollviews and even then only the last one was allowing dragging. Ain't sure about the vertical scrolling cuz right now only the first one has enough content to be scrolled rest need not to. I can try that out too but it's kinda late here, so, if someone can guide me with the provided info. would be much helpful. Else I can try that out tomorrow and post you with the result.
Thanks for your time.
I had similar issues with nesting UIScrollviews. I found this video from WWDC 2010 to be really helpful in showing how to work with scrollviews inside a paging scrollview, and I managed to fix the bugs I had by following the steps in this video and looking at the sample code.
Designing Apps with Scroll Views
Sample code

Lazy-loading Custom UIScrollView with dynamic grid size?

So I wrote a custom subclass of UIScrollView that basically displays rectangles in a 2-column grid, but while the width of each is fixed to half the width of the iPhone/iPad screen, the height varies, depending on the dimensions of the picture within it. All's well and good now, but I can imagine that after adding lots of these subviews to my UIScrollView subclass, things are going to lag. So I'm trying to implement lazy loading analogous to UITableView's dequeueing reusable cell method.
I've looked at a handful of other questions on SO, but they all involve paging based on full-screen photos, including Apple's WWDDC PhotoScroller example.
Anyone have any insight? Thanks.
You basically want to keep track of the views that are scrolled off screen and reuse them.
You might want to check out ATArrayView. It implements a recycling mechanism like what the UITableView has except with a UIScrollView with an arbitrary number of rows and columns?
I've used it as the basis for my own image scrolling code and is pretty good. It's delegate methods follow the spirit of UITableView data source and delegate protocols.
Good luck
Tim

Best approach for drawing a graph of almost infinite size in a UIScrollView on iPad

I'm currently working on an app which needs to draw s.th. like a network graph. Unfortunately this graph can become very big with thousands of movable objects.
I tried to put a giant UIView inside a UIScrollView but soon noticed this won't work because of memory limitations.
So I tried another approach: currently I have a UIView which has exactly the size of the visible part of the UIScrollView. The scrollview is set to not handle the scrolling (only the pinching). Instead I handle the scrolling in the UIView. Everytime a user scrolls, all graphic objects (those graphic objects are currently just subclasses of NSObject, which contain custom drawing code) are moved, so it seems like the view is scrolling. In the drawRect I only draw the graphics that are currently visible.
Also I constantly add and remove sublayers if they are moved out/in the visible frame
This works very smooth even with thousands of objects.
Unfortunately this approach has some drawbacks:
I can't zoom out to see all the objects in the graph, instead the user can only see a part of it
I don't get the inertial scrolling the UIScrollView offers
Other approaches I tried, like the CATiledLayer, don't work either because all the objects in the graph are draggable by the user and it looks really ugly if I use a CATiledLayer...
Swapping out the UIView with other UIViews while the user scrolls may help with the inertial scrolling, but it makes everything more complicated and zooming out completely still won't work :-(
Do you know of any best practices to draw graphs that can be very big?
//edit: I ended up with a uiscrollview which has a subview which has a cascrolllayer which has many sublayers. While zooming in and out the frame of the uiscrollviews subview is constantly changed to the uiscrollviews bounds by view.frame = scrollview.bounds. While dragging the scrollview the cascrolllayer is always forced to scroll to the current offset of the scrollview.
I needed to subclass the uiscrollview and hack around in order to make the zooming work nicely, but it's working well now. This approach works very well and allows very big graphs with lots of draggable elements.
//edit: see my other answer below, the approach above didn't work out as well as I initially thought, especially the zooming part
CATiledLayer is definitely what you should use here—there’s not really another solution that’ll let you use Quartz/UIKit drawing on a huge zoomable canvas. For anything that needs to be interactive (dragged or animated or whatever), you can disable its display in the main tiled layer and overlay another view or layer on top of it that just contains the object being interacted with.