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>;
}
Related
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.
Here's what I'm trying to achieve, I've created 3 pictures which do a better job describing what I want to do better than I ever could.
Here's what I want to do...
I want to keep "App Title" right where it is. I also have a UIImageView now that takes up the entire screen where the dark black is, and I want it to stay fixed like "App Title".
However on the first image when the user clicks "Create Account" I want to animate all those buttons left and off the screen, and then animate on the "Create Account" buttons from the right.
How can I do this.
Keep in mind I'm using storyboards and auto layout constraints. I've created the view in Picture #1. Now I need to figure out how to animate on the "Create Account" views. How can I do this, while keep using storyboards/IB and autolayout, and have it fit for all phones of course?
Just give you an example about how to do it
First I suggest you to use a contain view to contain your textfields and button.Then it become animate two contain view.
Drag the constraints of x position as outlet,in this demo,it is center x.Also drag the two contain view
#property (weak, nonatomic) IBOutlet UIView *yellowView;
#property (weak, nonatomic) IBOutlet UIView *greenView;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *greenConstraint;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *yellowConstraint;
Then in viewDidLoad,set the yellowView off the screen and set hidden
to YES
- (void)viewDidLoad {
super viewDidLoad];
self.yellowConstraint.constant = CGRectGetWidth(self.view.frame);
[self.view layoutIfNeeded];
self.yellowView.hidden = YES;
}
When click,animate to show the yellow view
- (IBAction)start:(id)sender {
self.yellowConstraint.constant = 0;
self.yellowView.hidden = NO;
self.greenConstraint.constant = -1 * CGRectGetWidth(self.view.frame);
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
self.greenView.hidden = YES;
}];
}
I have custom UITableViewCell like this :
#property (weak) IBOutlet UIDefaultServerButton * defaultButton;
#property (weak) IBOutlet UILabel * nameLabel;
#property (weak) IBOutlet UIRoundButton * deleteButton;
#property (weak) IBOutlet NSLayoutConstraint * buttonHeight;
#property (weak) IBOutlet NSLayoutConstraint * buttonWidth;
#property id <TableViewCellDelegate> delegate;
- (void) setDefaultServer: (BOOL) def;
- (void) animateLock;
- (void) animateTrash;
In the cellForIndex.. I add LongPress recogniser. When long press I call function animateLock.
- (void) animateLock
{
[self.deleteButton setImage:[UIImage imageNamed:#"lock"] forState:UIControlStateNormal];
self.deleteButton.hidden = NO;
self.deleteButton.backgroundColor = [UIColor redColor];
}
The weird thing is that button become visible and image has been change, but backgroundColor is ignored (no matter which color I set).
Why ?
Probably the image you have taken is of the same size as that of your button. Either make your image smaller or increase the area of your button.
The code which you are using is perfectly fine, but the reason of background colors is not visible, is that background image is hiding the background color of UIButton. You can confirm this by commenting the line
[self.deleteButton setImage:[UIImage imageNamed:#"lock"] forState:UIControlStateNormal];
And then button's background will be visible.
If you can elaborate that exactly why you want to set red background of button than i will look into that.
I got stuck with the strange behavior of UIScrollView that I cannot click on the UIButton after I enlarge the contentSize of the UIScrollView.
What I wanted to do:
Show a form with using UIScrollView
After clicking on the submit button, the scroll view will enlarge some amount of height to show further information.
In the further information, I will place and show another UIButton(hidden at the beginning) in order to process to the next step.
The problem is that I placed the new UIButton to the enlarged area and the button is not clickable whereas I placed the UIButton to existing area(the initial frame of scroll view) then the button works normally. For both cases, the scroll bar of the scroll view performs normal behavior.(ie, the scroll end is the new content height)
Here is what I have so far:
A UIView xib (placed all elements inside it including the hidden button)
A UIScrollView (loaded the UIView xib into it)
UIView* view = [[[NSBundle mainBundle] loadNibNamed:#"view" owner:self options:nil] objectAtIndex:0];
[view loaded];
[scrollView addSubview:view];
After the submit button is clicked:
// offset = some amount;
[scrollview setContentSize:CGSizeMake(scrollview.contentSize.width, scrollview.contentSize.height+offset)];
// h = some amount before the end of the scroll view
CGRect r = nextBtn.frame;
r.origin.y = h;
nextBtn.frame = r;
[nextBtn setHidden:NO];
I have tried to change the clipSubviews attribute of scroll view but seems it is not working for my case at all.
Anyone knows how it happens? And is there any better methods to get this job done? (resize the scroll view and then place another button in it)
Any help would be great! Thanks a lot!
I assume that the button is direct or indirect child of the contents view you load from the xib file.
The problem is because you changed the scroll view's contentSize but did not change the frame of the contents view. Superviews participate in touch hit testing. You can place a subview outside of its superview bounds and by default the subview will not be clipped but touch events will not be delivered to it because the superview checks during hit testing that the touch is outside of its bounds and rejects the touch. See UIView hitTest:withEvent: for details.
You can add a button say submit and another button as subview of the scrollview.Keep your another button hidden in start and call setContentsize. now when user clicks on submit button then set another button to visible and again call set content size.In this way you would be able to achieve what you want to.
i have tried to generate scenario for you.I have tried this on view based application with storyboard without auto layout.
so in story board do some thing like this:
#import <UIKit/UIKit.h>
#interface ALViewController : UIViewController
#property (nonatomic, weak) IBOutlet UIScrollView *scroll;
#property (nonatomic, weak) IBOutlet UIButton *btn1;
#property (nonatomic, weak) IBOutlet UIButton *btn2;
===========
implementation:
#import "ALViewController.h"
#interface ALViewController ()
#end
#implementation ALViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.btn2 setHidden:YES];
[self adjustContentSize];
}
-(void)adjustContentSize
{
CGRect contentRect = CGRectZero;
for (UIView *view in self.scroll.subviews)
{
if (![view isHidden]) {
contentRect = CGRectUnion(contentRect, view.frame);
}
}
self.scroll.contentSize = contentRect.size;
}
(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)btnClicked:(id)sender
{
UIButton *btn = (UIButton *)sender;
if (btn.tag ==1)
{
[self.btn2 setHidden:FALSE];
[self adjustContentSize];
}
}
#end
and in storyboard some thing like this:
#end
for your information:view frame 0,0,768,1024
scroll frame: 0,0,768,1024
btn1 frame: 361, 753, 46, 30
btn2 frame: 351, 1032, 46, 30
run your code :
at first your scroll view would be unscrollable because we have set btw 2 to be hidden and set content size.As soon as you will be clicking on btn 1, see code we are making btn 2 visible again and calling set content size.
Conclusion:
the scrollview content size looks for its visible contain of which we can take benefit of.
thanks and regards.
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.