Modify Height of Single Tab in UITabBar - iphone

Is there a way so that I can increase the height of a single tab (UITabbarItem) keeping the rest of the tabs with same height in UITabBar.

I am just taking a guess that you are trying to have an instagram (previous instagram) or keek like interface where one of the tabBarItems were much larger than the rest.
You have two options.
Create a customTabBar with one of the items much larger. (I will not recommend this)
Just keep the existing tabBarItems as they are. There is no need for a custom one.
You will just have to create a UIButton with the required height and shape and add that on top of your tabBarItem.
Our work then comes down to creating a subclass of UITabBarController and add a custom UIButton on top of the UITabBar.
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[button setBackgroundImage:highlightImage forState:UIControlStateHighlighted];
CGFloat heightDifference = buttonImage.size.height - self.tabBar.frame.size.height;
if (heightDifference < 0)
button.center = self.tabBar.center;
else
{
CGPoint center = self.tabBar.center;
center.y = center.y - heightDifference/2.0;
button.center = center;
}
[self.view addSubview:button];

From my experience, you must extend the UITabBar class and when you initialize your UITabBarItems, set their heights accordingly. Also, create a background image for your UITabBar.

You can use customTabBar, here you can get sample of it, its nice classes and you can set tabBar item according to your size.
Link

In Swift 2.0, you can have a subclass of UITabBarController and add the UIButton using the following code:
let button: UIButton = UIButton(type: UIButtonType.Custom)
button.backgroundColor = UIColor.clearColor()
let buttonImage: UIImage = UIImage(named: "logo")!
let buttonImageHighlighted: UIImage = UIImage(named: "logoHighlighted")!
button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
button.setBackgroundImage(buttonImage, forState: UIControlState.Normal)
button.setBackgroundImage(buttonImageHighlighted, forState: UIControlState.Highlighted)
let heightDifference:CGFloat = buttonImage.size.height - self.tabBar.frame.size.height;
if (heightDifference < 0) {
button.center = self.tabBar.center;
} else {
var center: CGPoint = self.tabBar.center;
center.y = center.y - heightDifference/2.0;
button.center = center;
}
self.view.addSubview(button)

Related

How can I change the color of a UITextField clearButton?

I would like to change the color of the clearButton that appaers when you are writting on a UItextField. Any suggestion? I am not an advanced interface developer and I have no idea of how to do it.
You should create your own UIButton (with image, you'll need a png of you desiderated button), instance it and put this button in the rightView of your UITextField.
CGFloat myWidth = 26.0f;
CGFloat myHeight = 30.0f;
UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, myWidth, myHeight)];
[myButton setImage:[UIImage imageNamed:#"myButtonImage"] forState:UIControlStateNormal];
[myButton setImage:[UIImage imageNamed:#"myButtonImage"] forState:UIControlStateHighlighted];
[myButton addTarget:self action:#selector(doClear:) forControlEvents:UIControlEventTouchUpInside];
myTextField.rightView = myButton;
myTextField.rightViewMode = UITextFieldViewModeUnlessEditing;
You could need to refine alignments using (these are example values):
myButton.imageEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 0);
Then, you will need to implement method -(void) doClear(id)sender; that will clear your textfield.
Swift 4
I used Giorgio's answer and this is what I went with :
let height = textField.bounds.height / 3
let width = height + 10
let rect = CGRect(x: 0, y: 0, width: width, height: height)
let myButton = UIButton(frame: rect)
myButton.setImage(UIImage(named: "clear button white"), for: .normal)
textField.rightView = myButton
textField.rightViewMode = .always
myButton.imageEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
The normal one :
enter image description here
This one :
enter image description here

How to create a round button?

I want to create a round circular button. This button should look like a circle.
This code gives round rectangular button.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(100, 100, 100, 30);
UIImage *image = [UIImage imageNamed:#"01.png"];
[button setImage:image forState:UIControlStateNormal];
[image release];
I figured out how to create a rounded rectangular button but I want to create a round circle button. What do I need to change?
Tested Code:
.h
#import <QuartzCore/QuartzCore.h>
-(void)roundButtonDidTap:(UIButton*)tappedButton;
.m
#define ROUND_BUTTON_WIDTH_HEIGHT YourButtonWidthToBeSetHere
-(void)roundButtonDidTap:(UIButton*)tappedButton{
NSLog(#"roundButtonDidTap Method Called");
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"TimoonPumba.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(roundButtonDidTap:) forControlEvents:UIControlEventTouchUpInside];
//width and height should be same value
button.frame = CGRectMake(0, 0, ROUND_BUTTON_WIDTH_HEIGHT, ROUND_BUTTON_WIDTH_HEIGHT);
//Clip/Clear the other pieces whichever outside the rounded corner
button.clipsToBounds = YES;
//half of the width
button.layer.cornerRadius = ROUND_BUTTON_WIDTH_HEIGHT/2.0f;
button.layer.borderColor=[UIColor redColor].CGColor;
button.layer.borderWidth=2.0f;
[self.view addSubview:button];
Result
Geometry in this concept
Storyboard Option (should apply to Swift or ObjC) -
If you prefer to work in Storyboards, there's another option.
First, set the width and height to be the same value to make a perfect square.
Second, type in the following attributes. IMPORTANT- make the value of your layer.cornerRadius half the size of your width.
Then, when you run the app, your button will be round.
Try this, it worked for me. It will make your button or any view in circular shape only if you have taken it in square i.e width should be equals to height.
yourButton.layer.cornerRadius = yourButton.bounds.size.width/2;
In Xcode 7.0.0 on IOS 8 this code works perfectly for me.
Provided the length and height of button frame is same.
myButton.clipsToBounds = YES;
myButton.layer.cornerRadius = myButton.layer.frame.size.width/2;
UIButton *myButton=[UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(50,50,30,30);
[myButton addTarget:self action:#selector(buttonEvent) forControlEvents:UIControlEventTouchUpInside];
[myButton setImage:[UIImage imageNamed:#"sarabjit.png"] forState:UIControlStateNormal];
[self.view addSubView:myButton];
Using Swift like the answer of
Vijay-Apple-Dev.blogspot :
let ROUND_BUTTON_WIDTH_HEIGHT YourButtonWidthToBeSetHere
override func viewDidLoad() {
super.viewDidLoad()
var button = UIButton.buttonWithType(.Custom) as UIButton
button.frame = CGRectMake(160, 100, ROUND_BUTTON_WIDTH_HEIGHT, ROUND_BUTTON_WIDTH_HEIGHT)
button.layer.cornerRadius = ROUND_BUTTON_WIDTH_HEIGHT / 2.0
button.layer.borderColor = UIColor.redColor().CGColor
button.layer.borderWidth = 2.0
button.setImage(UIImage(named:"TimoonPumba.png"), forState: .Normal)
button.addTarget(self, action: "roundButtonDidTap", forControlEvents: .TouchUpInside)
button.clipsToBounds = true
view.addSubview(button)
}
func roundButtonDidTap() {
NSLog(#"roundButtonDidTap Method Called");
}
override func viewDidLoad() {
super.viewDidLoad()
let facebookButton = UIButton()
facebookButton.frame = CGRectMake(30, 200, 150, 150)
facebookButton.layer.cornerRadius = 75
facebookButton.layer.masksToBounds = true
self.view.addSubview(facebookButton)
}
** To make round button you have to give same height and same width for the button and half of the value should be given to corner radius **
Step 1. Use [UIButton buttonWithType:UIButtonTypeCustom] to create the button.
Step 2. CGRectMake(100, 100, 100, 30) is a rectangular shape. Maybe you want to use the size of your image instead, like this:
CGRect frame = CGRectMake(100, 100, 0, 0);
frame.size = img.size;
button.frame = frame;
a round-rect button with circular image does not satisfy the need of a round Button. Nor even if they are made custom buttons. This is because, This buttons will respond to taps even outside the circular part ( which is a just a .png image ) if it is inside the button size range and not clipped.
The first answer(and only the first one by #vijay-apple-dev) given here is correct. You need to clip the boundary of the button frame in order to stop it responding just outside the image
make a
[UIButton buttonWithType:UIButtonTypeCustom];
and try to use the corner radius property
button.layer.cornerRadius = button.bounds.size.width/2 / 2.0

Basic Drag and Drop in iOS

I want to have a view in which there are vehicles driving around that the user can also drag and drop. What do you think is the best large-scale strategy for doing this? Is it best to get touch events from the views representing the vehicles, or from the larger view? Is there a simple paradigm you've used for drag and drop that you're satisfied with? What are the drawbacks of different strategies?
Assume you have a UIView scene with a background image and many vehicles, you may define each new vehicle as a UIButton (UIImageView will probably work too):
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(imageTouch:withEvent:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button setImage:[UIImage imageNamed:#"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];
Then you may move the vehicle wherever you want, by responding to the UIControlEventTouchDragInside event, e.g.:
- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
CGPoint point = [[[event allTouches] anyObject] locationInView:self.view];
UIControl *control = sender;
control.center = point;
}
It's a lot easier for individual vehicle to handle its own drags, comparing to manage the scene as a whole.
In addition to ohho's answer I've tried similar implementation, but without problem of "fast" drag and centering to drag.
The button initialization is...
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:#selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button addTarget:self action:#selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragOutside];
[button setImage:[UIImage imageNamed:#"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];
and method implementation:
- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
UIControl *control = sender;
UITouch *t = [[event allTouches] anyObject];
CGPoint pPrev = [t previousLocationInView:control];
CGPoint p = [t locationInView:control];
CGPoint center = control.center;
center.x += p.x - pPrev.x;
center.y += p.y - pPrev.y;
control.center = center;
}
I don't say, that this is the perfect solution for the answer. Nevertheless I found this the easiest solution for dragging.
I had a case where I would like to drag/drop uiviews between multiple other uiviews. In that case I found the best solution to trace the pan events in a super view containing all the drop zones and all the drag gable objects. The primary reason for NOT adding the event listeners to the actual dragged views was that I lost the ongoing pan events as soon as I changed superview for the dragged view.
Instead I implemented a rather generic drag drop solution that could be used on single or multiple drop zones.
I have created a simple example that can be seen here: Drag an drop uiviews between multiple other uiviews
If you decide to go the other way, try using uicontrol instead of uibutton. They declare the addTarget methods and are much easier to extend - hence give custom state and behavior.
I would actually track dragging on the vehicle view itself, rather than the large view - unless there is a particular reason no to.
In one case where I allow the user to place items by dragging them on the screen.
In that case I experimented with both having the top view and the child views draggable. I found it's cleaner code if you add a few "draggable" views to the UIView and handle how to they could be dragged. I used a simple callback to the parent UIView to check if the new location was suitable or not - so I could indicate with animations.
Having the top view track dragging I guess is as good, but that makes it slightly more messy if you would like to add non-draggable views that still interact with the user, such as a button.
-(void)funcAddGesture
{
// DRAG BUTTON
UIPanGestureRecognizer *panGestureRecognizer;
panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragButton:)];
panGestureRecognizer.cancelsTouchesInView = YES;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(50, 100, 60, 60);
[button addTarget:self action:#selector(buttontapEvent) forControlEvents:UIControlEventPrimaryActionTriggered];
[button setImage:[UIImage imageNamed:#"button_normal.png"] forState:UIControlStateNormal];
[button addGestureRecognizer:panGestureRecognizer];
[self.view addSubview:button];
}
- (void)dragButton:(UIPanGestureRecognizer *)recognizer {
UIButton *button = (UIButton *)recognizer.view;
CGPoint translation = [recognizer translationInView:button];
float xPosition = button.center.x;
float yPosition = button.center.y;
float buttonCenter = button.frame.size.height/2;
if (xPosition < buttonCenter)
xPosition = buttonCenter;
else if (xPosition > self.view.frame.size.width - buttonCenter)
xPosition = self.view.frame.size.width - buttonCenter;
if (yPosition < buttonCenter)
yPosition = buttonCenter;
else if (yPosition > self.view.frame.size.height - buttonCenter)
yPosition = self.view.frame.size.height - buttonCenter;
button.center = CGPointMake(xPosition + translation.x, yPosition + translation.y);
[recognizer setTranslation:CGPointZero inView:button];
}
- (void)buttontapEvent {
NSLog(#"buttontapEvent");
}
ohho's answer worked well for me. In case you need the swift 2.x version:
override func viewDidLoad() {
let myButton = UIButton(type: .Custom)
myButton.setImage(UIImage(named: "vehicle"), forState: .Normal)
// drag support
myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragInside)
myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragOutside)
}
private func imageMoved(sender: AnyObject, event: UIEvent) {
guard let control = sender as? UIControl else { return }
guard let touches = event.allTouches() else { return }
guard let touch = touches.first else { return }
let prev = touch.previousLocationInView(control)
let p = touch.locationInView(control)
var center = control.center
center.x += p.x - prev.x
center.y += p.y - prev.y
control.center = center
}
Here's the best way to do drag and drop as of iOS 11:
https://developer.apple.com/documentation/uikit/drag_and_drop/adopting_drag_and_drop_in_a_custom_view
For Swift 4 Easy and easiest way. 😛
Step 1:
Connect Your Button From Storyboard To View Controller. And Set The all Basic AutoLayout Constraints
#IBOutlet weak var cameraButton: UIButton!
Step 2:
Add Pan Gesture for your button In viewDidLoad()
self.cameraButton.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGestureHandler(panGesture:))))
Step 3:
Add panGestureHandler
#objc func panGestureHandler(panGesture recognizer: UIPanGestureRecognizer) {
let location = recognizer.location(in: view)
cameraButton.center = location
}
And Now Your Button Action
#IBAction func ButtonAction(_ sender: Any) {
print("This is button Action")
}
Add See the Result ☝️

Custom button in tabbar problem

I've a TabBarController Application.
This code in didFinishingLaunching method:
UIImage *buttonImage = [UIImage imageNamed:#"post-button2.png"];
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
NSLog(#"Button size: %f, %f", buttonImage.size.width, buttonImage.size.height);
button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
CGFloat heightDifference = buttonImage.size.height - self.tabBarController.tabBar.frame.size.height;
NSLog(#"self.tabBarController.tabBar.frame.size.height: %f", self.tabBarController.tabBar.frame.size.height);
NSLog(#"heightDifference: %f", heightDifference);
NSLog(#"%Tabbar: %f, %f", tabBarController.tabBar.center.x, tabBarController.tabBar.center.y);
if (heightDifference < 0)
button.center = tabBarController.tabBar.center;
else {
CGPoint center = self.tabBarController.tabBar.center;
center.y = center.y - heightDifference/2.0;
button.center = tabBarController.tabBar.center;
}
NSLog(#"%Button: %f, %f", button.center.y, button.center.x);
[tabBarController.view addSubview:button];
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
The output is:
Where is the problem? I can solve with hardcoded code:
CGPoint center = tabBarController.tabBar.center;
center.x = 160.00;
center.y = 455.50;
button.center = center;
But I'm not sure that is correct.
Ty.
To set the image of a tab you need to set the tabBarItem of the viewcontroller associated with the tab.
See UITabBarItem ref for how to create one with custom image.
So you create a UITabBarItem object with the custom image and then make it the tabBarItem property of the viewcontroller for the tab.
The UITabBarController will then manage putting the image in the right place.

UIButton title and image alignment query

I have a UIButton and I am trying to set a title and an image on it.
I would like to align the title for a UIButton to the left side and place an image aligned to the right. I am trying to get the look and feel of the button in Timer in Clocks app (the one which says "When Timer Ends").
I fiddled with contentHorizontalAlignment, contentEdgeInsets, titleEdgeInsets and imageEdgeInsets to achieve my goal, but to no avail. The documentation is also quite sparse for the same.
How can I achieve the same?
Also related questions, Timer in Clocks app has two set of Text, one aligned to the left and other aligned right with the image? How can that be done in a UIButton? ( I do not need that functionality though at the moment).
Here is the code I use for that:
//Right-align the button image
CGSize size = [[myButton titleForState:UIControlStateNormal] sizeWithFont:myButton.titleLabel.font];
[myButton setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, -size.width)];
[myButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, 0, myButton.imageView.image.size.width + 5)];
Change the imageEdgeInsets property on the UIButton and then just use setImage:forState:
The following code works:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = buttonRect;
[button setTitle:#"A title" forState:UIControlStateNormal];
[button setImage:buttonImage forState:UIControlStateNormal];
button.imageEdgeInsets = UIEdgeInsetsMake(0.0, WIDTH(button.titleLabel) + 10.0, 0.0, 0.0);
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
Remember that UIButton inherits from UIView, and so you can add subviews to it just like any other view. In your situation, you would create a button, then add a UILabel on the left side and a UIImage on the right:
// Create the button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// Now load the image and create the image view
UIImage *image = [UIImage imageNamed:#"yourImage.png"];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(/*frame*/)];
[imageView setImage:image];
// Create the label and set its text
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(/*frame*/)];
[label setText:#"Your title"];
// Put it all together
[button addSubview:label];
[button addSubview:imageView];
You can also override the titleRectForContentRect: and imageRectForContentRect: methods of the UIButton in order position your text and image anywhere you want.
In Swift for anyone that cares (with a 10pt spacing):
let size = (self.titleForState(UIControlState.Normal)! as NSString).sizeWithAttributes([NSFontAttributeName:self.titleLabel!.font])
let offset = (size.width + 10)
self.imageEdgeInsets = UIEdgeInsetsMake(0, offset, 0, -offset)
self.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, self.imageView!.frame.size.width + 10)
For using on iOS 9, i tried many answers in this thread but none of them suitable for me. I found answer for myself as follow:
class MyButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
self.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
if self.imageView?.image != nil {
// Move icon to right side
self.imageEdgeInsets = UIEdgeInsets(
top: 0,
left: self.bounds.size.width - self.imageView!.image!.size.width,
bottom: 0,
right: 0)
// Move title to left side
self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView!.frame.size.width + 8, 0, 0)
}
}
}
SWIFT 3:
class MyButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
self.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left
if self.imageView?.image != nil {
// Move icon to right side
self.imageEdgeInsets = UIEdgeInsets(
top: 0,
left: self.bounds.size.width - self.imageView!.image!.size.width,
bottom: 0,
right: 0)
// Move title to left side
self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView!.frame.size.width + 8, 0, 0)
}
}
}
I hope it will help somebody in the case as me!
Here's a subclass of UIButton in Swift that aligns the image on the left and the text in the centre. Set imageLeftInset to your desired value.
class LeftImageAlignedButton : UIButton {
var imageLeftInset : CGFloat = 10.0
override func layoutSubviews() {
super.layoutSubviews()
self.contentHorizontalAlignment = .Left
if let font = titleLabel?.font {
let textWidth = ((titleForState(state) ?? "") as NSString).sizeWithAttributes([NSFontAttributeName:font]).width
let imageWidth = imageForState(state)?.size.width ?? 0.0
imageEdgeInsets = UIEdgeInsets(top: 0, left: imageLeftInset, bottom: 0, right: 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: bounds.width/2 - textWidth/2.0 - imageWidth, bottom: 0, right: 0)
}
}
}
Create a UIButton subclass and override its layoutSubviews method to align your text & image programmatically. Or use something like https://github.com/stevestreza/BlockKit/blob/master/Source/UIView-BKAdditions.h so you can implement layoutSubviews using a block.