I'm trying to set the ContentSize of my UIScrollView automatically, but when I do it, the frame height of uiscrollview is not with the screenHeight as I want.
There's my code:
-(void) viewWillAppear:(BOOL)animated {
[self.scrollGeral setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.scrollGeral setContentSize:(CGSizeMake(screenSize.size.width, [self calcularAlturaScrollView]))];
}
-(CGFloat) calcularAlturaScrollView {
CGFloat scrollViewHeight = 0.0f;
for (UIView* view in self.scrollGeral.subviews)
{
scrollViewHeight += view.frame.size.height;
}
return scrollViewHeight;
}
Therefore, I'have tried to include the following line:
[self.scrollGeral setFrame:CGRectMake(0, 0, screenSize.size.width, screenSize.size.height)];
But if I do it, the UIScrollView 'disabled' the scroll
I solved my problem with the following code:
-(void) viewDidLayoutSubviews {
[self.scrollGeral setContentSize:(CGSizeMake(screenSize.size.width, [self calcularAlturaScrollView]))];
}
Related
I have text fields on registration screen so when keyboard appears i am moving up the view up.Now i want to scroll through text fields when i my view is moved up.
code for moving view up:
CGRect rect = self.view.frame;
rect.origin.y += 220;
rect.size.height -= 220;
self.view.frame = rect;
Here is hirecrchy
I have UIScrollView at top then under UIScrollView i have UIView i call it as contentView.On the contentView i have added some text fields.So my parent view is moved up fine but i am not able to scroll the textFields up & down when i view is up. I set the following value for scrolling.
self.cvHeight.constant=500;
self.scrollView.contentSize=CGSizeMake(500, 500);
Here cvHeight is outlet of height constraint of the contentView & scrollView is outlet of UIScrollView
Edit:
When i am not moving the parentView up which is self.view then i am able to scroll through but if i move the parent view up then my textFields are not scrolling down they are just moving up.
As you are using UIScrollView, this will be the best for you. Use TPKeyboardAvoidingScrollView
How to use?
Its very simple
For use with UITableViewController classes, drop TPKeyboardAvoidingTableView.m and TPKeyboardAvoidingTableView.h into your project, and make your UITableView a TPKeyboardAvoidingTableView in the xib. If you're not using a xib with your controller, I know of no easy way to make its UITableView a custom class: The path of least resistance is to create a xib for it.
For non-UITableViewControllers, drop the TPKeyboardAvoidingScrollView.m and TPKeyboardAvoidingScrollView.h source files into your project, pop a UIScrollView into your view controller's xib, set the scroll view's class to TPKeyboardAvoidingScrollView, and put all your controls within that scroll view. You can also create it programmatically, without using a xib - just use the TPKeyboardAvoidingScrollView as your top-level view.
- (void)keyboardWillShow:(NSNotification*)notification
{
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0,0.0,keyboardSize.height, 0.0);
self.scrollViewPost.contentInset = contentInsets;
self.scrollViewPost.scrollIndicatorInsets = contentInsets;
CGRect rect = self.scrollViewPost.frame;
rect.size.height = keyboardSize.height+_scrollViewPost.frame.size.height+84;
if (!CGRectContainsPoint(rect, self.txtPost.frame.origin))
{
CGPoint scrollPoint = CGPointMake(0.0, 264+Table_Y);
[self.scrollViewPost setContentOffset:scrollPoint animated:NO];
self.viewPutPost.frame=CGRectMake(0, _viewPutPost.frame.origin.y-254, 320, 30);
}
}
- (void)keyboardWillHide:(NSNotification *)notification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollViewPost.contentInset = contentInsets;
self.scrollViewPost.scrollIndicatorInsets = contentInsets;
self.viewPutPost.frame=CGRectMake(0,537 , 320, 30);
}
ViewController.h
#import <UIKit/UIKit.h>
#interface SignUp : UIViewController <UIScrollViewDelegate>
{
}
#property (nonatomic, assign) UITextField *activeTextField;
ViewController.m
#implementation SignUp
#synthesize activeTextField;
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
#pragma mark - Textfield
- (void)keyboardWasShown:(NSNotification *)notification
{
// Step 1: Get the size of the keyboard.
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// Step 2: Adjust the bottom content inset of your scroll view by the keyboard height.
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
_scrl.contentInset = contentInsets;
_scrl.scrollIndicatorInsets = contentInsets;
// Step 3: Scroll the target text field into view.
CGRect aRect = self.view.frame;
aRect.size.height -= keyboardSize.height;
if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) )
{
CGPoint scrollPoint = CGPointMake(0.0, self.activeTextField.frame.origin.y - (keyboardSize.height));
[_scrl setContentOffset:scrollPoint animated:YES];
}
}
- (void) keyboardWillHide:(NSNotification *)notification {
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
_scrl.contentInset = contentInsets;
_scrl.scrollIndicatorInsets = contentInsets;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
self.activeTextField = nil;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
self.activeTextField = textField;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField; // called when 'return' key pressed. return NO to ignore.
{
if(textField == _txt_name)
{
[_txt_email becomeFirstResponder];
return NO;
}
else if(textField == _txt_email)
{
[_txt_pwd becomeFirstResponder];
return NO;
}
else if(textField == _txt_pwd)
{
[_txt_repwd becomeFirstResponder];
return YES;
}
else if (textField == _txt_repwd)
{
[textField resignFirstResponder];
return YES;
}
else
{
return YES;
}
}
You don't have to move the whole view up.
Instead, change the contentOffset property of the scrollview according to your need, and increase the scrollView.contentSize accordingly when the keyboard is up.
And when keyboard is down set scrollView.contentOffset to CGPointZero and scrollView.contentSize
When your keyboard is up:
CGFloat yOffset = ; //Set According to the textField
self.scrollView.contentOffset = CGPointMake(0,-yOffset);
//Increase content size to enable scrolling till the end.
CGFloat contentHeight = self.crollView.contentSize.height + keyboardHeight;
self.scrollView.contentSize = CGSizeMake(kScreenWidth, contentHeight);
When keyboard is down:
self.scrollView.contentOffset = CGPointMake(0,0);
//Increase content size to enable scrolling till the end.
CGFloat contentHeight = self.crollView.contentSize.height - keyboardHeight;
self.crollView.contentSize = CGSizeMake(kScreenWidth, contentHeight);
Increasing the content size will enable you to scroll the scrollview till bottom when the keyboard is up.
I'm trying to implement a growing UITextView with the content size, I am using this class and autolayout and it works great but my problem is that my inner scroll view is not scrolling.
It was scrolling before adding the methods for growing text view in viewDidLoad.
This is what is in my xib:
View
outerScrollView
innerScrollView
labels
Growing UITextView
I do this to switch scrolling between scrollview
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if([scrollView isEqual:self.innerScrollview]){
self.outerScrollview.scrollEnabled = NO;
self.innerScrollview.scrollEnabled = YES;
}
else{
self.outerScrollview.scrollEnabled = YES;
self.innerScrollview.scrollEnabled = NO;
}
}
and in viewDidLoad where the "msg" is the growing textview:
self.msgHandler = [[GrowingTextViewHandler alloc]initWithTextView:self.msg withHeightConstraint:self.msgHeight];
[self.msgHandler updateMinimumNumberOfLines:1 andMaximumNumberOfLine:INT_MAX];
and in textViewDidChange
- (void)textViewDidChange:(UITextView *)textView {
[self.msgHandler resizeTextViewWithAnimation:YES];
}
so why is the growing text affecting the scrolling of the inner scrollview?
int outerContentHeight = self.outer_last_label.frame.size.height + self.outer_last_label.frame.origin.y;
int innerContentHeight = self.inner_last_label.frame.size.height + self.inner_last_label.frame.origin.y;
[self.outerSrollview setContentSize:CGSizeMake([[UIScreen mainScreen] bounds].size.width,outerContentHeight)];
[self.innerScrollview setContentSize:CGSizeMake(self.scrollview2.frame.size.width, innerContentHeight)];
I have managed to fix it but I removed the use of the class"GrowingTextViewHandler" and I did this instead
I changed "scrollViewDidScroll" to this:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if([scrollView isEqual:self.innerScrollview]){
[self.view insertSubview:self.innerScrollview atIndex:0];
}
else{
[self.view insertSubview:self.outerScrollview atIndex:0];
}
}
and changed "textViewDidChange" to this
- (void)textViewDidChange:(UITextView *)textView {
float height = self.msg.contentSize.height;
[UITextView beginAnimations:nil context:nil];
[UITextView setAnimationDuration:0.5];
self.msgHeightConstraint.constant = height + 10.0; //Give it some padding
[UITextView commitAnimations];
}
Please set the content size of the scroll view, Do not change anything in the code, and check,
[self.scrollViewOuter setContentSize:CGSizeMake(200, 1000)];
[self.scrollViewInner setContentSize:CGSizeMake(200, 1000)];
My both the scroll views are working if, I add content size in it.
In my iOS application i have a scrollview in which there are many imageviews and textviews.
I have to move all this views down to a fixed value, but i don't want to move them to left, right or resize them. I just want to move them down, on an event. The problem is that i can't know which are the values of these UIView.
This is my code:
for(UIView* subview in [myScrollView subviews])
{
subview.frame = CGRectMake(0, 0, screenWidth, screenHeight);
}
i'd like to do this:
for(UIView* subview in [myScrollView subviews])
{
subview.frame = CGRectMake(previousValue+100, previousValue, previousValue, previousValue);
}
I hope I explained myself
If you just want to move them down, why don't you just set scrollView's contentInset?
scrollView.contentInset = UIEdgeInsetsMake(100, previousValue, previousValue, previousValue);
this will make all your subViews down.
try something like this:
UIView *lastView;
for(UIView* subview in [myScrollView subviews])
{
CGrect lastFrame;
if (!lastView) {
lastFrame = CGRectMake(0,0,100,100); // your initial frame
} else {
lastFrame = lastView.frame;
}
lastFrame.origin.x += 100;
subview.frame = lastFrame;
lastView = subview;
}
I have a really big problem with UIScrollView. To make sure it wasn't my actual project, I created a NEW project, iPhone only, for iOS 6 and 7. I disabled autolayout.
I created a Tab Bar project
I created a view controller,
embedded it in a navigation controller and connected it as Tab bar
item #0
I put a UIScrollView in my view.
I connected the scrollview in the custom UIViewController created for this view.
I synthesized my IBOutlet and set the delegate to self. I also
implemented delegate in .h
Here is my code (ViewDidLoad):
self.scrollView.delegate = self;
[self.scrollView setScrollEnabled:YES];
[self.scrollView setContentSize:CGSizeMake(self.view.frame.size.width, 20000)];
NSLog(#"contentSize width %f", self.scrollView.contentSize.width);
NSLog(#"contentSize height %f", self.scrollView.contentSize.height);
NSLog(#"%#", NSStringFromCGAffineTransform(self.scrollView.transform));
It returns me "contentSize width 20000.000000", "contentSize height 0.000000
" and "[1, 0, 0, 1, 0, 0]". It scrolls left-right where it should scroll up-down
Please help!
I had the same issue until I realized I hadn't set the UIScrollView delegate. Also, if you're using auto layout, you need to wait for the layout to be applied to the UIScrollView. This means you should set the Content Size in "viewDidLayoutSubviews".
In viewDidLoad method, frame may not be correct, move the code to this method:
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
// Your code
}
Use this code. ScrollView setContentSize should be called async in main thread.
Swift:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
DispatchQueue.main.async {
var contentRect = CGRect.zero
for view in self.scrollView.subviews {
contentRect = contentRect.union(view.frame)
}
self.scrollView.contentSize = contentRect.size
}
}
Objective C:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
dispatch_async(dispatch_get_main_queue(), ^ {
CGRect contentRect = CGRectZero;
for(UIView *view in scrollView.subviews)
contentRect = CGRectUnion(contentRect,view.frame);
scrollView.contentSize = contentRect.size;
});
}
Okay, there is absolutely nothing wrong with your code. So some suggestions:
Make sure you added to your .h file like so:
#interface yourViewController : UIViewController <UIScrollViewDelegate> {
}
Try moving this snippet of code to the "viewWillLoad" method:
- (void)viewWillAppear:(BOOL)animated {
self.scrollView.delegate = self;
[self.scrollView setScrollEnabled:YES];
[self.scrollView setContentSize:CGSizeMake(self.view.frame.size.width, 20000)];
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var contentRect = CGRect.zero
for view: UIView in scrollView.subviews {
if !view.isHidden {
contentRect = contentRect.union(view.frame)
}
}
scrollView.contentSize = contentRect.size
scrollView.contentSize.width = self.view.frame.width
}
Working Swift 3.X code. Converted #Karen Hovhannisyan's answer.
I have two scrollViews i.e one inside other,
-OuterScroll
----InnerScroll
Need Outer scrollView to stop automatically and inner starts in a single scroll when outer ScrollView reaches contentOffSet value of greater than 300.
So far..
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
[self.view endEditing:YES];
if (scrollView ==scrollSuperView)
{
if (scrollView.contentOffset.y>300) {
[scrollContentView setScrollEnabled:YES];
}else if (scrollView.contentOffset.y<10){
[scrollContentView setScrollEnabled:NO];
}
}
}
By the way scrollSuperView is outerScroll and scrollContentView is inner.
Any help appreciated.
1.scrollSuperView (Outer)
frame = CGRect(0, 0, 320, 468)
contentSize = CGSizeMake(320, 600)
2.scrollContentView (Inner)
frame = CGRect(0, 300, 320, 468)
contentSize = CGSizeMake(320, 600)
So i have above two scrollViews as mentioned outer and inner
Once outer scrollView reaches content offset of >300 then scrollEvent much be passed to inner ScrollView if user is scrolling by putting finger on inner ScrollView..
Hope its more clear now.
Setting outer scrollView's delaysContentTouches to NO will pass touch events from outer scrollView to inner scrollView... "in a single move"
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == scrollSuperView) {
//outer scrollView
if (scrollView.contentOffset.y >= 300) {
//NSLog(#"Outer scrollView ContentOffset has reached 300");
[scrollSuperView setDelaysContentTouches:NO];
[scrollContentView setScrollEnabled:YES];
}
}
else if (scrollView == scrollContentView) {
//inner scrollView
if (scrollView.contentOffset.y == 0) {
//NSLog(#"Inner scrollView ContentOffset has reached 0");
[scrollSuperView setDelaysContentTouches:YES];
[scrollContentView setScrollEnabled:NO];
}
}
}
Assumptions:
scrollSuperView (Outer)
frame = CGRect(0, 0, 320, 300)
contentSize = CGSizeMake(320, 600)
delaysContentTouches = YES
scrollEnabled = YES
scrollContentView (Inner)
frame = CGRect(0, 400, 320, 200)
contentSize = CGSizeMake(320, 400)
delaysContentTouches = YES
scrollEnabled = NO
-(void)viewDidLoad{
//write your code here
innerScrollView.scrollEnabled =NO;
outerScrollView.scrollEnabled =YES;
//above two lines makes touch(scroll) events given to outer and not inner.
}
And your modified method,
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
[self.view endEditing:YES];
if (scrollView ==scrollSuperView)
{
if (scrollView.contentOffset.y>300) {
outerScrollView.scrollEnabled =NO;
innerScrollView.scrollEnabled =YES;
[outerScrollView setContentOffset:CGPointMake(0, 200)];
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
[self.view endEditing:YES];
if (scrollView ==scrollSuperView && decelerate==NO)
{
if (scrollView.contentOffset.y>300) {
outerScrollView.scrollEnabled =NO;
innerScrollView.scrollEnabled =YES;
[outerScrollView setContentOffset:CGPointMake(0, 200) animated:YES];
}
}
}