At first I want to say that i am new in iPhone application development.I want to make a tabbaritem when i will select a item of the tabbar then it should be look like that
Many Thanks In Advance.
Know it's already been answered, but wanted to offer an alternative approach.
Subclassing UITabBarController is a bad idea, according to the docs. I also had no end of trouble when I actually tried to use a UIImagePickerController as one of the view controllers behind the subclassed tabbar.
I took a much simpler approach just overlaying a uibutton over the tabbar item. Example project can be found here:
https://github.com/group6/RaisedCenterButton
It's just an example though. You're still going to need to do the work to incorporate it into an app.
Use the info in this Article
This has been covered in quite a few tutorials. How most of these apps achieve the effect is they put a custom UIButton which follows similar styling to the Tab Bar on top of the tab bar in the center.
iDev Recipes has an excellent tutorial with the code example
For this you need to create custom tab bar by Sub classing UITabBarController.
TabBarController.h file :
#interface TabBarController : UITabBarController<UITabBarControllerDelegate>
{
UITabBarController *tabController;
UIImageView *img1;
UIImageView *img2;
UIImageView *img3;
UIImageView *img4;
}
.m file
- (void)viewDidLoad
{
[self loadTabView];
//[self viewWillAppear:YES];
[super viewDidLoad];
}
- (void) loadTabView
{
tabController = [[UITabBarController alloc] init];
tabController.delegate = self;
tabController.tabBar.backgroundColor = [UIColor clearColor];
//set offset for tabbar items images.
int topOffset = 6;
int bottomOffset = 6;
UIEdgeInsets imageInset = UIEdgeInsetsMake(topOffset, 0, -bottomOffset, 0);
[self.view addSubview:tabController.view];
}
// reset the background image in custom tabbar.
- (void) setTabBarBackground {
UIImageView *img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"btnbg.png"]];
img.frame = CGRectOffset(img.frame, 0, 1);
img.frame = CGRectMake(img.frame.origin.x, img.frame.origin.y-1, img.frame.size.width, img.frame.size.height);
[tabController.tabBar insertSubview:img atIndex:0];
[img release];
}
// reset the background image in custom tabbar.
- (void) resetTabBar : (NSString *) tabid
{
[img1 removeFromSuperview];
NSLog(#"tab id - %#",tabid);
switch ([tabid intValue]) {
case 0:
img1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab-1.jpg"]];
break;
case 1:
img1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab-2.jpg"]];
break;
case 2:
img1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab-3.jpg"]];
break;
case 3:
img1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab-4.jpg"]];
break;
case 4:
img1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab-5.jpg"]];
break;
default:
break;
}
img1.frame = CGRectOffset(img1.frame, 0, 1);
[tabController.tabBar insertSubview:img1 atIndex:0];
[tabController.tabBar bringSubviewToFront:img1];
[img1 release];
}
// here push View controllers
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
}
Hope it gives you idea..
I would advise not to do this. iOS users are used to the familiar tab bar functionality. The highlight is sufficient to let them know on which tab they are.
Your design idea is very attractive, but it comes at a cost. The area above the bar beside the rased bar item is wasted, or the size of other icons have to be reduced. This will make it more difficult to use, not easier.
Here is a good tip: take 2 hours out of your busy life and read the Apple Human Interface Guidelines for iOS from cover to cover. Its fascinating reading and will give you good guidance for design questions like this.
Related
I have implemented UISegmentedControl with Direction theme using BASequenceControl from cocoacontrols.com.
I have added BASequenceControl.h and BASequenceControl.m classes and required images from GitHub
Great. Its working fine for me..However I have a concern with the last segment section tip.
Its displaying the junk space of last segment section.
Original Screen Shot
I need like this
The code I have Implemented
#import "BASequenceControl.h"
BASequenceControl *bASequenceControl = [[BASequenceControl alloc] init];
bASequenceControl.frame = CGRectMake(10, 10, 200, 44);
[bASequenceControl addSegmentWithTitle:#"First" animated:NO];
[bASequenceControl addSegmentWithTitle:#"Second" animated:NO];
bASequenceControl.leftMargin = -22;
bASequenceControl.rightMargin = 0;
bASequenceControl.overlapWidth = 22;
[self.view addSubview:bASequenceControl];
Any help on this is appreciated.
Thanks.
This is a pretty simple fix. You will have to edit the BASequenceControl.m file or you can duplicate the class and rename it.
The line that is causing the problem is in drawRect: it basically draws the grey arrow across the entire background of the control. Creating that nice gradient in the empty space.
[passiveSegmentImage drawInRect:CGRectMake(-passiveSegmentImage.size.width, 0,
w + 2 * passiveSegmentImage.size.width, h)];
You can change it to:
[passiveSegmentImage drawInRect:CGRectMake(0, 0,
w, h)];
Now you have to tell the control that it should not be opaque. Update the initializers like this.
- (void)awakeFromNib {
_selectedSegmentIndex = -1;
[self setOpaque:NO];
[super awakeFromNib];
}
- (id)init {
if ((self = [super init])) {
[self setOpaque:NO];
_selectedSegmentIndex = -1;
}
return self;
}
This is pretty quick and dirty, you could potentially make this settable with a property. Then submit a pull request to BaseAppKit, but I'll leave that to you. Here is a gist that you can copy and paste directly in BASequenceControl.m to fix the overhang.
https://gist.github.com/4632686
Edit: Make sure that you are using init as the initializer and then setFrame: (I'm not really sure why initWithFrame: wasn't overridden in the class.)
BASequenceControl *control = [[BASequenceControl alloc] init];
[control setFrame:CGRectMake(0, 0, 300, 40)];
Green background for dramatic effect
How about to use a mask like this :
to mask your SegmentedControl
My client doesn't like the gloss on the iOS 5 UISwitch, and wants me to create a non glossy version using some images. However I don't know how I would go a bouts this.
I have created a UIView Subclass and I don't know what to do next.
Any suggestions as to what I need to do next?
You can recreate UISwitch using CoreGraphics (without using images).
Have a look at this: DCRoundSwitch
DCRoundSwitch is designed to be a drop in replacement for UISwitch.
In any case you should create a UIControl subclass!
There are a number of ways to do what you want. One way is to use a UIImageView and just switch the image when the user taps on the control.
Something like:
-(void) loadView
{
[super loadView];
UIImageView *image1 = [UIImage imageNamed:#"image1-from-client"];
UIImageView *imageView = [[[UIImageView alloc] initWithImage:image1] autorelease];
imageView.userInteractionEnabled = YES;
[self.view addSubview:imageView];
// detect the tap
UITapGestureRecognizer *tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)] autorelease];
[imageView addGestureRecognizer:tapRecognizer];
}
// this gets called when the user taps
-(void) tap:(UIGestureRecognizer*)gesture
{
UIImageView *viewTapped = (UIImageView*)gesture.view;
if ( viewTapped.tag == 0 )
{
viewTapped.tag = 1;
viewTapped.image = [UIImage imageNamed:#"image2-from-client"];
}
else
{
viewTapped.tag = 0;
viewTapped.image = [UIImage imageNamed:#"image1-from-client"];
}
}
You can recreate a custom UISwitch by subclassing UIControl. Then you can use regular UIViews to create almost any effect you want. You can look take a look at SevenSwitch. A custom UISwitch replacement I've created. It is non-glossy and the colors can be customized to you're liking.
https://github.com/bvogelzang/SevenSwitch
So,
I am subclassing my UITabBarController and I add the color Green to my UITabBar.
- (void)viewDidLoad {
CGRect frame = CGRectMake(0.0, 0.0, self.view.bounds.size.width, 48);
UIView *v = [[UIView alloc] initWithFrame:frame];
v.backgroundColor = [UIColor greenColor];
[v setAlpha:0.35];
[[self tabBar] insertSubview:v atIndex:0];
[v release];
[super viewDidLoad];
}
This does not work .
But if I try [[self tabBar] insertSubview:v atIndex:1]; it Works .. and a green color is added to the entire TabBar !!
I work on the iPhone Simulator using ios5 SDK and it works properly and I am able to select all tabs.
But when I try this code on the ios4.2 (real iPhone), the first tab is visible.. but DOES NOT RESPOND TO TOUCH
The reasons is clear, its because of adding a SubView of greenColor # index ==1;
But If I change to [[self tabBar] insertSubview:v atIndex:0]; my firstTab is selectable, but the tabBar just does not turn Green !!
Kindly Advise !!
Thanks.
Edit:
So the problem is associated with the iOS5 and the earlier versions. I will edit the answer and put back the original answer once iOS 5 is released.
Right now.... Off to the developer forums !!! :)
You might want to create a custom control for this that does not subclass UITabBarController. From the documentation, "You should never access the tab bar view of a tab bar controller directly."
The view layers and the hierarchy part of the non-public API and subject to change across different version of the iOS.
I'd like to make an app that uses a UITabBarController that is similar to the one in the Twitter app for iPhone and iPod touch. (Blue light for unread and sliding arrow for switching between content views).
Is there an easy way to do this? Any open source code?
Edit:
I've added a bounty. I'm looking for an answer that works across devices and on iOS 4 and iOS 5.
EDIT:
I've messed with my original code and I found a simple solution. I've added the following check, for iOS 5 in my animation code:
// iOS 5 changes the subview hierarchy
// so we need to check for it here
BOOL isUsingVersionFive = NO;
NSString *reqSysVer = #"5.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending){
//On iOS 5, otherwise use old index
isUsingVersionFive = YES;
}
Then, instead of this:
CGFloat tabMiddle = CGRectGetMidX([[[[self tabBar] subviews] objectAtIndex:index] frame]);
... I use this:
CGFloat tabMiddle = CGRectGetMidX([[[[self tabBar] subviews] objectAtIndex:index + (isUsingVersionFive ? 1 : 0)] frame]);
Still holding out on the bounty though, in case I get a chance to find something that works in the answers.
I would create a subclass of the standard UITabBarController and add a couple of subviews for the blue light and the sliding arrow. Shouldn't be too hard to accomplish.
Edit:
Here's an idea of some of the stuff that should go in your subclass. I don't even know if this code will compile.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
super.delegate = self;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
//Create blueLight
UIImage* img = [UIImage imageNamed:#"blue_light.png"]
self.blueLight = [[UIImageView alloc] initWithImage:img];
self.blueLight.center = CGPointMake(320, 460); //I'm using arbitrary numbers here, position it correctly
[self.view addSubview:self.blueLight];
[self.blueLight release];
//Create arrow, similar code.
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
//Put code here that moves (animates?) the blue light and the arrow
//Tell your delegate, what just happened.
if([myDelegate respondsToSelector:#selector(tabBarController:didSelectViewController:)]){
[myDelegate tabBarController:self didSelectViewController:viewController]
}
}
Here is how you create the arrow
http://isagoksu.com/2009/development/iphone/fancy-uitabbar-like-tweetie/
And follow Rafael's answer to get the blue light.
Although an ageing post, I though I would interject with a GitHub project that no one mentioned, they've recreated the Twitter styled tab bar quite well, here is the link:
https://github.com/boctor/idev-recipes/tree/master/CustomTabBar
The project is in the sub folder named "CustomTabBar", more information can be found here:
http://idevrecipes.com/2011/01/04/how-does-the-twitter-iphone-app-implement-a-custom-tab-bar/
BCTabBarController is what I based my custom twitter style tab-bar on and it works in iOS 4 and 5:
http://pastebin.me/f9a876a6ad785cb0b2b7ad98b1024847
Each tab view controller should implement the following method for the tabs image:
- (NSString *)iconImageName {
return #"homeTabIconImage.png";
}
(In the App delegate) you would initialize the tab bar controller like so:
self.tabBarController = [[[JHTabBarController alloc] init] autorelease];
self.tabBarController.delegate = self;
self.tabBarController.viewControllers = [NSArray arrayWithObjects:
[[[UINavigationController alloc] initWithRootViewController:[[[iPhoneHomeViewController alloc] init] autorelease]] autorelease],
[[[UINavigationController alloc] initWithRootViewController:[[[iPhoneAboutUsViewController alloc] init] autorelease]] autorelease],
[[[UINavigationController alloc] initWithRootViewController:[[[iPhoneContactInfoViewController alloc] init] autorelease]] autorelease],
[[[UINavigationController alloc] initWithRootViewController:[[[iPhoneMapUsViewController alloc] init] autorelease]] autorelease],
[[[UINavigationController alloc] initWithRootViewController:[[[iPhoneCreditsViewController alloc] init] autorelease]] autorelease],
nil];
Optionally, you can use a custom background image for each tabs view controller with this method:
- (UIImage *)tabBarController:(JHTabBarController *)tabBarController backgroundImageForTabAtIndex:(NSInteger)index {
NSString *bgImagefilePath;
switch (index) {
case 0:
bgImagefilePath = #"homeBG.png";
break;
case 1:
bgImagefilePath = #"aboutBG.png";
break;
case 2:
bgImagefilePath = #"contactBG.png";
break;
case 3:
bgImagefilePath = #"mapBG.png";
break;
case 4:
bgImagefilePath = #"creditsBG.png";
break;
default:
bgImagefilePath = #"homeBG.png";
break;
}
return [UIImage imageNamed:bgImagefilePath];
}
The arrow at the top of the tab bar slides across to the tab that is selected just like the twitter tab bar.
Some screenshots:
Just 2day I made one app like this one for POC, it turns out that it is easier than you can think.
First in my applicationdidfinishlaunching: method I added the imageview holding the image of pointer or arrow with the width as 64 as the screen width is 320 and I have 5 tabs in the tab bar. you can also calculate it if you think that your project will have dynamic tabs and then just change the width of the imageview accordingly something like this.
CGRect rect = tabBarpointerImageView.frame;
rect.size.width = sel.window.frame.size.width / tabbarcontroller.viewControllers.count;
tabBarpointerImageView.frame = rect;
You might also want to set the content mode of that image view as uiviewcontentmodecenter
Also I have set the frame of the imageview by some calculation like this
CGRect rect = CGRectZero;
rect.size.width = self.window.frame.size.width / tabbarcontroller.viewControllers.count;
rect.size.height = 10;// as image was of 10 pixel height.
rect.origin.y = self.window.frame.size.height - 49;// as the height of tab bar is 49
tabBarpointerImageView.frame = rect;
And then in the delegate method of tab bar controller
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
just use an animation block to animate the movement of pointer like this
[uiview beginanimation:nil context:nil];
CGRect rect = tabBarpointerImageView.frame;
rect.origin.x = rect.size.width * tabbarcontroller.selectedIndex;
tabBarpointerImageView.frame = rect;
[uiview commitanimations];
PS.
Sorry if some spellings are not correct.
I'm trying to make a subclassed UITableViewCell where I draw an image in the upper right corner. I have it working perfectly - except when I set self.backgroundView, my background image covers up the image drawn in drawRect.
There must be a way to be able to set a background image (and the selectedBackgroundView) without covering up what's being done in drawRect.
Am I going about this the wrong way?
EDIT: I've posted an example project with the problem.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
// TODO: figure out why this covers up self.starImage that's drawn in drawRect
self.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellBackground.png"]] autorelease];
}
return self;
}
- (void)drawRect:(CGRect)rect {
[self.starImage drawAtPoint:CGPointMake(self.bounds.size.width - self.starImage.size.width, 0.0)];
}
EDIT 2: at AWrightIV's request, here's how I got it working... which didn't require subclassing UITableViewCell at all. I'm just adding a subview to cell.backgroundView:
// create a UIImageView that contains the background image for the cell
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellBackground.png"]];
// create another UIImageView that contains the corner image
UIImage *starRedImage = [UIImage imageNamed:#"starcorner_red.png"];
UIImageView *starImageView = [[UIImageView alloc] initWithFrame:CGRectMake(297,
0,
starRedImage.size.width,
starRedImage.size.height)];
starImageView.image = starRedImage;
// add the corner UIImageView as a subview to the background UIImageView
[bgImageView addSubview:starImageView];
// set cell.background to use the background UIImageView
cell.backgroundView = bgImageView;
You are not really supposed to mix the drawing with your cell like that, you are operating at a lower-level than the UITableViewCell machinery is operating, and this is why you get this problem.
This is just one of the various problems you will end up running into. You will run into other problems as you go down that path, including problems with how the selection works.
The proper approach is to create a custom UIView that contains the code to draw, and then you can addSubView that into your cell's root view. That will take care of the rendering in the proper order, and wont interfere with the selection system, and will work correctly in this case.
You shouldn't override the -drawRect: of a tablecell. Instead, create a new custom view and add it to the cell's contentView, and draw in there.
Have you tried adding a [super drawRect:rect]; there?
Here's a solution that's a bit of a kludge, but it fits my requirements exactly... with one fatal flaw: when cells get reused, the star corner shows up when I don't want it to.
http://dl.dropbox.com/u/2349787/UIImage_Position_subclassed_cell2.zip
I'm still using drawRect here, but only because self.starImage is null if you access it within the initWithStyle method. Also, instead of adding the subview to self.contentView, I'm adding it to self.backgroundView to prevent the cell's delete button from interfering with it. The star corner is positioned correctly in both portrait and landscape mode, and works fine within edit mode as well.
With the cell reuse issue though, It's still a no go... so, maybe I'm back to trying to do it without subclassing UITableViewCell.
I'm open to any further suggestions. Thank you!
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
// Initialization code
self.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cellBackground.png"]] autorelease];
}
return self;
}
- (void) drawRect:(CGRect)rect {
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(self.bounds.size.width - self.starImage.size.width, 0, self.starImage.size.width, self.starImage.size.height)] autorelease];
imageView.image = self.starImage;
imageView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[self.backgroundView addSubview:imageView];
}