I have a UITableView which is a subview of a UIView, then that UIView is a subview of a UIScrollView. How do I detect the touches that should scroll the UITableView?
The UITableView can get item selection events (a cell in the table is selected/tapped) just fine, except that you have to hold down on the cell before it fires. But I can't get the UITableView to scroll, its always the UIScrollView that reacts to the pan gesture.
Any help is greatly appreciated. Thanks in advance!
EDIT:
Solved, though I asked the wrong question. It does work by default as Roman K pointed out. I think the problem was related to having a part of the UITableView outside the bounds of the UIScrollView (the UITableView went over the bottom bounds of the UIScrollView). Setting it to correctly fit inside the UIScrollView fixed it.
Please, make sure that UIScrollView's properties delaysContentTouches and canCancelContentTouches are set appropriately. They control how UIScrollView instance passes touch information to its subviews. By default delaysContentTouches is set to YES. Also, make sure that, if you extended UIScrollView, touchesShouldBegin:withEvent:inContentView: allow touches in the subview.
Otherwise, UITableView scrolling should work by default in your scenario. If you create a test project with just the view hierarchy as described you will see that it is the case. So, compare the two and see what difference affects the scrolling.
Related
I've been struggling with this issue for days, so I hope someone can help me out...
I have a grouped UITableView with several cells. I want to draw some custom graphics above the UITableView that would scroll with the content of the table. Specifically, I want to draw a line with dots, joining the UITableViewCells (across the sections) like this:
Of course if we have more cells than what the screen is capable of displaying, the upper layer with the custom drawing should move with the underlaying cells.
I've tried to subclass UITableView and override it's -drawRect method, but it didn't work. Even if I wouldn't call [super drawRect:rect], the table content displayed without problem.
I've tried to add a new subview to the UITableView, but it changes it's size dynamically when it gets the cells and sections from its datasource... I'm out of ideas...
Although the Web is full of custom UITableViewCell samples, I haven't managed to find anything similiar to my concept...
Can anyone help me how to achieve the above mentioned feature?
First your should subclass UITableView. Then create another UIView and add it as a subView of your custom UITableVIew.
Next override the contentOffset property of the UITableView.
-(void)setContentOffset:(CGPoint)contentOffset
{
[super setContentOffset:contentOffset];
// Custom code here. Update custom subview here.
}
This method will be called as the UITableView is scrolled. You can then adjust the offset of your subview and update its drawing.
In my iOS app have a UITableView which contains a custom subview in one of it's cells. This cell is an interactive view that handles touch events (touchesBegan, touchesEnded, touchesMoved) to update itself.
The problem is that when the user 'drags' up or down, the tableView catches these touches (although I don't pass the touches up the responder chain), scrolls the table and prevents the subview from working correctly. I would like to prevent the table from scrolling as long as the user is touching that particular subview.
The subview has no reference at all to the tableView.
How can I prevent the scrolling behavior of the table?
Update
Despite accepting the answer below, I ended up handling my situation differently. I handle the touch events in my custom view now, pass them up the responder chain (to the table cell), the cell handles the touch events as well, using them to enable/disable scrolling on the superview (the table).
Turning off "Cancellable Content Touches" in the UITableView solved this for me (in the UITableView attributes inspector under Scroll View / Touch). I got this from this SO question: Scrolling a UITableView inside a UIScrollView
From the UIScrollView:canCancelContentTouches doc:
If the value of this property is NO, the scroll view does not scroll
regardless of finger movement once the content view starts tracking.
The most common method I use in such cases is to delegate information up the event chain. Set delegates in manner:
subview->cell->table
The second thing you can do is to send a notification via Notificaion Center. Table would listen to any events that forbid normal scrolling. It is overshoot but it will leave your code consistent.
I have no more ideas at the moment.
I have a view controller that is basically a form with multiple UITextFields and UITextView, embedded in a UIScrollView. When an UITextField becomes first responder, the scroll view automatically move to the focused field, which is believe is the behaviour explained in the first answer in this topic :
Disable UIScrollView scrolling when UITextField becomes first responder
This does not happen when the first responder is an UITextView though, and I'm not sure why and how I should fix it.
The second problem is that when the keyboard is shown, the scroll view does not scroll if the UITextView is not in view (because it's hidden by the newly shown keyboard). I implemented the code of Apple's documentation on how to manage the keyboard :
http://developer.apple.com/library/ios/#DOCUMENTATION/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
And added another activeField variable named activeView for textViews (initialized in the beginEditing of TextView, set to nil in endEditing, and scrollToVisible according to it's frame when the keyboard is shown). The problem here is that the beginEditing in UITextView is called after the keyboardWasShown, so the activeView is not initialized and thus does not scroll. For some reason, for UITextFields the beginEditing is called before, which is the intended behaviour.
How can I scroll to an UITextView and it's the first responder, and how can I move to it when the keyboard is shown and hide it?
To scroll to show anything in a UIScrollView do
scrollRectToVisible:/*frame of object you want to show*/ animated:YES
Subscribe to UITextViewTextDidBeginEditingNotification and call the above method when you get it.
Imagine, there is a UIViewController with a UIScrollView in it. At the top of the view there is an UIImageView, some UILabels and other things. Furthermore, there is a UITableView which content is Dynamic Prototypes. I attach a picture to make it clear:
I haven't got a static amount of cells in the UITableView so it could be scrollable. My problem is the following: the UITableView scrolls in itself but I want to scroll the whole View. What is the best possibility to do that?
Possible solutions I've founded today
1) The first thing is: I create a UITableViewController and declare a header section in which I include all my labels, images etc. programmatically (I would love to use the interface builder for that...)
2) Another solution is to calculate the height of the view. I tried the best to do it like this way - but: without success. If this is the best way to do that: Can anybody give an example?
I would ditch the UIScrollView and just use a UITableView. You can add a UIView object as the tableHeaderView of the UITableView just by dragging it in in Interface Builder. Now since everything is part of the UITableView hierarchy, everything will scroll together as expected.
You could also try setting delaysContentTouches to NO on your scrollView. Depending on your setup, this may make the scroll view respond to the touch first instead of the table view.
From Apples UIScrollView Docs:
delaysContentTouches
A Boolean value that determines whether the scroll view delays the
handling of touch-down gestures.
#property(nonatomic) BOOL delaysContentTouches
Discussion
If the value of this property is YES, the scroll view delays handling
the touch-down gesture until it can determine if scrolling is the
intent. If the value is NO , the scroll view immediately calls
touchesShouldBegin:withEvent:inContentView:. The default
value is YES.
You'll have to (as you've mentioned) add the UIView containing the image and buttons to the actual UITableView. Embedding it in the scroll view will produce the undesired behavior that you're seeing.
I would recommend returning the UIView as the header view for the first section of your table view. You can do this by implementing the UITableViewDelegate method:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
If you maintain an IBOutlet to the view containing your image/labels, you can return it here.
this is same demo i hope its helps you from iphone sorce code library
http://developer.apple.com/library/ios/#samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html
thank you
I wonder if anyone else is facing the same issue. I have a UITextView field placed in a UITableViewCell. Sometimes it does not displays the text. When i click or scroll the table view, it appears. Any guesses?
Details:
I call a method in viewDidLoad method that calls a web service to retrieve some data. On receiving the data, i set the values of UILabel and UITextView. UILabel values appear fine, but the UITextView (sometimes) do not show the value until i move to subview or scroll up and down to revisit the area contaning UITextView. I'm showing UILabel and UITextView objects in UITableViewCell. I call [tableView reloadData] right after setting values in UILabel and UITextView, but i do not re-create the UITableViewCell.
Thanks for your reply and pointers.
I solved this by calling [myTableView reloadData];
I had this same problem more or less - a UITextView inside a custom UITableViewCell subclass would not display its text until you touched (and thus scrolled) the UITextView. This would only happen with the FIRST cell in the table. I couldn't figure out why it was happening, but the problem was easily fixed by just "nudging" the UITextView's contentOffset programmatically.
problemCell.textView.contentOffset = CGPointMake(0.0, 1.0);
problemCell.textView.contentOffset = CGPointMake(0.0, 0.0);
This might have something to do with the fact that UITextView and UITableView are both subclasses of UIScrollView. So you have a scroll view inside of a scroll view, and it wouldn't surprise me if that was the cause of your problems.
If you don't need to edit the text within the table, just use a multi-line UILabel.
If you absolutely have to have a UITextView inside a UITableView, perhaps disabling scrolling on one of them might also fix the problem. (I think the property name is scrollEnabled or scrollingEnabled.)
Make sure that you're calling [super viewWillAppear:] and [super viewDidAppear:] in all the places where you override viewWillAppear or viewDidAppear.
Probably true of all the other viewDidWhatever and viewWillWhatever methods as well.
The problem you're having suggests that the UITextView isn't getting the message to draw itself on the screen when you're first displaying the table but does get the message when it needs to refresh.