Objective C: UILongPressGesture on ScrollView - objective-c

I am trying this code on UIScrollView but it's not working. The NSLog is not appearing on my console. What's wrong? its working fine when its not on UIScrollView.
- (void)viewDidLoad
{
[super viewDidLoad];
[self papers];
UIGestureRecognizer *recognizer = [[ UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
longPressGR = (UILongPressGestureRecognizer *)recognizer;
longPressGR.minimumPressDuration = 0.5;
[Image1 addGestureRecognizer:longPressGR];
}
-(void) handleLongPress:(UILongPressGestureRecognizer *)recognizer {
NSLog(#"Long Press");
}

You didn't say what Image1 is. I'm guessing a UIImageView, in which case you need to make sure you do:
[Image1 setUserInteractionEnabled:YES];
(Unlike most views, UIImageView has interaction disabled by default.)
(As an aside, it's conventional in Objective-C to have your ivars and methods begin with lower-case letters; classes begin with upper-case.)

Related

IBAction is not working with UITapGestureRecognizer

I am working on an application where i need to zoom a UIView on click of UITapGestureRecognizer and want to perform a IBAction while zooming and after zooming. Is this possible?. Please give me a small example of it.
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleDoubleTap:)];
tapGestureRecognizer.numberOfTapsRequired = 2;
[self.scrollContainer addGestureRecognizer:tapGestureRecognizer];
}
- (void)handleDoubleTap:(UIGestureRecognizer *)recognizer
{
if(isAlreadyZoomed)
{
CGPoint Pointview = [recognizer locationInView:recognizer.view];
CGFloat newZoomscal = 3.0;
CGSize scrollViewSize = self.scrollContainer.bounds.size;
CGFloat width = scrollViewSize.width/newZoomscal;
CGFloat height = scrollViewSize.height /newZoomscal;
CGFloat xPos = Pointview.x-(width/2.0);
CGFloat yPos = Pointview.y-(height/2.0);
CGRect rectTozoom = CGRectMake(xPos, yPos, width, height);
[self.scrollContainer zoomToRect:rectTozoom animated:YES];
[self.scrollContainer setZoomScale:3.0 animated:YES];
isAlreadyZoomed = NO;
}
else
{
[self.scrollContainer setZoomScale:1.0 animated:YES];
isAlreadyZoomed = YES;
}
}
IBAction are just regular methods that returns void and take 0 or 1 argument only.
You can call them in code as you would call any other king of methods.
UITapGestureRecognizer are design to call an IBAction method while triggered. You can set that from InterfaceBuilder or in code
for example the following code
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleTap:)];
tap.numberOfTapsRequired = 2;
[imageView addGestureRecognizer:[tap cop]];
will called this methods when the user doubleTap the imageView
- (void) handleTap:(UITapGestureRecognizer *)sender;
in this methods, you can pretty much do whatever you need:
managing your subviews,
calling other methods etc...
However, if you plan an zooming in and out, I would strongly recommand the usage of the UIScrollView class instead of the UIView class.
Cheers
hi i hope below would give u a idea.....
UITapGestureRecognizer *tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(scrollViewDoubleTapped:)];
tap2.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:tap2];
- (void) scrollViewDoubleTapped:(UITapGestureRecognizer *)sender
{
scrollZoomAdjust.zoomScale=2.0f;// set your required Zoom scale
// scrollZoomAdjust is the scroll view that contain the image within it
}
the above code was not tested

Does it make sense to add ATMHud to tabBarController.view

When i try to add ATMHud to uitableviewcontroller subview it does work but it doesn't disable the scrolling and if the tableview is not on top i can't see the hud view. What i did was added to teh tabBarController.view that works but i want find out if this is a good idea or later on i might have issues with it.
Another question is tabBarController.view frame is that the whole screen or just the bottom part. How come atmhud shows in the middle of the screen?
Thanks in advance!
Yan
============
Found a blog post that shows how to reset self.view and add tableview separately in uitableviewcontroller
UITableViewController and fixed sub views
- (void)viewDidLoad {
[super viewDidLoad];
if (!tableView &&
[self.view isKindOfClass:[UITableView class]]) {
tableView = (UITableView *)self.view;
}
self.view = [[[UIView alloc] initWithFrame:
[UIScreen mainScreen].applicationFrame] autorelease];
self.tableView.frame = self.view.bounds;
self.tableView.contentInset = UIEdgeInsetsMake(44.0, 0.0, 0.0, 0.0);
[self.view addSubview:self.tableView];
UIView *fixedBar = [[UIView alloc] initWithFrame:
CGRectMake(0.0, 0.0, self.view.bounds.size.width, 44.0)];
fixedBar.backgroundColor = [UIColor colorWithRed:
0.0 green:1.0 blue:0.0 alpha:0.7];
[self.view addSubview:fixedBar];
[fixedBar release];
}
After this when add hud to self.view you will be able to disable the tableview on the bottom.
Let me know if this a good way to setup the tableview
The problem with using the tab bar is that the hud is now modal, and the user cannot change the tab.
It sounds like the tableview is not your primary viewm, as it can get "covered up". If its not the primary view, then add the ATMHud to self.view. If the tableView is the same as self.view, then add a new transparent view to it, then add the HUD to that view.
The tabBarController.view is the view that hosts the tabbed views - if you want to see its size (or frame) log it using NSStringFromCGRect(self.tabBarController.frame);
EDIT: I just did a test, the ATMHud DOES block the UI. All I can think of is that you have not inserted it where you need to (at the top of current view's subviews.) I have a demo project where I do this:
hud = [[ATMHud alloc] initWithDelegate:self];
[self.view addSubview:hud.view];
[hud setCaption:#"Howdie"];
[hud setActivity:YES];
[hud show];
[hud hideAfter:5];
A button under the hud is not active - in fact nothing in the view is active (probably the Nav Bar would be live though)
If you want an ARCified and field tested version, you can grab it here
EDIT2: The solution to your problem is below. Note that ATMHud blocks clicks from getting to the table, and the code below stops the scrolling:
- (void)hudWillAppear:(ATMHud *)_hud
{
self.tableView.scrollEnabled = NO;
}
- (void)hudDidDisappear:(ATMHud *)_hud
{
self.tableView.scrollEnabled = YES;
}
Dump the views:
#import <QuartzCore/QuartzCore.h>
#import "UIView+Utilities.h"
#interface UIView (Utilities_Private)
+ (void)appendView:(UIView *)v toStr:(NSMutableString *)str;
#end
#implementation UIView (Utilities_Private)
+ (void)appendView:(UIView *)a toStr:(NSMutableString *)str
{
[str appendFormat:#" %#: frame=%# bounds=%# layerFrame=%# tag=%d userInteraction=%d alpha=%f hidden=%d\n",
NSStringFromClass([a class]),
NSStringFromCGRect(a.frame),
NSStringFromCGRect(a.bounds),
NSStringFromCGRect(a.layer.frame),
a.tag,
a.userInteractionEnabled,
a.alpha,
a.isHidden
];
}
#end
#implementation UIView (Utilities)
+ (void)dumpSuperviews:(UIView *)v msg:(NSString *)msg
{
NSMutableString *str = [NSMutableString stringWithCapacity:256];
while(v) {
[self appendView:v toStr:str];
v = v.superview;
}
[str appendString:#"\n"];
NSLog(#"%#:\n%#", msg, str);
}
+ (void)dumpSubviews:(UIView *)v msg:(NSString *)msg
{
NSMutableString *str = [NSMutableString stringWithCapacity:256];
if(v) [self appendView:v toStr:str];
for(UIView *a in v.subviews) {
[self appendView:a toStr:str];
}
[str appendString:#"\n"];
NSLog(#"%#:\n%#", msg, str);
}
#end

Tap Recognition for UIImageView in the UITableViewCell

Currently I'm facing a problem, I would like to perform action when the UIImageView on my UITableViewCell had been tapped.
Question: How could I do it? Could any one show me the code, or any tutorial?
Thanks in advance!
This is actually easier than you would think. You just need to make sure that you enable user interaction on the imageView, and you can add a tap gesture to it. This should be done when the cell is instantiated to avoid having multiple tap gestures added to the same image view. For example:
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myTapMethod:)];
[self.imageView addGestureRecognizer:tap];
[self.imageView setUserInteractionEnabled:YES];
}
return self;
}
- (void)myTapMethod:(UITapGestureRecognizer *)tapGesture
{
UIImageView *imageView = (UIImageView *)tapGesture.view;
NSLog(#"%#", imageView);
}
Try this
//within cellForRowAtIndexPath (where customer table cell with imageview is created and reused)
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
tap.cancelsTouchesInView = YES;
tap.numberOfTapsRequired = 1;
[imageView addGestureRecognizer:tap];
// handle method
- (void) handleImageTap:(UIGestureRecognizer *)gestureRecognizer
{
RKLogDebug(#"imaged tab");
}
make sure u have....
imageView.userInteractionEnabled = YES;
you can use a customButton instead UIImageView
A tap gesture recogniser can be very memory hungry and can cause other things on the page to break. I would personally reconmend you create a custom table cell, insert a button into the custom cell frame and in the tableview code set the self.customtablecell.background.image to the image you want. This way you can assign the button an IBaction to make it push to whatever view you want.
Use ALActionBlocks to action in block
__weak ALViewController *wSelf = self;
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithBlock:^(UITapGestureRecognizer *weakGR) {
NSLog(#"pan %#", NSStringFromCGPoint([weakGR locationInView:wSelf.view]));
}];
[self.imageView addGestureRecognizer:gr];

UIView in front of everything not rotating with screen?

I have this code:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.image = [UIImage imageNamed:#"image.png"];
UIApplication *app = [UIApplication sharedApplication];
[app addSubViewOnFrontWindow:imageView];
...
- (void)addSubViewOnFrontWindow:(UIView *)view {
int count = [self.windows count];
UIWindow *w = [self.windows objectAtIndex:count - 1];
[w addSubview:view];
}
The problem is, when the app rotates, the view on the front doesn't rotate. It just stays in portrait.
How can I get this to rotate normally with the rest of the device?
I haven't tried this, but UIWindow has a property rootViewController
The root view controller for the window.
#property(nonatomic, retain) UIViewController *rootViewController
Discussion
The root view controller provides the content view of the
window. Assigning a view controller to this property (either
programmatically or using Interface Builder) installs the view
controller’s view as the content view of the window. If the window has
an existing view hierarchy, the old views are removed before the new
ones are installed.
The default value of this property is nil.
Availability
Available in iOS 4.0 and later.
Declared In
UIWindow.h
As you should be providing this root view controller you should be able to add it to the rootViewContoller's view, and handle aout rotation correctly.
another solution could be, that you swap the windo with a custom one while presenting your view, with another view controller. this trick in action you can see in the implementation of TSAlertView.
- (void) show
{
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate date]];
TSAlertViewController* avc = [[[TSAlertViewController alloc] init] autorelease];
avc.view.backgroundColor = [UIColor clearColor];
// $important - the window is released only when the user clicks an alert view button
TSAlertOverlayWindow* ow = [[TSAlertOverlayWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
ow.alpha = 0.0;
ow.backgroundColor = [UIColor clearColor];
ow.rootViewController = avc;
[ow makeKeyAndVisible];
// fade in the window
[UIView animateWithDuration: 0.2 animations: ^{
ow.alpha = 1;
}];
// add and pulse the alertview
// add the alertview
[avc.view addSubview: self];
[self sizeToFit];
self.center = CGPointMake( CGRectGetMidX( avc.view.bounds ), CGRectGetMidY( avc.view.bounds ) );;
self.frame = CGRectIntegral( self.frame );
[self pulse];
if ( self.style == TSAlertViewStyleInput )
{
[self layoutSubviews];
[self.inputTextField becomeFirstResponder];
}
}
with
#interface TSAlertOverlayWindow : UIWindow
{
}
#property (nonatomic,retain) UIWindow* oldKeyWindow;
#end
#implementation TSAlertOverlayWindow
#synthesize oldKeyWindow;
- (void) makeKeyAndVisible
{
self.oldKeyWindow = [[UIApplication sharedApplication] keyWindow];
self.windowLevel = UIWindowLevelAlert;
[super makeKeyAndVisible];
}
- (void) resignKeyWindow
{
[super resignKeyWindow];
[self.oldKeyWindow makeKeyWindow];
}
//
#end
add a new window, with new rootviewController, and subscribe it to
[[NSNotificationCenter defaultCenter] addObserver:(id) selector:(SEL) name:UIDeviceOrientationDidChangeNotification object:nil];
Windows don't autorotate. Ever. You should be adding this imageView to a UIViewController's view as the UIViewController has built in autorotation.
If you want to use a UIWindow to hold all your views, you will need to write your own transform code to handle rotations.

How to position a UIToolbar in a UIWebView

I've a sample project, where I have created a custom UIWebView named WebView. They are added to the view in a UIViewController. Two WebView's are initialized in the viewDidLoad and added to an array list. The first one is added as subview på self.view. The Storyboard contains a UIBarButton, and when this is tapped, the second WebView is added as subview to the self.view.
- (void)viewDidLoad
{
[super viewDidLoad];
WebView *webView1 = [[WebView alloc] initWithFrame:self.view.bounds];
WebView *webView2 = [[WebView alloc] initWithFrame:self.view.bounds];
self.webViews = [NSArray arrayWithObjects: webView1, webView2, nil];
UIWebView *webView = [self.webViews objectAtIndex:0];
[self.view addSubview:webView];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://m.google.com/"]]];
}
Here is the implementation of the WebView where a toolbar is added to the bottom (-50px) of the view:
#implementation WebView
- (void) initToolbar {
UIToolbar *toolbar = [UIToolbar new];
toolbar.barStyle = UIBarStyleBlackTranslucent;
toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
[toolbar sizeToFit];
toolbar.frame = CGRectMake(0, self.frame.size.height-80, 320, 30);
[self addSubview:toolbar];
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self initToolbar];
}
return self;
}
#end
The problem is, that the toolbar does not have the same position in the two views (they could be positioned like the first one). Why are they not positioned equally?
You can download the small sample project here:
http://uploads.demaweb.dk/UIWebView.zip
My notes: As mentioned, the two WebView's are currently initialized in the viewDidLoad. If I instead wait and first initialize then when I need them, it seems to work as expected.
The thing here is that self.frame.size.height on viewDidLoad is not the same when you initialize it via the button click. If you add the UIWebView directly in viewDidLoad, the UINavigationBar of your UINavigationController is not loaded yet and the frame of self.view is 'perceived' to be (not really, because it is) larger.
This explains the difference of 40.0 (?) points.
One possible solution to this problematic behaviour is to initialize and add (at least the first) instance of UIWebView in the viewWillAppear:animated method. (UIViewController does already implement this method)