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.
Related
Have UITableviewcell --> inside which i have 4 different UIView and 3 of the views has UIButtons. I want to make UIButton clickable. For the first time the buttons are clickable but when i go to next screen and come back, the buttons don't work. Please let me know how to implement this? Thanks!
PHMyTripView *tripsView=[[PHMyTripView alloc] initWithFrame:CGRectMake(10, 5, self.frame.size.width-20, cell.frame.size.height)];
tripsView.onBaggageClick = ^{
[weakSelf handleBaggagePurchaseTapped];
};
if ([data count]>0) {
[tripsView fillTripData:[data firstObject]];
[tripsView showAncillaries:self.predictiveManager.upcomingCDAirBookingInfo];
}
[cell bringSubviewToFront:tripsView.bagsButton];
[cell.viewPlaceHolder addSubview:tripsView];
This happens because the cells are reusable and if you go to another screen the button may kinda mess round into different cell in UI or functionally.
The way to solve this is to add tag. You can define cell.tag = indexPath.row * 10 or so.
Then when draw the button, you check the condition, if cell.tag == ?, then add your button.
Thank you everyone for your response but they din't work in my case.
Here is the answer. Since the UITableview was reloading when it comes back to the screen.The frames were mis placed and Hence the button was not able to click.
Used this one line code which worked fine.
self.tripsView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
You should turn off delaysContentTouches on each UITableView subview, which is an instance of UIScrollView class.
Subclass UITableView and override initWithFrame method:
.h file
#interface NoDelaysOnTouchTableView : UITableView
#end
And .m file
#import "NoDelaysOnTouchTableView.h"
#implementation NoDelaysOnTouchTableView
- (id) initWithFrame: (CGRect) frame
{
self = [super initWithFrame: frame];
if (self) {
for (id view in self.subviews) {
if ([NSStringFromClass([view class]) isEqualToString: #"UITableViewWrapperView"]) {
if ([view isKindOfClass: [UIScrollView class]]) {
// turn OFF delaysContentTouches in the hidden subview
UIScrollView* scroll = (UIScrollView*)view;
scroll.delaysContentTouches = NO;
}
break;
}
}
}
return self;
}
#end
Next - use this subclass (create an instance of NoDelaysOnTouchTableView) to be able to press UIButton immediately.
I think that the causes would be multiples.
You can try:
check the constraints for each button in your cell
in cellForRow you can do addTarget: for each button with relative #selector and in this method check the object (datasource) associated to button.
do not use addSubView in your cell, instead use a Xib (or define your cell in a storyboard within tableView) so you can set the constraints.
I Hope, i've helped you.
Not specifically about this issue, but for some people it may be the case.Try to add subviews in contentView of the cell.
Instead of addSubview(textField) use contentView.addSubview(textField)
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.
I already have the code to animate UIPickerView to act like iOS keyboard, but the problem is when it's loaded for the first time, the UIPickerView is already shows up. I want to hide it first outside UIView area, until UIButton tapped. so it will animate just like iOS keyboard.
here's the picture to illustrate what I mean :
how can it be done? thank you.
Just set the frame of pickerView accordingly while initiating.
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(100, 900, 200, 200)];
if you want pickerView to appear from bottom then increase the y co-ordinate and if you want pickerView to appear from right then increase the x co-ordinate value
if pickerView is on the UIView which is again on some UIViewController then set the ClipsToBounds to YES.
[yourView setClipsToBounds:TRUE];
Hope this will help you.
Sorry i cant comment so answering from this I think you are already placed an UIpicker view in your view concept is same as #xman said. If you didnt place picker view place it
then in .h create property for picker view
#interface ViewController : UIViewController
{
IBOutlet UIPickerView *statepicker;
}
#property (weak, nonatomic) IBOutlet UIView *statepickerview;
in .m first synthesize
#implementation ViewController
#synthesize statepickerview;
in viewdidLoad initially set frame of picker view out of view example
- (void)viewDidLoad
{
statepickerview.frame = CGRectMake(-9, 506, 367, 263);
[super viewDidLoad];
}
then in action call the frame to visible postion
- (IBAction)ButtonPress:(id)sender {
statepickerview.frame = CGRectMake(0, 250,321, 260);
}
when you press button if it is not visible then try to change the co-ordinates
If this not works properly check this link create view and place the picker view inside the custom view and change the frame size of the view
see this link surely it will help
You can set pickerview's y position with your window's height. Like this :
[self.view addSubview:pickerView];
pickerView.frame = CGRectMake(0, appDelegate.window.frame.size.height,pickerView.frame.size.width,pickerView.frame.size.height)
You have to add pickerview in your view and then set frame of it.
I found answer... case closed... it's all because of 'AutoLayout' is enabled on my XCode Project... when it's disabled, everything works as I expected.
2ND UPDATE
Courtesy of this thread
In iOS6, XCode 4.5, UIScrollView is not Scrolling, despite contentSize being set
the answer has been provided! Turning off Auto Layout on your Storyboard (the entire thing) will fix ScrollView and allow things to scroll properly. Spread the word people!
UPDATE
Added code. Seriously cannot figure out why this will not work on a iPad.
.h file
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#end
.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.contentSize = CGSize(768, 1600);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Again just to clarify I'm using Storyboards, I'm first dragging in a ScrollView, setting the size to standard iPad screen (768x1004 because I have a Nav bar at the top) then adding my image on top of that and setting it's size (768x1600). Then I connect both of these to the header file (as shown above) and still I can't get the image to scroll. I have my view mode set to "Aspect Fit", could this be the issue? I've tried other settings and no luck but not all of them.
Any specific advice would be so appreciated!
ORIGINAL POST
I know there a number of topics out there regarding this one, but I'm having a dog of a time trying to get a ScrollView to work. I am attempting to load an image that is 768x1600 (on an iPad screen only) so that you have to vertically scroll to see more of the image's content. To create the ScrollView, I use a Storyboard and drag a ScrollView into the ViewController frame, align it and ensure interactions are enabled. Then, on top of the ScrollView (also in Storyboard) I add the UIImage I wish to use (ensuring it is a subview) and size it accordingly, then set interactions enabled as well.
No matter how hard I try, I cannot get this to work in Simulator or on my device. I have made sure that my ScrollView is set as a delegate in the IB, that is has an IBOutlet on the header file and is both synthesized and loaded into my implementation file. I have also ensured that I have set contentSize by;
self.scrollView.contentSize = CGSizeMake(768, 1600);
I have also tried to add the UIImage as a Subview via code (as opposed to on the Storyboard) and when I do this the image does not appear when I run Simulator. On top of this, when I click the page no scrolling option is available.
Any help anyone can give me on this one is much appreciated. If code is necessary I will post it.
I think I just figured it out. You say you drug the UIImageView on top of the scroll view.
UIImageView's aren't user-interactable!
Try selecting your image view in Interface Builder and setting 'User interaction enabled' to YES for the image view.
If that doesn't work, I would suggest adding the image view in code (remove it from IB first):
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"someImage.png"]];
self.imageView.frame = CGRectMake(0,0,768,1600);
self.imageView.userInteractionEnable = YES;
[self.scrollView addSubview:self.imageView];
self.scrollView.contentSize = CGSizeMake(768, 1600);
self.scrollView.frame = self.view.bounds;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
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>;
}