So I have looked over a bunch of other questions that could possible be duplicates. But none of the solutions that have been mentioned seem to work. Also, the answers tend to be scattered and incomplete.
So, I have a UIView inside of a subclassed UIScrollView. All I need to do is have the UIScrollview ignore all forms of gesture that can occur with 3 fingers and, instead, pass it on to the UIView inside. Could someone help me with this.
You need to subclass the scrollview to accomplish this. I tested this technique with a UITableView just now and it worked.
#interface OneTwoTouchScrollView : UIScrollView
#end
#implementation OneTwoTouchScrollView
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)recognizer
{
return recognizer.numberOfTouches < 3 && [super gestureRecognizerShouldBegin:recognizer];
}
#end
Related
I have an iPad interface where different views can be moved left-right with one finger (as for e.g. like the Twitter iPad interface).
I have a problem with this, as I have a slider on one view and when I start sliding, the UIGestureRecogniser on the main (underlying) view also start acting on the movement.
Is there a way to prevent this? That only the UISlider takes the touch action, and that the underlying view does not act? I mean to remember there is a variable for this with UIGestureRecognisers, but cannot find it for views/sliders.
Thanks in advance!
Set the exclusive touch property:
[view setExclusiveTouch:YES];
I searched for hours and I following trick work for me.
ViewController.h
#property (weak, nonatomic) IBOutlet UIScrollView *yourScrollView;
ViewController.m
- (void)viewDidLoad
{
yourScrollView.delaysContentTouches = NO;
}
Is there an easy way for listening for when a child or subview has been added to a UIView?
I've gone through the addobserver options and haven't found an obvious option anyway. There may be another option that would be affected though when content is added to a view or am I wrong in saying that? i.e. content width or height, positions, etc.?
Edit
This is accomplished easily using the advice of #Alkimake below (TextHolderClass).
I created a custom UIView subclass and set the UIView's class in Interface Builder to be equal to TextHolderClass
Thanks for your help, I know it should have been obvious :)
UIView methods may help you:
- (void)willMoveToSuperview:(UIView *)newSuperview
UIView has 2 methods to call after subview interactions. Simply create your custom UIView class and implement these methods which is pretty for you. And use your own CustomView
- (void)didAddSubview:(UIView *)subview;
- (void)willRemoveSubview:(UIView *)subview;
So I just have a standard UIViewController with a UIWebView in it that displays a pdf. For the app functionality, I have need to be able to respond to the UIWebView's nested UIScrollView events like scrollViewWillBeginDragging, scrollViewDidScroll, etc.
The only way I can get access to the scrollView is to (it seems like a hack) go in and get it by the subviews array:
for (id subview in webView.subviews){
if ([[subview class] isSubclassOfClass: [UIScrollView class]]) {
UIScrollView * s = (UIScrollView*)subview;
s.delegate = self;
s.tag = 1;
scrollView = s;
}
}
But that seems to introduce more problems than it's worth, because I lose native UIScrollView stuff like zooming.
So to sum up what I'm needing:
What is the best way to set my UIViewController class as the delegate of the UIScrollView inside of the UIWebView? Is there something I need to do with subclassing my own UIWebView so that it handles events from it's built in UIWebView a certain way and then pass it along somehow to the UIViewController? How does that passing thing work anyway?
Please advise!
Thank you!
Have you checked there is only one UIScrollView subclass in the subviews? Bung in a log in your loop to see. If there is more than one, then you'll only pick up the last one using your code.
If there is just one UIScrollView subclass, you could try saving a reference to its delegate and then in your own delegate methods passing messages on after you have done your business.
So, in your loop, something like
originalDelegate = s.delegate
And then for the delegate methods, something like:
- (void) scrollViewDidScroll: (UIScrollView*) scrollView;
{
// do your stuff
[originalDelegate scrollViewDidScroll: scrollView];
}
You might need to check whether originalDelegate responds to the selector before calling it, i.e. if ([originalDelegate respondsToSelector: #selector(scrollViewDidScroll:)) etc. If it were me, I'd start by implementing all twelve delegate methods defined in the UIScrollView delegate protocol.
Not tested this, so will be interested to know if it can be made to work. Do note, the docs explicitly say that UIWebView "should not be subclassed"
So I wanted to make my UIWebview respon to touch events. I have read several topics about this. I created a Subclass of UIWebView, added it so my UIViewController and linked it via IB.
In my Subclass, i overrode touches ended and called [super touchedEnded]. didnt help.
I overrode hittest, but it doesnt call super either!
If I add this code to my subclassed UIWebView:
#implementation UIWebView (CustomView)
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(#"hit");
return self;
}
#end
then the touches ar forwarded to the superclass, but hittest is not(!)and additionally the webview stops scrolling.
Well, I want so recognize a touch in my webview and pass it to super - what am I doing wrong?
EDIT:
I'm wondering, why so many suggestions include using 'hittest' - this results in being unable to scroll your webview.....any ideas?
Answering my own question here - this is the version that did what I wanted: The right way. This is about subclassing UIWindow and passing on the events caught.
I would still love some explanations to my previous questions tho :P
Tell me if I am wrong with that:
I made an new class ScrollViewDataSource. That class conforms to an protocol I created within my delegate for the scroll view. Well, it's a very special delegate that does some very complex stuff upon scrolling. So this delegate receives that data source object upon initialization. The datasource object now has a method
(NSArray*)subviewsFromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex;
so when the user scrolls, the delegate rings the datasource object lots of times dunring scrolling to ask for data. I'm going to recycle views during scrolling. That means, if the user scrolls down, I remove the views from the top to the bottom, and fill them up with new data.
The NSArray contains UIView objects, which will be positioned appropriately during scrolling. Also, on first launch of the view that contains the scroll view, the data source will deliver the data to display the first visible contents.
Is that a good pattern, or do you have better ideas for that?
BTW: I know a UITableView does something similar. But I want to learn that. It's a practise for me. Thanks!
May,
This is the best pattern that you can make use of. Exclusively followed by Apple in various of their data displaying views like UITableView in iPhone and NSTableView,NSOutlineView in Mac.
All the best.
If your content views are using same layout, I would make ScrollViewDataSource containing only the data that content views needed, so I don't need to alloc/create new UIView for my UIScrollView when asking new data (since MyScrollView hold the content views that I can reuse):
#interface MyScrollView : UIView {
#private
id <MyScrollViewDelegate> _delegate;
id <MyScrollViewDataSource> _dataSource;
UIScrollView *_scrollView;
NSMutableArray *_contentViews; // you need to create/maintain/reuse contentView from here
}
#property (nonatomic, assign) id <MyScrollViewDelegate> delegate;
#property (nonatomic, assign) id <MyScrollViewDataSource> dataSource;
#end
#protocol MyScrollViewDataSource <NSObject>
#optional
- (NSString *)myScrollView:(MyScrollView *)myScrollView requestTitleForContentViewAtIndex:(NSInteger)index;
- (UIImage *)myScrollView:(MyScrollView *)myScrollView requestLogoForContentViewAtIndex:(NSInteger)index;
#end
...
The good about this is, your MyScrollView interface would look clean to superview, and you are dealing all the scrolling, layout, redraw and content updating stuffs within your MyScrollView AND without bothering other views or controllers from outside.
But, if your content views are totally different to each others, I won't use pattern like this.