I implemented a TableView to show up a PickerView when a particular row is selected. But that would sometime block the selected cell. So, I want my scrollView to scroll to the selected cell when the pickerView shows up.
Is there anyway to get the current location of the selected row? Such that I can implement something like
//---scroll to the current text field---
CGRect textFieldRect = [currentTextField frame];
[scrollView scrollRectToVisible:textFieldRect animated:YES];
Thanks.
If you want to solve the pickerView or the keyboard hiding the screen, you can try this approach. Implement the heightForFooterInSection and set a height value, and the tableView will scroll up to the same value as you specify there.
-(CGFloat)tableView:(UITableView*)tableView heightForFooterInSection:(NSInteger)section
{
return 70.0;
}
If you just want the tableView to scroll , just implement the scrollToRowAtIndexPath:atScrollPosition:animated:
Edit:
Since you are using a UIScrollView, you can programmatically scroll to a certain region using
[scrollView setContentOffset:CGPointMake(x, y) animated:YES];
Also read through this reference: http://www.aaron.griffith.name/weblog/2011/02/23/scrolling-a-uiscrollview-programmatically/
Related
I am trying to set search bar for table, so can anyone tell me that, is it possible to have uisearchabr when table scroll up / pull up and for other case search bar doesn't get appear on screen. Is it possible? If yes, then how?
Thank you in advance
You can implement scrollViewDelegate scrollViewDidScroll and check the contentOffset to show/hide search bar. Since table view is a subclass of UIScrollView, you can depend on this delegate method to decide when to show/hide it.
Basically when the contentOffset represents the scrolled up position, you can show this search bar and when the contentOffset value starts changing, you can hide the search bar. Use hidden property of the search bar to show/hide it. You can also use removeFromSuperView/addSubview methods.
You can use below code or concept.Concept is in scroll view delegate function you will check the content offset and display the set the search bar object in table view header.
Code :
//MARK: -UIScrollViewDelegate
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
if (scrollView.contentOffset.y <= - 65.0f) {
[self.tableView setTableHeaderView:self.searchBar];
}
}
Make delegate of UIScrollViewDelegate and implement its delegate method,
in this when you start scroll the table then unhide your searchBar and change frame of tableView.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[mySearchBar setHidden:NO];
[quotesTableView setFrame:CGRectMake(0, 44, 320, 416)];
}
Using storyboard, I made this UITableViewController:
Ok, when I start search, in searchBarShouldBeginEditing: I will hide navigation bar and show the scope bar:
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
[self.mySearchBar setShowsScopeBar:YES];
[self.mySearchBar sizeToFit];
[self.mySearchBar setShowsCancelButton:YES animated:YES];
[self.navigationController setNavigationBarHidden:YES animated:YES];
return YES;
}
But the first cell of table is hidden behind the scope bar. I think I need increase the table header, but how I do this? Or have some other way to fix it?
UITableViewDelegate has a method that does this:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
//return height as a float here
}
Implement that in your delegate with the appropriate height.
Alternatively, if the bar is hiding the top of the cell, you may need to move the table view down on the screen by changing its frame like so:
CGRect newFrame = tableView.frame;
newFrame.origin.y += 45; //or whatever number of pixels you want to move it down by
tableView.frame = newFrame;
Answering my own question, looking a little further I found a solution that seems most correct, which is using UISearchDisplayController. Here is the tutorial I followed: https://developer.apple.com/library/ios/#samplecode/TableSearch/Introduction/Intro.html
Using this way, he hides the navigation bar and displays the scope without the need for additional codes and without the problem of the first cell being hidden.
I want to scroll down to given row in my table view.
if I use following code inside a button event it works correctly.
[planTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:7 inSection:0 ] atScrollPosition:0 animated:YES];
But I want to do it just after the page load. Placing above code inside viewDidLoad or viewDidAppear did not work.
Any help??
it's kinda hack, but you also might want to perform the -scrollToRowAtIndexPath:atScrollPosition:animated: with some delay, because when either -viewDidLoad or -viewDidAppear: is called, table view rows haven't been created yet so there's nothing to scroll to.
so:
- (void)doScrolling
{
[planTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:7 inSection:0 ] atScrollPosition:0 animated:YES];
}
and in -viewDidAppear:
[self performSelector:#selector(doScrolling) withObject:nil afterDelay:0.3];
also pay attention to atScrollPosition: argument. it's enum actually:
typedef enum {
UITableViewScrollPositionNone,
UITableViewScrollPositionTop,
UITableViewScrollPositionMiddle,
UITableViewScrollPositionBottom
} UITableViewScrollPosition;
so if the row is visible and 0 is passed, no scrolling will be performed
UITableView is a subclass of UIScrollView, so you can just set the contentOffset of your tableView in viewDidLoad: or viewWillAppear.
If you need to scroll 7 table view cells down in length, calculate the height of these 7 cells (the default is 44px, but if you have custom cell heights you need to factor that in) and set the contentOffset to CGPointMake(0, *calculated height*). In the case of 7 44px height cells, it would be CGPointMake(0, 308).
I have seen this question being addressed several times here at SO, e.g Problem with UIScrollView Content Offset, but I´m still not able to solve it.
My iphone app is basically a tab bar controller with navigation bar. I have a tableview controller made programmatically and a DetailViewController that slides in when I tap a cell in my tableview controller.
The DetailViewController is made in IB and has the following hierarchy:
top view => UIScrollView => UIView => UIImage and a UITextField.
My goal is to be able to scroll the image and text field and this works well. The problem is that my UIScrollView always gets positioned at the bottom instead at the top.
After recommendations her at SO, I have made my UIScrollView same size as the top view and instead made the UIView with the max height (1500) of my variable contents.
In ViewDidLoad I set the contentSize for the UIScrollView (as this is not accessible from IB):
- (void)viewDidLoad {
[scrollView setContentSize:CGSizeMake(320, 1500)];
[scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
NSLog(#"viewDidLoad: contentOffset y: %f",[scrollView contentOffset].y);
}
Specifically setting the contentOffset, I would expect my scrollView to always end up at the top. Instead it always go to the bottom. It looks to me that there is some autoscrolling beyond my control taking place after this method.
My read back of the contentOffset looks OK. It looks to me that there may be some timing related issues as the scrolling result may vary whether animation is YES or NO.
A ugly workaround I have found is by using this delegate method:
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrView {
NSLog(#"Prog. scrolling ended");
[scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}
This brings my scrollview to top, but makes it bounce down and up like a yo-yo
Another clue might be that although my instance variables for the IBOutlet are set before I push the view controller, the first time comes up with empty image and textfield:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (!detailViewController) {
detailViewController = [[DayDetailViewController alloc] init];
}
// Pass dictionary for the selected event to next controller
NSDictionary *dict = [eventsDay objectAtIndex:[indexPath row]];
// This method sets values for the image and textfield outlets
[detailViewController setEventDictionary:dict];
// Push it onto the top of the navigation controller´s stack.
[[self navigationController] pushViewController:detailViewController animated:NO];
}
If I set animation to YES, and switch the order of the IBOutlet setting and pushViewController, I can avoid the emptiness upon initialization. Why?
Any help with these matters are highly appreciated, as this is really driving me nuts!
Inspired of Ponchotg´s description of a programmatically approach, I decided to skip interface builder. The result was in some way disappointing: The same problem, with the scrollview ending up in unpredictable positions (mostly at bottom), persisted.
However, I noticed that the scroll offset error was much smaller. I think this is related to the now dynamic (and generally smaller) value of ContentOffset. After some blind experimenting I ended up setting
[textView setScrollEnabled:YES];
This was previously set to NO, as the UITextView is placed inside the scrollview, which should take care of the scrolling. (In my initial question, I have erroneously said it was a UITextField, that was wrong)
With this change my problem disappeared, I was simply not able to get into the situation with scrollview appearing at bottom anymore in the simulator! (At my 3G device I have seen a slight offset appear very seldom, but this is easily fixed with scrollViewDidEndScrollingAnimation delegate described previously ).
I consider this as solved now, but would appreciate if anyone understand why this little detail messes up things?
OK! i have a question before i can give a correct answer.
Why are you using a UIView inside the Scrollview?
You can always only put your UIImageView and UITextField inside the UIScrollView without the UIView
and set the contentSize dynamically depending on the size of the text.
to give you an example how i do it:
int contSize = 0;
imageView.frame = CGRectMake(10, 0, 300, 190);
imageView.image = [UIImage imageNamed:#"yourimage"];
contSize = 190 //or add extra space if you dont want your image and your text to be so close
[textField setScrollEnabled:NO];
textField.font = [UIFont systemFontOfSize:15];
textField.textColor = [UIColor grayColor];
textField.text = #"YOUR TEXT";
[textField setEditable:NO];
textField.frame = CGRectMake(5, contSize, 310, 34);
CGRect frameText = textField.frame;
frameText.size.height = textField.contentSize.height;
textField.frame = frameText;
contSize += (textField.contentSize.height);
[scrollView setScrollEnabled:YES];
[scrolView setContentSize:CGSizeMake(320, contSize)];
In the above example I first create an int to keep track of the ysize of my view then Give settings and the image to my UIImageView and add that number to my int then i give settings and text to my UITextField and then i calculate the size of my text depending on how long is my text and the size of my font, then add that to my int and finally assign the contentSize of my ScrollView to match my int.
That way the size of your scrollview will always match your view, and the scrollView will always be at top.
But if you don't want to do all this, you can allways just:
[scrollView setContentOffset:CGPointMake(0, 0) animated:NO];
at the end of the code where you set your image and your text, and the NOto avoid the bouncing.
Hope this helps.
I am using Xcode's SplitView template.
I have placed a bunch of text fields on the 'detail' side of the view however I forgot about the keyboard taking up half the screen.
How do I move this detail view up when the keyboard comes onto the screen?
I used this solution from the always-useful Cocoa With Love when I could not use a UIScrollView.
If you want to add a UIScrollView you your hierarchy, it gets even easier. Just insert the UIScrollview in the hierarchy above the text fields and use this code when the user taps the text item to begin editing:
UIScrollView* v = (UIScrollView*) self.view ;
CGRect rc = [textField bounds];
rc = [textField convertRect:rc toView:v];
rc.origin.x = 0 ;
rc.origin.y -= 60 ;
rc.size.height = 400;
[self.scroll scrollRectToVisible:rc animated:YES];
Good Luck!
I had that problem once. My app used a table view to show the fields, so the solution I came up with is to listen the textViewDidBeginEditing to perform a scrollToRowAtIndexPath on the table view:
- (void)textViewDidBeginEditing:(UITextView *)textView{
UITableViewCell *cell = (UITableViewCell*) [[textView superview] superview];
[self.myTableView scrollToRowAtIndexPath:[self.myTableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
If you don't have a table view but a scroll view I think you could take same similar approach but telling the scrollview to scroll to the section you need just as #MystikSpiral told.