Wanted to add a "Pull To Refresh" feature similar to Tweetie2, so i looked around to see if there was any reusable code (screenshot from Zattr).
Cocoanetics (ex-Dr. Touch) has a good article explaining"pull to refresh" internal workings, well worth investing the time and effort to read. Recommended! However he's solution was not reusable for me, since I don't have UITableViewController. Fortunately he referenced Enormego's solution using UITableViews, including a walk-through with changes.
Thursday, October 28, 2010
Wednesday, October 20, 2010
How to Make Round Corners for UITableViewCell
Sometimes you need round border around one or more UITableViewCell. Or maybe a button look-a-like without going through the trouble of actually making one. Here's a quick way:
First of all, you MUST include QuartzCore header, else meet some interesting error notes:
For example I replaced this (got a bit further with carefully positioned UIViews inside UITableViewCell) with hardcoded bitmaps and scaling them nicely.
First of all, you MUST include QuartzCore header, else meet some interesting error notes:
#import <QuartzCore/QuartzCore.h>Then add this code after your cell initialization routine, usually at cellForRowAtIndexPath:
CALayer *layer = cell.layer;Like many things in iOS SDK, you get to a certain point with relative ease - and this is about it. If you want to have more control over your "bubble button" you either dig deep into Quartz sample code or implement something which looks same in a completely different way.
layer.borderColor = [[UIColor blueColor] CGColor];
layer.borderWidth = 3.0f;
layer.cornerRadius = 20.0f;
For example I replaced this (got a bit further with carefully positioned UIViews inside UITableViewCell) with hardcoded bitmaps and scaling them nicely.
Thursday, October 14, 2010
How to Control UISearchBar Background Color
When you have a list, you want to search it. How would you do that? No, don't code it by yourself. Done it, removed it.
By default each UITableView comes with search support via a built-in UISearchDisplayController. You just add and connect UISearchBar to your table in Interface Builder and provide some delegate methods to make it work. Pretty easy:
You can fix that by doing two things. First get rid of default background:
Sad to think how many hours I wasted experimenting Things That Will Not Work, just to find out that kind of miniscule solution. Also bet that this will not work one year from now...
By default each UITableView comes with search support via a built-in UISearchDisplayController. You just add and connect UISearchBar to your table in Interface Builder and provide some delegate methods to make it work. Pretty easy:
self.searchDisplayController.delegate =Controlling how your UISearchBar looks like is a bit more difficult. If you want to show search box and some other component(s) side by side, you can do it by putting UIToolbar at back and a short UISearchBar on top of it. By default their backgrounds are different, looking pretty ugly together. Like a hack, what it really is.
self.searchDisplayController.searchBar.delegate =
self.searchDisplayController.searchResultsDataSource =
self.searchDisplayController.searchResultsDelegate = self.mySearchObject;
You can fix that by doing two things. First get rid of default background:
for (UIView *view in self.searchBar.subviews)...and the second thing? Something that will be extremely hard to find out, unless you get it right by accident? You have to set UISearchBar style Black Translucent!
{
if ([view isKindOfClass:NSClassFromString
(@"UISearchBarBackground")])
{
[view removeFromSuperview];
break;
}
}
Sad to think how many hours I wasted experimenting Things That Will Not Work, just to find out that kind of miniscule solution. Also bet that this will not work one year from now...
Wednesday, October 13, 2010
Custom Data Formatter for NSIndexPath
Have been using UITableViews for a long time, always complained to myself why cannot I see section and row right away in debugger or variable popup. Something like with CGRect or CGSize. Well, this morning I was doing something completely different. Suddenly solving NSIndexPath debug problem was the much easier task:
Now I can continue fixing The Real Problem.
section={(int)[$VAR section]}, row={(int)[$VAR row]}Start debugging anything with a local NSIndexPath variable, even a temporary dummy one. Put breakpoint right after it. When debugger stops, double click on debugger window summary row for NSIndexPath variable and paste the string above there. Seems to stick even after restarting Xcode.
Now I can continue fixing The Real Problem.
Monday, October 11, 2010
How to Find Out Width of Truncated UILabel Text
Found out my tip "How to Float an Icon after UILabel" worked only in positive scenarios. If your text string is longer than UILabel width, icon could have been pushed out of sight. In worst case nobody would ever have seen the icon!
// TitleSome measurements of different methods, just to check what is available:
label = (UILabel *)[cell viewWithTag:1];
label.text = @"This is a very long title which is too long";
// Icon
image = (UIImageView *)[cell viewWithTag:10];
image.image = [UIImage imageNamed:@"logo.png"];
CGSize frame1 = label.frame;Next icon positioning. Here you should have calculations to compensate for different icon sizes (in case all of your icons are not same size):
// 205x21
CGSize frame2 = [label sizeThatFits:label.frame.size];
// 291x19
CGSize frame3 = [label.text sizeWithFont:label.font constrainedToSize:label.frame.size];
// 163x19
CGSize frame4 = [label.text sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:label.lineBreakMode];
// 203x19
CGSize frame5 = [label.text sizeWithFont:label.font forWidth:label.frame.size.width lineBreakMode:label.lineBreakMode];
// 203x19
// Icon positioningOk, now that's perfect (until next defect report)!
CGSize frame = image.frame;
frame.origin.x = label.frame.origin.x + frame5.width + 4;
image.frame = frame;
Thursday, October 7, 2010
How to Get Rid of Keyboard with a Tap on Background part2
There was a nice way to remove keyboard by using UITextView, but that has stopped working with iOS4. At least I got such a defect report for beta application. This time I will remove keyboard using UIButton, let's see how long that will work:
Nice, easy, simple, fast - what more can you ask for!
- (IBAction)removeKeyboardOpen your view in Interface Builder, create new custom full screen UIButton to cover everything, select UITextFields and UIButtons (etc.) one by one and "Send to Front" via Layout menu. Connect UIButton "Touch Up Inside" to your callback and that's it.
{
[textField1 resignFirstResponder];
[textField2 resignFirstResponder];
}
Nice, easy, simple, fast - what more can you ask for!
Wednesday, October 6, 2010
How to Float an Icon after UILabel
Want to place a floating icon right after a variable lenght text string - using Interface Builder? Wonderful helper that IB tool or so I thought...
First create a UITableViewCell template with IB, put there a fixed lenght UILabel followed by a UIImageView. No problems, their values are easy to setup at cellForRowAtIndexPath with view tag id numbers:
I had a problem that Interface Builder wanted to set UITableViewCell tag same as my image tag. No errors, no warnings, no indications of problem - except that I couldn't get my image frame no matter how much I banged head into brickwall! Removing tag didn't help, it just automagically came back. Ouch!
First create a UITableViewCell template with IB, put there a fixed lenght UILabel followed by a UIImageView. No problems, their values are easy to setup at cellForRowAtIndexPath with view tag id numbers:
UILabel *label = nil;But how to "float" that image right after text string? UILabel is fixed sized, so that won't help. Have to check the size of label.text instead:
UIImageView *image = nil;
CGRect frame;
// Title
label = (UILabel *)[cell viewWithTag:1];
label.text = @"Title text";
// IconThat's it, very simple! Just beware that your tag numbers MUST be unique.
image = (UIImageView *)[cell viewWithTag:10];
image.image = [UIImage imageNamed:@"logo.png"];
// Icon positioning
frame = image.frame;
CGSize f = [label sizeThatFits:label.frame.size];
frame.origin.x = label.frame.origin.x + f.width + 4;
image.frame = frame;
I had a problem that Interface Builder wanted to set UITableViewCell tag same as my image tag. No errors, no warnings, no indications of problem - except that I couldn't get my image frame no matter how much I banged head into brickwall! Removing tag didn't help, it just automagically came back. Ouch!
Tuesday, October 5, 2010
How to Disable UITabBarItems but Only Temporarily
User is allowed to use only one UITabBar item, until he has done something e.g. made a selection on list. Other tabs are available after that. Access to tabs can be blocked again e.g. if user chooses to delete current "entry".
Tab access control is done in AppDelegate, since it owns UITabBarController and UITabBarItems. Just set up delegate handling - and that's the key: either there is a delegate to block tabs or there is none for free access:
Btw this works only as long as you don't need UITabBarControllerDelegate for any other purpose. You have been warned.
Tab access control is done in AppDelegate, since it owns UITabBarController and UITabBarItems. Just set up delegate handling - and that's the key: either there is a delegate to block tabs or there is none for free access:
@interface MyAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>Access control can be enabled in any other class/file:
{
UITabBarController *tabBarController;
}
...
- (BOOL)tabBarController:(UITabBarController *)aTabBarController
shouldSelectViewController:(UIViewController *)viewController
{
if (
([aTabBarController.viewControllers objectAtIndex:1] == viewController) ||
([aTabBarController.viewControllers objectAtIndex:2] == viewController)
)
{
// Disable switch to tab 1 and 2
// Check: otherViewController to enable
// Check: SomeViewObject to disable
return NO;
}
else
{
// Tab ok at index 0
return YES;
}
}
- (void)blockTabAccessAccess control can be disabled in any other class/file:
{
MyAppDelegate *app = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
app.tabBarController.delegate = app;
[app SwitchToTab:kTabFirst];
}
- (void)releaseTabAccessSome consider it poor design to access AppDelegate directly from "anywhere" and further more to use it to control application state. My defense are the classic a) it's easy b) it's fast c) it works and d) sometimes central control place is a good thing.
{
MyAppDelegate *app = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
app.tabBarController.delegate = nil;
[app SwitchToTab:kTabSecond];
}
Btw this works only as long as you don't need UITabBarControllerDelegate for any other purpose. You have been warned.