How to put text on left and right side of UIButton - ios

I am new to iOS development and I recently got stucked with a problem where I am not able to set text on both sides of a button. Also I wish to add multi-line text in a button (as shown below). I have gone through lot of answers but none of them satisfied my requirement.
Any suggestion or help would greatly be appreciated, thanks!

You should definitely go with a custom UIButton class. The reason for this is that UIButton has other properties that you will want, like being recognized by iOS as a button, conform to Accessibility as a button, show up in storyboard as a button class, let your co-workers see that it actually is a button, have same/similar interface as a button, and so on.
Creating a custom button isn't that hard. Basically, just sub-class UIButton and implement awakeFromNib to set up the internals and layoutSubviews to position and size everything.
Here is an outline of how to do it...
1. Create a UIButton sub-class (.h)
Add the custom interface to the header file. It could look something like this.
#interface MyButton : UIButton
- (void)setServiceText:(NSString *)serviceText;
- (void)setPriceText:(NSString *)priceText;
- (void)setTimeText:(NSString *)timeText;
#end
2. Add controls to hold the internals of your button (.m)
The three labels and a view to use as the red sidebar. From here on you add to the code file.
#interface MyButton ()
#property (strong, nonatomic) UILabel *serviceLabel;
#property (strong, nonatomic) UILabel *priceLabel;
#property (strong, nonatomic) UILabel *timeLabel;
#property (strong, nonatomic) UIView *redSideBarView;
#end
3. Add code corresponding to the interface (.m)
Since UILabel redraws itself when we set the text property, we do not need to do more to make it appear on the button.
- (void)setServiceText:(NSString *)serviceText {
_serviceLabel.text = serviceText;
}
- (void)setPriceText:(NSString *)priceText {
_priceLabel.text = priceText;
}
- (void)setTimeText:(NSString *)timeText {
_timeLabel.text = timeText;
}
4. Implement awakeFromNib (.m)
This method will be called when Storyboard instantiate your button, so here is a good place to create your labels and do other stuff that only needs to be done once.
- (void)awakeFromNib {
[super awakeFromNib];
_sideBarView = [[UIView alloc] initWithFrame:CGRectZero];
_sideBarView.backgroundColor = [UIColor redColor];
[self addSubview:_sideBarView];
_serviceLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_serviceLabel.font = [UIFont systemFontOfSize:18.0];
[self addSubview:_serviceLabel];
_priceLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_priceLabel.textColor = [UIColor greenColor];
_priceLabel.font = [UIFont systemFontOfSize:16.0];
_priceLabel.textAlignment = NSTextAlignmentRight;
[self addSubview:_priceLabel];
_timeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_timeLabel.font = [UIFont systemFontOfSize:14.0];
[self addSubview:_timeLabel];
self.clipsToBounds = YES;
}
5. Add code to layout your button (.m)
This is the final piece of the custom button code. Note that layoutSubviews will usually be called several times during the controls lifetime, so do not add sub-views here. Use it to position and size the internals of your button. self.bounds.size represents the current size of your button, so this is a good reference for all other elements.
- (void)layoutSubviews {
// Layout sub-elements
CGFloat buttonWidth = self.bounds.size.width;
CGFloat buttonHeight = self.bounds.size.height;
_serviceLabel.frame = CGRectMake(30.0, 2.0, buttonWidth * 0.7, buttonHeight * 0.5);
_priceLabel.frame = CGRectMake(buttonWidth - 40, 5.0, 30.0, buttonHeight * 0.4);
_timeLabel.frame = CGRectMake(30.0, buttonHeight * 0.5, buttonWidth * 0.7, buttonHeight * 0.4);
_sideBarView.frame = CGRectMake(0.0, 0.0, 10.0, buttonHeight);
self.layer.cornerRadius = 10.0;
}
6. Use it!
To use it you create a regular button in Storyboard, then in the Identity Inspector, select your new button class. As usual, tie the button to a variable in your view controller class. The variable should be of your button class, of course. That's it for the design!
#property (weak, nonatomic) IBOutlet MyButton *button;
Now don't forget to set the properties.
self.button.backgroundColor = [UIColor lightGrayColor];
[self.button setServiceText:#"FULL SERVICE HAIRCUT"];
[self.button setPriceText:#"$30"];
[self.button setTimeText:#"30 minutes"];
A couple of things I didn't address here was the gradient and the drop shadow. The gradient is probably best done with a CAGradientLayer added to the button's view's layer. The drop shadow needs a bit more coding, since you are clipping the button to have rounded corners. Probably you need to add one more UIView in between to contain everything that you then clip, and then add shadow to the button view.

I wouldn't go with a UIButton but with a UIView with Labels from Xib. Tutorial on that can be found here: link.
Then you may add a target to your UIView, so that when tapping it will call some method (as would UIButton do):
yourView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(buttonTapped))
yourView.addGestureRecognizer(tap)
And method:
#objc func buttonTapped() {
// do what you need on tap here
}
Hope it helps! Please comment if you have questions.
PS. I'm not sure but from what I see you are probably building a UITableView. is it? Can you please show a design of the full screen? If you have many "buttons" like that then it's not a single "button" but a Table View.

To display multiple lines use below code
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.numberOfLines = 2; // or 0(Zero)
And you need to add UIView and add tap gesture to that view and design that view like above image.
For Gestures
//Create tap gustures for view
UITapGestureRecognizer *viewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onClickView:)];
[self.yourViewName addGestureRecognizer: viewTap];
- (void) onClickView:(UITapGestureRecognizer *)recognizer {
//Write your code
}
This is one approach.
And second one is...
For this use UITableViewCell and design that cell.
This is second approach.

Related

how to set (make) a UIButton at bottom of my UITableview?

i have two Viewcontroller. one with tableview,check button, add button at bottom . i just adjust my tableview up and kept my add button at bottom. when user press my add button it will take to next viewcontroller ( i did these thing via storyboard )
Needed:
I need my add button should be bottom to above my table view.when user scroll down my table view also it should stick at centre of my tableview.i have tried with creating seperate view ,but no use can't do that.Here this is my viewcontroller.m file:
Thanks in advance !
I used storyboard ,so i did iboutlet and synthesis it,
#interface ViewController ()
#property (strong) NSMutableArray *notes;
#end
#implementation ViewController
#synthesize tableView;
#synthesize addButton;
my viewdidload:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.title = #"My Notes";
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:tableView];
}
when my add button presses it will move to another viewcontroller:
- (IBAction)addButtonPressed:(id)sender {
AddNoteViewController *addNoteVC = [AddNoteViewController new];
// to remove unused warning....
#pragma unused (addNoteVC)
}
Like this i need but in centre ....
Since you only want the UIButton to hover over your UITableView the solution should be quite easy.
I just created a UIButton which could the one you using.
in your method where you initialise the UIButton (e.g. viewDidLoad)
yourBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[yourBtn setImage:[UIImage imageNamed:#"yourIMG"] forState:UIControlStateNormal];
[yourBtn setTitle:#"+" forState:UIControlStateNormal];
yourBtn.frame = CGRectMake(0, self.view.bounds.size.height -150, buttonwidth, buttonheight);
yourBtn.center = CGPointMake(self.view.center.x, self.view.bounds.size.height -155);
[yourBtn addTarget:self action:#selector(addButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:yourBtn];
If this shouldn't be your solution feel free to comment this answer!
Edit
To set the width and buttonheight just add the following. Write it above the yourBtn.frame line!
CGFloat buttonwidth = 57.5;
CGFloat buttonheight = 57.5;
Edit 2.0
You need to set the segues identifier first in IB. Check: iOS and xcode: how to give a segue a "storyboard id" so that I can programmatically manipulate it
-(IBAction)addButtonPressed:(id)sender {
[self performSegueWithIdentifier:yourSegue sender:self];
}
Cheers
I think instead of frame setting in #MasterRazer's answer you should edit or add NSLayoutAttributeCenterX of your UIButton in IB. Setting that constraint of your button to 0 would make your button stays in the middle and be a clean and good solution for your problem.

iOS UIKit Dynamics - unable to add bouncy behaviour for a view

I am trying to add a bouncy behaviour (collision detection) to view which contains all the contents like buttons and images named as ViewContent [it should fall from top and collide/bounce with the bottom of screen].
Here is my view Hierarchy:
and Code:
viewController.h
#interface LoginViewController : UIViewController <UIScrollViewDelegate, UICollisionBehaviorDelegate>
#property (weak, nonatomic) IBOutlet UIView *viewContent;
#property (nonatomic, strong) UIDynamicAnimator *animator;
#end
in storyboard I've set the viewContent frame as (0, -568, 320, 568) so that is should come from top
viewController.m
#implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:#[viewContent]];
gravityBehavior.gravityDirection = CGVectorMake(0.0, 1.0);
[self.animator addBehavior:gravityBehavior];
UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:#[viewContent]];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
collisionBehavior.collisionDelegate = self;
[self.animator addBehavior:collisionBehavior];
UIDynamicItemBehavior *contentViewBehavior = [[UIDynamicItemBehavior alloc] initWithItems:#[viewContent]];
contentViewBehavior.elasticity = 0.4;
[self.animator addBehavior:contentViewBehavior];
As a result nothing happens. I'm following this tutorial http://www.teehanlax.com/blog/introduction-to-uikit-dynamics/ and able to add a collision detection on a square with frame (100, 100, 100, 100), but not able to add collision on a view having frame (0, 0, 320, 568).
I'm new and can't figure it out, any ideas/suggestion please.
Update
Nib view added as #Fogmeister suggested.
I've added a separate nib view file named as LoginView and assigned the LoginViewController class so that I am able to add IBOutlets and IBActions from this Nib.
In LoginViewController's ViewDidLoad method just added these lines right under the [super viewDidLoad
self.content = [[[NSBundle mainBundle]
loadNibNamed:#"ViewLogin"
owner:self options:nil]
firstObject];
[self.view addSubview:self.content];
rest of the code is remain same except in initWithItems viewContent is just replaced with this newly created view self.content.
At the moment you can't use AutoLayout and UIKit Dynamics together. They just don't work together at all.
Also, the first rule of AutoLayout is that you can't update the frame of a view directly. So your line self.viewContent.frame = CGRectMake = (0, -568, 320, 568); won't work either.
What you need to do with this view is disable AutoLayout in order to use Dynamics.
Seeing as you are using a storyboard then the problem is that disabling auto layout for one view will disable it for all views.
If you just want the main view to bounce then what you can do is define that view in a separate nib (or in code).
Either way you then need to programmatically add that view to the view controller's view.
Then your dynamics will work.

iOS Access dynamically created label from other method

I have created a TableView that contains UIViews, which hold a few other elements. These UIViews are created dynamically, as the data is called from a server. Inside each UIView there is a UILabel and a UIButtton. Once the button is clicked, I would like to have the corresponding label updated with some value. I was able to modify the UIButton and the view itself but unable to modify the UILabel. Here is an example of the method that is called when a UIButton is called. Right now it will change the background color of the corresponding UIView, but the label element does not work as intended. How can accomplish modifying this label element which is a subelement of the UIView?
- (void) heartPlus:(id)sender {
UIButton *button = (UIButton*) sender;
NSInteger id_num = button.tag;
UIView * view = (UIView *)[self.view.superview viewWithTag:id_num];
UILabel * label = (UILabel *)[view viewWithTag:id_num];
label.backgroundColor = [UIColor blueColor];
}
Creating the UIView along with adding the corresponding elements.
UIView * msgView = [[[UIView alloc] initWithFrame:CGRectMake(0,offSet,320,120)] init];
[msgView setTag:someID];
// Add button
UIButton * buttonUpdate = [UIButton buttonWithType:UIButtonTypeRoundedRect];
buttonUpdate.tag = someID;
[buttonUpdate addTarget:self action:#selector(heartPlus:) forControlEvents:UIControlEventTouchUpInside];
UILabel * labelHeart = [[[UILabel alloc] initWithFrame:CGRectMake(280,100,20,10)] init];
labelHeart.tag = someID;
// Add each element to the msgView
[msgView addSubview:buttonUpdate];
[msgView addSubview:labelHeart];
There is still some missing code, but as far as I can see you have the error in heartPlus method and viewWithTag does not return the correct view. Therefore the assignment of backgroundColor fails. The explanation is below:
You are first getting the parent view of view that contains UIButton and UILabel. I assume your view hierarchy looks something like this:
UITableViewCell
UIView (tag: someID)
UILabel (tag: someID)
UIButton (tag: someID)
So, if I assume there is no error in the line below and that it returns correct UITableViewCell (or whatever other view is the parent of both UILabel and UIButton):
UIView * view = (UIView *)[self.view.superview viewWithTag:id_num];
We can clearly see the problem with both UILabel and UIButton having the same tags. So if you ask the UITableViewCell for the view with tag, it will simply fail - returns nil.
There are multiple solutions to this problem, but the problem remains the same.
Do not give the UILabel the same tag as UIButton.
I assume you are a beginner with Objective-C so I would suggest you first look into some tutorials of how UIViews work. But to make it easier for you, here are few options:
Create a custom subclass of the UIView with UIView properties.
Use unique tags for UILabel and for UIButton. To find the correct id_num on click, use introspection and sender's superview, which is passed to you in a method.
You could easily loop through UIView's subviews property (which is an array) and find the UILabel manually - this works, if there is only one UILabel or you are looking for all of them.
But in either case, you need to rethink of how UITableView works. It is not a good practice to ask self.view.superview for viewWithTag and your method could already fail at this point.

why my actual UI layout is not same with my designed layout in xib

this is what I designed in xib, and it's my expectation also.
My ViewControlle.h file:
#interface DetailHeadViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *slideScrollView;
#property (weak, nonatomic) IBOutlet UIImageView *smallImageView;
#property (weak, nonatomic) IBOutlet UIImageView *barBGVImageView;
#end
My ViewController.m file (part of the source code)
- (void)viewDidLoad
{
[super viewDidLoad];
slideScrollView.pagingEnabled = YES;
slideScrollView.showsHorizontalScrollIndicator = NO;
slideScrollView.showsVerticalScrollIndicator = NO;
UIImageView * page1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"headSection_hot1"]];
[slideScrollView addSubview:page1]; //Update 3
}
the result is this,
But actually the correct result is this,
Anyone can help to point out what the problem is?
Thanks in advance
update (remove bar image)
for easier, I remove bar image in xib and also comment out the relatived code.
Please see the following picture.
update 2
IB
To me it looks like your scroll view frame is not set correctly. It should probably be set to 0,0,480,320.
It also looks like the transparency isn't set on the BarImageView. Select the BarImageView in the xib, open up the inspector window, click on the 4th tab, set the background color to Clear Color and reduce the alpha.
You may also want to post how your adding the image to the scroll view as that could create issues as well.
Update 1:
In the viewDidLoad of your DetailHeadViewController try this:
self.scrollView.frame = self.view.bounds;
UIImageView * page1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"headSection_hot1"]];
page1.frame = self.view.bounds;
[self.slideScrollView addSubview:page1];
self.scrollView.contentSize = self.view.bounds.size; // Note that the contentSize must be changed
// from this if you want to scroll.

How to setup a scrollview with many buttons in it?

I have been trying to add buttons on scroll view, but unable to do them. I want to add more 7 buttons in a view, but I want that user can get access to all seven buttons by scrolling down. How can I do that?
Please someone guide me or else provide me a link where I can understand.
EDIT:
I have created a view based application and named as poo1 & in the poo1ViewController.h,
#interface poo1ViewController : UIViewController <infodelegate>
{
IBOutlet UIButton *a;
IBOutlet UIButton *b;
IBOutlet UIButton *c;
IBOutlet UIButton *d;
IBOutlet UIButton *e;
IBOutlet UIScrollView *fView;
}
#property (nonatomic,retain) UIScrollView *fView;;
#property (nonatomic,retain) UIButton *a;
#property (nonatomic,retain) UIButton *b;
#property (nonatomic,retain) UIButton *c;
#property (nonatomic,retain) UIButton *d;
#property (nonatomic,retain) UIButton *e;
-(IBAction) ia:(id)sender;
And in implementation file
#import "poo1ViewController.h"
#implementation poo1ViewController
#synthesize a;
#synthesize b;
#synthesize c;
#synthesize d;
#synthesize e;
#synthesize fView;
-(IBAction) ia:(id)sender {
}
#end
LIke this I have a method for all the button, now I want all the button to be present when the App opens but to access all the user needs to scroll down, I don't know how to implement the scrollview in the present view, so the poo1ViewController.xib view gets to be scrollable.
I had the same problem too. I created buttons programmatically and couldn't access all of them because the view didn't scroll. Important for the scrolling is the last line of my code. First i set a specific starting point "positionX" for the buttons. After that i loop through my database and create a button for each entry. After creating a new button, i increment positionX by the height of a button + 10. When all buttons have been created, the loop ends, and the value of positionX will be also used for the height of my UIScrollView.
int positionX = 10;
for (int i = 0; i < [activities count]; i++) {
//get single object out of nsarray
Activity *activity = [activities objectAtIndex:i];
//create button for an activity
UIButton *activityButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[activityButton setTitle:activity.definition forState:UIControlStateNormal];
activityButton.frame = CGRectMake(10, positionX, 300, 40);
[self.activityScrollView addSubview:activityButton];
positionX += 50;
}
//set the content size of the scroll view
[self.activityScrollView setContentSize:CGSizeMake(320, positionX + 20)];
Maybe this website is useful too. I solved the problem after reading the tutorial.
The UIScrollView won't be scrollable in Interface Builder. You'll either have to stretch it out and add your UIButtons where you want them to be and then resize the UIScrollView at the end, OR you'll need to add your UIButtons programmatically to your UIScrollView.
Personally, I'd opt for doing this one programmatically. You can either create the UIButtons programmatically as well (what I'd opt to do), or if you want to cut corners, you can just add them to your UIScrollView in your xib file and make sure you have an IBOutlet connecting them to your code. Then in your code set their frames to where you want them.
-(void)viewWillAppear:(BOOL)animated {
// CGRectMake(x,y,width,height)
a.frame = CGRectMake(20, 20, a.frame.size.width, a.frame.size.height);
b.frame = CGRectMake(20, 50, b.frame.size.width, b.frame.size.height);
// etc. etc. for the rest of your buttons
Then make sure you set the frame and contentSize of your UIScrollView otherwise it won't scroll.
myScrollView.frame = self.view.frame;
myScrollView.contentSize = CGSizeMake(self.view.frame.size.width,
myScrollView.frame.size.height
+ how many pixels you want it to be able to scroll up and down>;
}

Resources