i did a text rendering program using UIView and UITableViewController. What i did is before going drawRect method, i just calculate all of the cells height as well as each text start & height,width. So that, i can estimate the cell height approximately and then i draw the text.
I did this for both portrait & landscape mode. My program looks like twitter updates. When the user changed to landscape mode i calculated the same things for landscape mode. Next time, i simply retrieve the stored data for drawing text(Valid before application quits).
Now my problem is, when my inputs are less, it works good. But for the huge input say 100 inputs, it takes some time to show the text. Also, my program's scrolling is somewhat not smooth. Also there is no leak in my application.
Please anyone suggest me the good way to do this application and make it so smooth and faster...
Thanks in Advance,
Rajkanth
The short answer to this is to minimize any computation you do in rendering of the cells. This includes any transparent backgrounds. To achieve the fastest scrolling, ideally you would have very few amounts of non-opaque elements.
The trick is to only have one big opaque element by coalescing all your individual elements into a single view.
http://blog.atebits.com/2008/12/fast-scrolling-in-tweetie-with-uitableview/
Related
I have an infinite scrollview in which I add images as the user scrolls. Those images have varying heights and I've been trying to come up with the best way of finding a clear space inside the current bounds of the view that would allow me to add the image view.
Is there anything built-in that would make my search more efficient?
The problem is I want the images to be sort of glued to one another with no blank space between them. Making the search through 320x480 pixels tends to be quite a CPU hog. Does anyone know an efficient method to do it?
Thanks!
It seems that you're scrolling this thing vertically (you mentioned varying image heights).
There's nothing built in to UIScrollView that will do this for you. You'll have to track your UIImageView subviews manually. You could simply maintain the max y coordinate occupied by you images as you add them.
You might consider using UITableView instead, and implementing a very customized tableView:heightForRowAtIndexPath: in your delegate. You would probably need to do something special with the actual cells as well, but it would seem to make your job a little easier.
Also, for what it's worth, you might find a way to avoid making your solution infinite. Be careful about your memory footprint! iOS will shut your app off if things get out of hand.
UPDATE
Ok, now I understand what you're going for. I had imagined that you were presenting photographs or something rectangular like that. If I were trying to cover a scroll view with UILeafs (wah wah) I would take a statistical approach. I would 'paint' leaves randomly along horizontal/vertical strips as the user scrolls. Perhaps that's what you're doing already? Whatever you're doing I think it looks good.
Now I guess that the reason you're asking is to prevent the little random white spots that show through - is that right? If I may suggest a different solution: try to color the background of your scroll view to something earthy that looks good if it shows through here and there.
Also, it occurred to me that you could use a larger template image -- something that already has a nice distribution of leaves -- with transparency all along the outside outline of the leaves but nowhere else. Then you could tile these, but with overlap, so that the alpha just shows through to the leaves below. You could have a number of these images so that it doesn't look obvious. This would take away all of the uncertainty and make your retiling very efficient.
Also, consider learning about CoreAnimation (CALayer in particular) and CoreGraphics/Quartz 2D ). Proper use of these libraries will probably yield great improvements in rendering speed.
UPDATE 2:
If your images are all 150px wide, then split your scrollview into columns and add/remove based on those (as discussed in chat).
Good luck!
I have a uiscrollview that has a custom child view that contains text and images.
The text items are UILabels. I have attached an image representing the quality issue:
Do you guys think it might be worth a shot to draw the text, then convert to a uiimage and display that instead? Maybe it would scale better? Or perhaps there is a way to smooth the text?
There's no reason to expect that you're going to draw the text better than UILabel does. Your picture is very hard to make out, but here's what you want to look at:
Are you just adding a UILabel to the UIScrollView's contentView, or are you doing something else fancier. That "something else fancier" could easily be the problem.
Make sure you're drawing on pixel-aligned boundaries. The easiest way is to make sure the origin of your UILabel is integral (not a fraction). On a retina display, you can get away with half-points, but it's usually easier just to make everything integers.
I thinks it is the position issue. I bet you set the x or y value to float value like 12.3 or 12.5 .
What I have done now is I have created a uiimage version of my text and am showing that now instead of the uilabels, the quality is soo much better, you can really see the difference when you are looking at it scaled up on the ipad, it must just do a better job scaling images then text?
Before:
After:
The above images show how the text renders on the ipad with my app scaled up, before and after my change.
Hi all,
The images above are taken from the "Nike Boom" App. I am wondering how to do a magnified effect on the number list as shown in the images. I also want to point out that it is very very smooth animation, so screen capturing certain part of a screen and projected it back on UIView may not work (I tried that)
Thankz in advance,
Pondd
Update:
Hey,
Just so for anyone who might comes across this topic, I've made a simple sample based on Nielsbot's suggestion and posted up on github here
Please feel free to fork it, improve it and pass it on :)
Best,
Pondd
It's done with 2 scroll views, one in front of the other. One scroll view (A) contains the small numbers. The second scroll view (B) contains the zoomed numbers. The frame of (B) is the transparent window. When you scroll (A), you scroll (B) programmatically, but you move it farther than (A). (I.e. if (A) scrolls 10 pixels, you might scroll (B) 20 pixels.)
Make sense?
If you've ever used Convert.app from TapTapTap they use a similar effect.
I'm making an iPhone game and using UIView objects to draw sprites. Most of the time, I have no performance problems. However, once I have around 15 to 20 objects on the screen (and maybe 5 of them moving around), the game becomes considerably slower, especially on the iPhone 3G. The frame rate can drop to as low as a single frame per second.
Is this simply a limitation of using UIView objects, or should iOS be able to handle this many UIView objects on screen at the same time?
In order to isolate the problem, I've made drawing my views very simple — drawing a red rectangle. drawRect is only getting called once per view. The view hierarchy is very simple and shallow. I'm using CADisplayLink to update the UIView locations every frame.
There's very little else going on, so I'd like to hear if anyone else has had success using this number of UIView objects.
The key to my problems ended up being that I had labels on top of my game content. The labels are not opaque, which likely was a large part of the problem, as phix23 suggested.
The first thing that made a big difference was removing a frames per second label that was on top of the content. Having a label that changed content on every frame caused a lot of slowdown.
I also had a large label that displayed on top of much of the game and changed shape when you level up. It turned out that drawing this label on top of everything caused a lot of slowdown as well.
In answer to my original question, I've found that on an iPhone 3G I can support about 30-40 opaque UIViews onscreen at the same time, with 2 or 3 non-opaque views as well. Non-opaque UIViews that change size, shape, or location are by far the worst, and even one of these that covers a significant amount of the screen can quickly cause problems.
If you're setting the opaque property of each view to NO, keep in mind that this seriously affects the speed of drawing the views. If your views aren't transparent, you should leave this set to YES, which is default.
for such type of application you should use CoreGraphics / Quartz / OpenGL but anyway I don't think there is a limitation on such low count. For example if I have a table view with 9 rows and each row has 5 subviews its still displayed acceptable fast. Have you tried using UIView animation to change the position in view?
good luck in learning OpenGL ;)
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.