scrolling other UITableview at the same time as another UItableview - iphone

I have a quite complicated view. What I basicly have is the following
You can see I have a vertical tableview. In each cell I have a horizontal tableview. What I want to do now is when I scroll one horizontal tableview, every other horizontal tableview should scroll also.
In my subClass of the vertical tableviewCell I have the following.
for(HorizontalTableCell *cell in mainTable.subviews){
if([cell isKindOfClass:[HorizontalTableCell class]]){
for(UITableView *cellTable in cell.subviews){
if([cellTable isKindOfClass:[UITableView class]]){
NSLog(#"cell table is table %#",cellTable);
[cellTable setContentOffset:CGPointMake(scrollView.contentOffset.x, 0) animated:NO];
}
}
}
}
But this is not working OK. Can anybody help me with this?

You will need to use the scroll view delegate methods. I'd suggest posting a Notification and then picking it up in the cells like so...
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"CellScrolledHorizontally" object:self.tableView];
}
Then in the horizontal cells you can observe the notification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(scrolled:) name:#"CellScrolledHorizontally" object:nil];
- (void)scrolled:(NSNotification *)notification
{
UITableView *notificationTableView = notification.object;
if (notificationTableView == self.tableView)
return;
[self.tableView setContentOffset:notificationTableView.contentOffset];
}
Alternatively, use a UICollectionView.

Can u try this logic:
Instead of Horizontal tableviews use a UIScrollView. Now the base is a UITableView on which the horizontal scrollviews. Now use UIScrollview delegate methods for event handling.
Although this is not the solution but you can look at EASYTABLEVIEW

Related

How can i set content offset on multiple scrollviews with one method?

I am having a little problem. I want to make all my scrollview scroll to the top when I press a UITableViewCell. Following is the code in didSelectRowAtIndexPath:
[self.tableView setContentOffset:CGPointZero];
[verbTableView setContentOffset:CGPointZero];
[seinhabenScrollView setContentOffset:CGPointZero];
[mdhPresensScroll setContentOffset:CGPointZero];
[mdhPreteritumScroll setContentOffset:CGPointZero];
[mhdScroll setContentOffset:CGPointZero];
....
There are more of those scrollview, and I want to put the all in one single object or something... I have tried following code:
for (UIScrollView *scrolls in topLayer.subviews)
{
[scrolls setContentOffset:CGPointZero];
}
Thanks!
The basic idea is right. It just depends upon how you identify the scroll views. You could do something like the following, which explicitly tests whether the subview is a kind of UIScrollView:
for (UIScrollView *scrollView in self.view.subviews)
{
if ([scrollView isKindOfClass:[UIScrollView class]])
scrollView.contentOffset = CGPointZero;
}
Or you can explicitly reference the specific scrollviews in question (in which case the class membership test isn't strictly needed):
for (UIScrollView *scrollView in #[seinhabenScrollView, mdhPresensScroll, mdhPreteritumScroll])
{
scrollView.contentOffset = CGPointZero;
}
Or, if you create an IBOutletCollection in IB, you can use that, too:
for (UIScrollView *scrollView in self.scrollViews)
{
[scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}
(Note, in that final example, I'm scrolling to the location in question with animation, providing the user some visual cue as to what just happened; that's completely up to you.)
In a comment above, you say that topView has subviews which, themselves, have subviews that are scrollviews, you'd have to do something like the following to handle this subview-of-subview situation:
for (UIView *subview in topLayer.subviews)
{
for (UIScrollView *scrollView in subview)
{
if ([scrollView isKindOfClass:[UIScrollView class]])
scrollView.contentOffset = CGPointZero;
}
}
Avoiding the dynamic type check, just place the views that can scroll into an array. Then, a little fancier, add an extension to scroll view so they can scroll to zero using no params, that let's us do the scrolling with an NSArray one-liner (makeObjectsPerform...)...
#interface UIScrollView (ScrollToZero)
- (void)scrollToZero; // a no-param method for scrolling to zero offset
#end
#implementation UIScrollView (ScrollToZero)
- (void)scrollToZero {
[self setContentOffset:CGPointZero animated:YES];
}
#end
NSArray *allMyScrolls = #[verbTableView, seinhabenScrollView, // and so on. put ONLY scrollViews in here
// you can make this array a property, initialized when the views are created
[allMyScrolls makeObjectsPerformSelector:#selector(scrollToZero)];

How can external UITableView delegate hide the UISearchBar keyboard?

I have a table view with a data source/delegate in another file. In addition, there is a search bar above the table view that belongs to the first file. In other to hide the keyboard when scrolling, I would need to call:
[self.searchBar resignFirstResponder]
But the
(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
method is in the delegate. So how would I hide the keyboard when scrolling in this case?
Thanks!
you could send a notification in scrollviewwillbegindragging. tableview delegate:
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
[[NSNotificationCenter defaultCenter] postNotificationName:#"resign" object:nil];
}
searchbar delegate:
-(void)viewDidLoad{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(goTo:) name:#"resign" object:nil];
}
-(void)goTo:(NSNotification*)notification {
[self.searchBar resignFirstResponder];
}
There are many ways to do,a couple of them are below.
option 1:
add below line after initializing your table object
[yourTableView setKeyboardDismissMode:UIScrollViewKeyboardDismissModeOnDrag];
or
option 2:
Get your tableview's superview(i'm expecting that as aViewcontrollerObj.view) and forcibly end its editing .
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
UIView *tableviewSuperView = yourTableView.superview;
[tableviewSuperView endEditing:true];
}
Hope that helps
Happy coding :)

UIScrollView scrollToTop not getting called for iPhone

I have a universal app, the code is the same. I have a UIScrollView in which has the scrollToTop working on the iPad but not on iPhone. I am pretty frustrated by this.
I know there's a similar thread posted here, but that is not the case. I used to have the scrolling to work before this both on the iPad and iPhone. Any idea what to look for?
The structure of the code is like this. I have a mainVC called A. I then have a VC called B. There is also another VC called C, which has a UIScrollView. I added C as B's child view controller. and then B as A's child VC. Now the scroll view on C did not have the scrollToTop working.
The delegate scrollViewShouldScrollToTop is also called only in the iPad, not in the iPhone.
Take a look at my answer to the question you've talked about. I've just added it a moment ago.
EDIT
I don't have the original code I've made, but it should be like that:
-(void)cleanUp:(UIScrollView*)view{
if([view isKindOfClass:[UIScrollView class]]){
view.scrollsToTop = NO;
}else{
for(UIScrollView* subview in view.subviews){
if([subview isKindOfClass:[UIView class]]){
[self cleanUp:subview];
}
}
}
}
and you can call it like this:
[self cleanUp:self.view];
You may also need even more tough variant of that routine (sometimes you may have a tableView inside a scrollView or something like that):
-(void)cleanUp:(UIScrollView*)view{
if([view isKindOfClass:[UIScrollView class]]){
view.scrollsToTop = NO;
}
for(UIScrollView* subview in view.subviews){
if([subview isKindOfClass:[UIView class]]){
[self cleanUp:subview];
}
}
}
I Just took the solution of #Ariel and done some improvements I want to share with you:
+ (void)globalDisableScrollToTop:(UIView *)_view;
{
// Check whether we got a scroll view
if ([_view isKindOfClass:[UIScrollView class]])
{
// Disable scroll to top
((UIScrollView *)_view).scrollsToTop = NO;
}
// Iterate all subviews
for (UIView *view in _view.subviews)
{
// Recursive call of this method
[self globalDisableScrollToTop:view];
}
}
Or without comments:
+ (void)globalDisableScrollToTop:(UIView *)_view;
{
if ([_view isKindOfClass:[UIScrollView class]])
((UIScrollView *)_view).scrollsToTop = NO;
for (UIView *view in _view.subviews)
[self globalDisableScrollToTop:view];
}
It now fixes all subviews and could be implemented as static method (of your root scroll view class).
If possible, Please paste the add subview code here. Looks like the problem is the view on which the scrollview is present is getting hide behind other view. Try changing the sequence of adding subview. Or you may also try bringSubviewtoFront property for setting the scrollview on top.
Let me know if it helps.

Enable all textfields in UITableViewCell when in Edit mode

I have a bunch of custom UITableViewCells with a label and textbox. I have the textbox disabled but I want to make it so when the user taps the Edit button it will make the textboxes editable. How can I do this so that ALL the UITextFields in the UITableView become enabled?
I have
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.navigationItem setHidesBackButton:editing animated:YES];
if (editing) {
}
}
but cannot add the textbox enable in there since I don't have access to all the textfields. Would I need to add code to grab all the cells and loop through them and enable the textfields?
I would do this by setting a isEditing BOOL on your UITableViewDelegate in the setEditing:animated: method and just updating visible cells when the value is changed.
NSArray *visibleCells = [myTable visibleCells];
for (MyTableViewCell *cell in visibleCells)
cell.textField.enabled = isEditing;
Then, using your UITableViewDelegate again, update new cells as they appear in tableView:willDisplayCell:forRowAtIndexPath:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.textField.enabled = isEditing;
}
Edit your subclass of UITableViewCell and register your instances for an editing notification in your subclass's viewDidLoad or init method:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(disableTextBox) name:#"EditingIsEnabled" object:nil];
And implement a method called disableTextBox that disables the text box for that cell.
Then in your setEditing:animated method, post the notification when you want to start editing:
[[NSNotificationCenter defaultCenter] postNotificationName:#"EditingIsEnabled" object:self];
Override the method dealloc in your UITableViewCell and remove yourself as an observer, or you'll crash:
[[NSNotificationCenter defaultCenter] removeObserver:self];
If you're not using ARC, make sure to call [super dealloc]. If you're using ARC, do not call super.
You can do the same thing when you want to disable all the cells, just post a notification with a different name like EditingIsDisabled.
Let me know if you need me to flesh out the code a bit more.
Edit: I like DBD's method better in this situation.

scrollToRowAtIndexPath not scrolling to inactive/unloaded cells

I've noticed that scrollToRowAtIndexPath:atScrollPosition:animated: doesn't scroll to cell that are not currently in view, so If I have 100 cells and I need to get to the one at 70, the call to that selector will do nothing.
Is there a way I can get that cell into memory? I already have the cell's index path...
I need to scroll to that position in my app when the user would want to go there.
Thanks for any thoughts!
EDIT: #dasblinkenlight
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillHide
{
//Load remote cell here then scroll
// :( dont know how to load remote cell yet
}
- (void)keyboardWillShow
{
//Load remote cell here then scroll
// :( dont know how to load remote cell yet
//_cellIndexPath gets assigned on didSelectRowAtIndexPath:
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_cellIndexPath.row inSection:_cellIndexPath.section] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
EDIT2:
- (void)keyboardWillShow
{
//Load remote cell here then scroll
[NSThread detachNewThreadSelector:#selector(keyboardWillShowThreaded) toTarget:self withObject:nil];
}
- (void)keyboardWillShowThreaded
{
[NSThread sleepForTimeInterval:2.0];
[self performSelectorOnMainThread:#selector(keyboardWillShowMainThread) withObject:nil waitUntilDone:YES];
}
- (void)keyboardWillShowMainThread
{
//Get the cell
//_textFieldThatHasFirstResponder is a subview in the cell
//This returns null, probably because the cell is not loaded into memory
UITableViewCell *cell = [_textFieldThatHasFirstResponder superview];
NSLog(#"CELL TO SCROLL TO: %#",cell);
NSIndexPath *indexPathForCell = [self.tableView indexPathForCell:cell];
[self.tableView scrollToRowAtIndexPath:indexPathForCell atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
OK, I've got the cause of this, see, you have:
NSIndexPath *indexPathForCell = [self.tableView indexPathForCell:cell]; // nil here
[self.tableView scrollToRowAtIndexPath:indexPathForCell atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
When you send indexPathForCell: for an out-of-view cell it returns nil, so tableView doesn't know where to scroll to.
you can implement a delegate so that you can call it from the class where you are in, so that is can update the position
"I've noticed that scrollToRowAtIndexPath:atScrollPosition:animated:
doesn't scroll to cell that are not currently in view, so If I have
100 cells and I need to get to the one at 70, the call to that
selector will do nothing. "
No. it is not true. I have just tried with a tableview with 100 rows. The following code works well.
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:78 inSection:0]
atScrollPosition:UITableViewScrollPositionNone animated:YES];
I don't think adding sleep is changing anything. It just delays execution but does not affect the order. Can you check if the index your are passing to scrollToRowAtIndexPath is valid? I remember seeing the same problem myself but it was related to invisible cell. It was impossible to retrieve invisible cell (tableView returned nil) and therefore its index path was nil and thus scrolling failed.
You could store locations of all cells or compute it on the fly and then pass it to
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated;
It's the only solution I can imagine.