I have a UITableView with custom cells. It scrolls every time if I swipe fast, but when I swipe more slowly, sometimes it won't scroll.
Setup:
UITableview controller with a standard table view. I load some images in the cells asynchronously. The cells subclassed, but the only methods I override are awakeFromNib and layoutSubviews.
I'm setting these methods:
self.scrollView.delaysContentTouches = true
self.scrollView.canCancelContentTouches = true
Symptoms
It's almost as if the cell doesn't return the touch event to the scrollView. For example, in the Mail app, you can hold down on a cell, but if you keep scrolling, it will break the touch and allow you to scroll.
I'm being as specific as I can without dumping a bunch of code, let me know if there's any other relevant info I should add.
Things to try:
Do you have any other gesture recognizers in the view?
If it's not necessary to have user interaction with the cells, you can disable selection in the UITableView
Is this issue only present on hardware or also in the simulator? Depending on your hardware (i.e. older iPod Touches) some ios mobile devices have less responsive displays
Depending on the content of your cells, you may be scrolling inside a textView or something similar. Maybe try disabling scrolling inside those controls?
Related
So I recently implemented a collection view in my app, and I got a bug that I can't seem to solve, searched it and saw no threads about it.
If I have my cursor/finger over the cells i can't scroll through my collection view i need select a "empty" area to scroll.
Second strange Behavior I came across is that I can't directly touch a cell. I need some sort of swipe gesture over it to trigger the code when a cell is selected.
If I go to my collection view on my storyboard and select Delays Content Touches and Cancellable Content Touches in the scrollview section, the collection view scrolls just fine but if I put my finger/cursor over a cell with these option enabled I can't access any cells anymore.
This completely confuses me.
and thank you for reading/considering this thread.
Let's see what your two properties do.
delaysContentTouches: If the value of this property is true, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent. If the value is false , the scroll view immediately calls touchesShouldBegin(_:with:in:). The default value is true.
canCancelContentTouches: If the value of this property is true and a view in the content has begun tracking a finger touching it, and if the user drags the finger enough to initiate a scroll, the view receives a touchesCancelled(_:with:) message and the scroll view handles the touch as a scroll. If the value of this property is false, the scroll view does not scroll regardless of finger movement once the content view starts tracking.
First, you set delaysContentTouches to false. So the scrollview immediately calls the content view's touch handling methods, allowing it to handle the touch. Obviously, the scroll view won't start scrolling right away because of this, even if you drag.
Second, you also set canCancelContentTouches to false. But if the scroll view isn't allowed to "take over" touches that the content already handles (by cancelling them), it is never able to start scrolling later on either. So if your touch hits a content view, there is no possible way for the scroll view to start scrolling: it isn't allowed to scroll right away because it isn't allowed to delay the content touches, and it can't start scrolling later because it can't cancel the content touches.
I don't know what happens within your cells, not sure what code you put in there. However, you should probably allow your tableview to both delay touches (that means that your cell won't handle swipes that are cancelled immediately anyway because they were intended to be scroll gestures), and to cancel content touches (that means that when you touch down and don't release, you can still start a scroll gesture after a cell became highlighted).
i had the same problem when touching a cell, the problem was that I'm using more than one UIGesture without adding ".cancelsTouchesInView = false" for each one
so if you're using a UIGesture just add Your_Gesture.cancelsTouchesInView = false
and you should be able to access your cells
When tableView is scrolling with high speed, and user tries to stop it by touch, tableView keeps scrolling. And user can stop scrolling tableView only after two or three touches. If speed of tableView scrolling is low, tableView respond touches well.
The tableView displays cells with a lot of subviews, and I localized problem on one view.
If I set problemView.userInteractionEnabled = NO, scrolling works well. To set userInteractionEnabled = NO for all subviews of problemView but not for problemView, do not help.
Here image of diplaying cell, the problemView is view with red frame.
Could somebody to give an advice, how to solve the problem?
There are several possibilities:
Your custom view, or one of its superviews, has userInteractionEnabled set to NO.
There is another view on top of your custom view, or on top of the table view within the custom view.
The custom view that the table view is inside is smaller than the table view (with clipsToBounds=NO, a subview that extends beyond the bounds of its parent can be seen but not normally interacted with). Or the same for another view in the stack.
The custom view (or one of its superviews) overrides pointInside:withEvent: or hitTest:withEvent: incorrectly.
It might be that it thinks you are editing it in some way. Try allowsSelectionDuringEditing = YES. Here is more information with using the UITableView.
If you are using NSTimer inside the UITableViewCell then I have experienced anomalous actions as you have discussed. In such case you need to replace implicitly scheduled timer with explicitly scheduled timer.
For me the problem was that having userInteractionEnabled = true with a click handler on subviews in the cell broke the scrolling. Not sure why this is the case though. I solved this in my case by using didSelectRowAt on the tableview instead of having custom click handlers on the subviews. Then both the scrolling and the click handling worked as I wanted to.
I'm creating my views programmatically. I have a UITableView in my UIViewController subclass that I want to add a scrolling subview to that is not a cell. I want to add some text-based subview to the UITableView that scrolls with the table and starts out above y=0 so the user will only see it if he pushes the table down. That is, it should reside above the first section of my table. If it helps for visualization, I intend to make something similar to those "scroll down to refresh" features and want some indication to the user that scrolling down causes a refresh. Is there any way to do this without something messy like using another UITableViewCell to represent it or abusing the UITableView delegate methods to move a view around whenever the user scrolls?
Simply using [tableView addSubview:] in my viewWillLoad only makes it appear for a split-second then disappear once the table data is loaded. This seems weird to me because UITableView is a subclass of UIScrollView, which is meant to hold other views in it. Using [tableView.backgroundView addSubview] does nothing.
P.S. Why not use a UIRefreshControl for this? I'm still undecided but leaning towards not using one because I don't like how slow that spinning wheel "feels" when the refreshes are usually very very quick. I've been looking at other options like flashing the background subtly and only showing a wheel if it's taking a longer time than usual.
I You can implement pull to refresh with only a table view
To do this using the scroll view delegate, since tableview is a subclass of scroll view.
Set view controller to be the tableview delegate and implement
(void)scrollViewDidScroll:(UIScrollView *)scrollView
When scrollview content offset y value passed a point, add a label to the viewcontroller.view not tableview. When you scroll back or release, remove the view.
You might also be able to add label to the table view and set the frame origin to negative y value, so when you pull the label will move into view (Never tested this do might not work)
I've created a simple grid based UICollectionView but I'm having trouble with the scrolling. If I touch the view itself rather than a cell within it then it seems to scroll correctly but if I touch one of the cells and try to scroll then nothing happens. This is a bit of an issue, as I basically want the grid of cells to completely fill the view, and when the view is filled like that there is nowhere to touch that will actually make it scroll! I guess the easiest way to describe what I'm trying to achieve is a table view but with two columns of cells rather than one.
I can't seem to find anything in the documentation that talks about this issue and I've tried various combinations of "user interaction enabled" settings etc.
One final thing, I do require the cells to respond to a single tap touch (basically to toggle them on and off) so I don't want to completely disable them responding to touches.
I have a UICollectionView added to a UIView in an app I am working on. Displayed in the UICollectionView I have a set of images pulled from Core Data. The vertical scrolling works fine but the scrollbar does not display until the user touches the UICollectionView.
How can I make sure the scrollbar at the right is always visible so that an indication is given to the user that it is scrollable?
You can't make them always visible. Instead, you can flash them once, when the user is first presented with the collection view to notify them, that this view can be scrolled.
Since UICollectionView is a subclass of UIScrollView you can do this:
[myCollectionView flashScrollIndicators];
Check out the Settings app for instance. When you go to a settings list that is longer then the screen, the scroll indicator is flashed once.
FYI for Swift:
myCollectionView.flashScrollIndicators()