5 ms·
Designing for iOS: Taming UIButton
- millerm 14y agoNice article. I'm still excited about getting my first beta of Pixate (http://www.pixate.com/ http://www.pixate.com/). I saw that kickstarter project here and bought in, twice (they had lowered the goal). Then we'll have a new way of customizing iOS controls. I did get the shirt, but I'd really the the beta. It should be coming any day now.
- spobo 14y agoYou know about Nimbus CSS, right? http://docs.nimbuskit.info/group___nimbus_c_s_s.html http://docs.nimbuskit.info/group___nimbus_c_s_s.html
- millerm 14y agoThanks for the link. I will have to take a harder look at it as it wasn't quite obvious to me as to what it truly provides at the moment. Again, thanks and I will clone it when I get to my laptop.
- allr 14y agoAny similar tutorial/article for styling UITableView? Always struggled with custom cells (specially grouped cells)
- k-mcgrady 14y agoApple has good docs on it[1]. I find the easiest solution is to create a custom cell nib and style that. If I need multiple custom cells I tend to do it in code. This was something I always found difficult to do well but over the years it's improved a lot (especially with the appearance API in iOS 5). [1] http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7 http://developer.apple.com/library/ios/#documentation/UserEx...
- jarcoal 14y agoMaybe you've already seen this, but I found it helpful for customizing cells: https://github.com/vicpenap/PrettyKit https://github.com/vicpenap/PrettyKit
- coob 14y agoDrawing controls in code, unless you gain something other than the space saved for bitmaps, is a waste of time and energy. You gain nothing by drawing the gradients for buttons in code. If it all ends up in that format anyway, you might as well do what Apple does 95% of the time: just use bitmaps. In mobile, saving cycles is more important than saving storage.
- flyosity 14y agoAlso, calling -imageNamed to load your images will automatically cache the contents. Numerous Apple engineers have told me not to draw UIs in code and just to use images instead, so although it's a fun challenge, there really is no upside. Even animations in iOS like the jiggling/opening trash are just a series of PNGs using UIImageView animation.
- RandallBrown 14y agothere are plenty of upsides to drawing UIs in code. You get resizable controls, controls you can change the color on, controls that can be added easier programatically, and smaller app bundles.
- masklinn 14y ago> You get resizable controls You also have that with images, so that does not apply. You do get the rest, which has to be weighted against lower performances and higher maintainability costs.
- potatolicious 14y ago> "You also have that with images, so that does not apply." No, it very much still does. The only sort of resizing you get with images is whatever neatly fits within a 9-patch. Which is to say, if your center patch is non-uniform (gradient? textured surface?) you lose resizability. So yes, if you design a very standard UI that sails very close to the default iOS look and feel, you will be using stretchable images for almost everything. Which is to say, single-line elements that do not resize vertically at all, vertical linear gradients as an aesthetic theme instead of texturing (which is becoming a thing now), etc. The moment you depart those shores though, images start becoming a liability instead of an asset, and you'll need to do a lot more custom work to get your widgets to resize properly.
- andymatuschak 14y agoIt's really worth noting that there are substantial performance ramifications to your choice here, in terms of CPU time for generation, memory usage, I/O, and GPU time for rendering. The resizable image background technique will be the fastest option (provided you don't need to programmatically tweak the appearance). Next would be the full-sized background (which needlessly wastes memory). Then the CG-based approach, which could actually perform better than the full-sized background if you had generated a resizable image—the technique presented here needlessly wastes memory and CPU time by generating a full-width image. But it will still perform worse in basically all cases than the resizable-image-from-disk technique, so you would only want to do that if the parameters need to be tweaked at runtime. The CAGradientLayer-based approach (as written) is a very poor idea unless you need the animated transitions because it requires extremely expensive off-screen drawing passes due to the masking. If your situation permits you to use "overdrawn" masking (as I discussed in WWDC 2012's "Polishing Your Rotation Animations"), this would actually perform quite well—less memory consumption than all the other options; small rendering cost each frame. See also WWDC 2011's "Understanding UIKit Rendering" for more on graphics performance with UIKit. I guess it's also worth noting that the cost of masking CALayers with a borderRadius is much lower in iOS 6 than iOS 5, but don't go nuts: it's still way higher than all these other options.
- andrewljohnson 14y agoIt really just matters what you want to achieve, and if you are just rendering one button, all techniques perform fine. What if you want buttons that can be any color? Then using resizable images doesn't work very well. I use custom drawing code for one button in an app because I have a color wheel that let's you color all controls in the app to whatever theme you like. And for some other buttons, I use images to have more graphical control.
- andymatuschak 14y agoIt's not really true that all techniques perform fine if you're rendering just one button. If you're using a masked CALayer, and that layer's in a scroll view or is otherwise animating around the screen, there's a very real chance that you'll drop frames, just from that layer's off-screen rendering pass. Depends on how big the button is. Certainly, though, if you need parameterizable imagery, you need parameterizable imagery, and so you can't load them from disk. But you can still make your runtime-generated images resizable!
- drp4929 14y agoAny thoughts on performance impact, on the app responsiveness, of each approach ?
- objclxt 14y agoIt depends what you want to do - as has been alluded to here, the image based approach will be the best option in terms of responsiveness. If you draw your entire button with core graphics you can then rasterize it, but the drawing process is in itself computationally more expensive than rendering out the image.
- DHowett 14y agoI'd like to throw in the minor nitpick that stretchable/capped images are not iOS 5+, but in fact date back to iPhoneOS 2.0, with -[UIImage stretchableImageWithLeftCapWidth:topCapHeight:] All said and done, however, how is "here, use the APIs provided to you, or draw the graphics yourself" at all "taming" UIButton?
- aaronbrethorst 14y agoA recently introduced second option consists in using a resizable image as a button background after having set its resizable and non-resizable areas in code. Start by making a pill-shaped background image in your graphic editor. Not accurate. -[UIImage stretchableImageWithLeftCapWidth:topCapHeight] has been around since the first public SDK release. Although, I must say the -resizableImageWithCapInsets: methods added in iOS 5 and 6 are far more powerful. Also, here are a bunch of UIButton subclasses that I think are pretty neat that demonstrate some of the techniques described in the article, plus others: http://www.cocoacontrols.com/platforms/ios/controls/bbutton http://www.cocoacontrols.com/platforms/ios/controls/bbutton http://www.cocoacontrols.com/platforms/ios/controls/psstorebutton http://www.cocoacontrols.com/platforms/ios/controls/psstoreb... http://www.cocoacontrols.com/platforms/ios/controls/gloss-caustic-shader http://www.cocoacontrols.com/platforms/ios/controls/gloss-ca...
- Inebas 14y agoNot connected to the tutorial but I was trying to look at their other posts and I seem to get redirected to their learn.thoughtbot.com where they show their books, webcasts, and workshops which isn't bad but I just want to read their other posts. Does anyone know how?