I have a ios-chart as a subview that takes up half the screen. When I pan up on any other subview it scrolls. But not when I pan on the chart.
I tried setting:
[self.chart setDefaultTouchEventsEnabled:YES];
//and
[self.chart setScaleEnabled:NO];
It says in the documentation
defaultTouchEventsEnabled
enables/disables default touch events to be handled. When disable, touches are not passed to parent views so scrolling inside a UIScrollView won’t work.
What can I do to enable scrolling when panning/dragging on the chart?
I was struggling with this as well. Since I needed the chart to be scrollable, #Entrabiter's solution didn't work for me. The only solution that worked for me, was assigning the delegate of the chart view's UIPanGestureRecognizer to my ViewController and implement UIGestureRecognizerDelegate.
This solution is in Swift, but it should also work fine in Objective-C.
class MyViewController: UIViewController, UIGestureRecognizerDelegate {
// MARK: Outlets
#IBOutlet weak var contentView: UIScrollView!
#IBOutlet weak var myChart: LineChartView!
override func viewDidLoad() {
super.viewDidLoad()
if let gestureRecognizers = myChart.gestureRecognizers {
for gestureRecongnizer in gestureRecognizers {
if gestureRecongnizer is UIPanGestureRecognizer {
gestureRecongnizer.delegate = self
}
}
}
}
}
The important part is to tell the gestureRecognizer to recognize both the scrollview's panGestureRecognizer as well as the chartview's panGestureRecognizer.
// MARK: UIGestureRecognizerDelegate
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if otherGestureRecognizer == contentView.panGestureRecognizer {
return true
}
return false
}
Set userInteractionEnabled on the chart view to NO.
I think I figured it out...
I removed all the UIPanGestureRecognizers from the ios-charts subview.
This allowed for the scrollview to handle all the pan events.
for(UIGestureRecognizer *rec in self.chart.gestureRecognizers){
if([rec isKindOfClass:[UIPanGestureRecognizer class]]){
[self.chart removeGestureRecognizer:rec];
}
}
Related
In my tvOS app, I am trying to listen to changes in scrolling of my UICollectionView. After research, I found that the collection view natively receives a few gesture recognizers among them a UIPanGestureRecognizer with the selector handlePan:
<UIScrollViewPanGestureRecognizer: 0x101a4c1a0; state = Possible; delaysTouchesEnded = NO; view = <UICollectionView 0x1020c5d00>; target= <(action=handlePan:, target=<UICollectionView 0x1020c5d00>)>>
in the log, or in code:
myCollectionView.panGestureRecognizer
I was wondering if there's a way to add my controller as the target of the gesture recognizer, or maybe override the handlePan method.
I tried implementing the UIGestureRecognizerDelegate but it does not give me an access to the handlePan method.
Maybe I should just add a custom UIPanGestureRecognizer of my own on the collection view?
UICollectionView is a subclass of UIScrollView so you can detect scroll changes on collectionview by adding scrollview delegates.
Objective-C
// called on finger up if the user dragged. decelerate is true if it will continue moving afterwards
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
}
// called when scroll view grinds to a halt
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
}
Swift
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
}
Hello I am trying to override the UIscrollview methode so I can prevent auto scrolling on my scroll view. However I keep getting an error. This is the way i have it in my code. Im not sure exactly what im doing wrong
class FirstViewController: UIViewController {
//scrollview outlet
#IBOutlet var ScrollerScreen: UIScrollView!
}
class MyScrollView: UIScrollView {
-(void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated{}
}
You could implement the UIGestureRecognizerDelegate method
gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch)
and return false when you don't want your scroll view to scroll.
I have two views; a UIView placed on top of a UITableView. I need to know when the UIView has been panned, so I’ve placed a UIPanGestureRecognizer on it. However, this creates a UI which seems buggy because you expect the UITableView behind it to move as your finger does.
So it seems I need to somehow pair up this pan gesture with making the table view behind it move, at least, until this covering view disappears.
How do I pair up a pan gesture to move a UIScrollView?
Note: If you’re wondering about the cover view, it’s actually a UIImageView which has a snapshot of the table view with a filter applied to it for UI reasons.
When this view is panned, it disappears. So from the user’s point of view, while they begin dragging the cover view, I want them to keep thinking they are dragging the table view as the cover disappears.
Assuming you have a view controller with a table view setup like the following:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate
{
#IBOutlet var tableView: UITableView!
#IBOutlet var scrollView: UIScrollView!
You can add a couple of gesture recognizers:
var gestureRecognizer1: UIPanGestureRecognizer = UIPanGestureRecognizer()
var gestureRecognizer2: UIPanGestureRecognizer = UIPanGestureRecognizer()
Setup your delegates and add the gesture recognizers to the scroll views:
override func viewDidLoad()
{
super.viewDidLoad()
scrollView.contentSize = CGSizeMake( ) // <-- Set your content size.
scrollView.delegate = self
tableView.delegate = self
gestureRecognizer1.delegate = self
gestureRecognizer2.delegate = self
tableView.addGestureRecognizer(gestureRecognizer1)
scrollView.addGestureRecognizer(gestureRecognizer2)
}
Implement a delegate method for UIGestureRecognizerDelegate to recognize simultaneous gestures:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool
{
return true
}
Implement a delegate method for UIScrollViewDelegate:
func scrollViewDidScroll(scrollView: UIScrollView)
{
tableView.contentOffset = scrollView.contentOffset
}
}
The movement of the tableView will be synchronized to the scroll view.
In the end I’ve decided to directly change the cell’s images with a CIFilter rather than take a snapshot. This way is the way I should have done it anyway, it’s much cleaner and uses no possibly-buggy “workarounds”.
How can I add a Pan Gesture Recognizer to an UITableView, without blocking my scrolling feature of my TableView?
This is my code:
#IBOutlet var ScanPanGestureRecognizer: UIPanGestureRecognizer!
#IBAction func ScanPanGestureRecognizer(sender: UIPanGestureRecognizer)
{
print("TEST")
}
override func viewDidLoad()
{
ScanTableView.addGestureRecognizer(ScanPanGestureRecognizer)
}
So the code works and I get a lot of prints with "Test" but I'm not able to move (scroll) my TableView any more. I have read some other questions / answers but I couldn't find my issue. I thought that the extension "addGestureRecognizer" only add a gesture and not overwrite the TableView pan gesture... Thanks!
I think whatever you want to do with a pan gesture recognizer on a UITableView you can do it in UITableView's delegate method scrollViewDidScroll: in that method the scrollView.contentOffset will tell you how much the tableView has scrolled
Is there a way to determine the panning location of a UIPageViewController while sliding left/right? I have been trying to accomplish this but its not working. I have a UIPageViewController added as a subview and i can slide it horizontally left/right to switch between pages however i need to determine the x,y coordinates of where I am panning on the screen.
I figured out how to do this. Basically a UIPageViewController uses UIScrollViews as its subviews. I created a loop and set all the subviews that are UIScrollViews and assigned their delegates to my ViewController.
/**
* Set the UIScrollViews that are part of the UIPageViewController to delegate to this class,
* that way we can know when the user is panning left/right
*/
-(void)initializeScrollViewDelegates
{
UIScrollView *pageScrollView;
for (UIView* view in self.pageViewController.view.subviews){
if([view isKindOfClass:[UIScrollView class]])
{
pageScrollView = (UIScrollView *)view;
pageScrollView.delegate = self;
}
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NSLog(#"Im scrolling, yay!");
}
My personal preference is not to rely too much on the internal structure of the PageViewController because it can be changed later which will break your code, unbeknownst to you.
My solution is to use a pan gesture recogniser. Inside viewDidLoad, add the following:
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handler))
gestureRecognizer.delegate = yourDelegate
view.addGestureRecognizer(gestureRecognizer)
Inside your yourDelegate's definition, you should implement the following method to allow your gesture recogniser to process the touches
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Now, you should be able to access the X/Y location of the user's touches:
func handler(_ sender: UIPanGestureRecognizer) {
let totalTranslation = sender.translation(in: view)
//...
}