I have one custom table name tbltask in my view and on touch begin and on touch moved method i am creating a lable dynamically.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
self.scrollEnabled=NO;
CGPoint point = [[touches anyObject] locationInView:[self superview]];
CGPoint pointtask=[[touches anyObject] locationInView:self];
NSIndexPath *indexPath = [self indexPathForRowAtPoint:pointtask];
rowid=indexPath.row;
app.sublable=[[UILabel alloc] initWithFrame:CGRectMake((point.x)-145, (point.y)-50, 300, 40)];
app.sublable.textAlignment=UITextAlignmentRight;
messagedrag=[app.arraddtask objectAtIndex:rowid];
app.sublable.text=[NSString stringWithFormat:#" %#",messagedrag.msgsubject];
app.sublable.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"black.png"]];
app.sublable.layer.cornerRadius=8.0;
app.sublable.layer.borderWidth=4;
app.sublable.layer.borderColor=[[UIColor lightGrayColor] CGColor];
app.sublable.textColor=[UIColor whiteColor];
UIFont *f = [UIFont fontWithName:#"Verdana-Bold" size:16];
app.sublable.font = f;
[app.sublable setTextAlignment:UITextAlignmentLeft];
[self.superview addSubview:app.sublable];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if(app.sublable!=nil)
{
[app.sublable removeFromSuperview];
}
CGPoint point = [[touches anyObject] locationInView:[self superview]];
NSIndexPath *indexPath = [self indexPathForRowAtPoint:point];
NSLog(#"............super %f",[self superview].frame.origin.y);
app.sublable=[[UILabel alloc] initWithFrame:CGRectMake((point.x)-145, (point.y)-50, 300, 40)];
app.sublable.textAlignment=UITextAlignmentRight;
messagedrag=[app.arraddtask objectAtIndex:rowid];
app.sublable.text=[NSString stringWithFormat:#" %#",messagedrag.msgsubject];
app.sublable.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"black.png"]];
app.sublable.layer.borderWidth=4;
app.sublable.layer.borderColor=[[UIColor lightGrayColor] CGColor];
app.sublable.layer.cornerRadius=8.0;
app.sublable.textColor=[UIColor whiteColor];
UIFont *f = [UIFont fontWithName:#"Verdana-Bold" size:16];
app.sublable.font = f;
[app.sublable setTextAlignment:UITextAlignmentLeft];
[self.superview addSubview:app.sublable];
}
it result in that.
so when i touch on tbltask touchBegan method start working and create one lable with subject is written on that in superview which is main view here on where the tbltask is there as you can see.(the bottom one is table task)
Now when i call touchesEnded method ::
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
//<my stuff>
[super touchesEnded:touches withEvent:event];
NSString *taskname=[[NSString alloc] init];
self.scrollEnabled=YES;
if(app.sublable!=nil)
{
taskname=app.sublable.text;
[app.sublable removeFromSuperview];
}
[taskdelegate droptask:self strtask:taskname];
}
this subject is dropped on above table.
It works fine.but when i touch the tbltask left to right or right to left something is happened and touch end method is not called so sublable is not removed from the view like this.like this...
so what am i doing wrong in this...
and yes i m calling the touch events on table touch as you will notice.
please help me in this problem...
Thanks in Advance.
Related
Hi
Can I add the vertical alphabets selector thing like that we use in UITableView, in UIView?
Best Regards
Yes.
If you create the UIView yourself you can do whatever you want.
It's not even that hard in your case. Some UILabels as subviews and some logic in touchesDidSomething:withEvent: to figure out which label is near the touch.
And a delegate method that tells which section was touched.
I think I could need something like that, so I decided to try it.
//myIndexSelectorView.m
- (id)initWithFrame:(CGRect)frame andLabels:(NSArray *)l {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor lightGrayColor];
self.layer.cornerRadius = frame.size.width/2;
labels = [l retain];
NSInteger count;
for (NSString *string in labels) {
CGFloat margin = 5.0f;
CGFloat yPosition = count*(frame.size.height/[labels count]);
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(margin, yPosition, frame.size.width-2*margin, frame.size.height/[labels count])] autorelease];
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor darkGrayColor];
label.textAlignment = UITextAlignmentCenter;
label.text = string;
[self addSubview:label];
count++;
}
}
return self;
}
- (void)touch:(UITouch *)touch {
CGPoint touchPosition = [touch locationInView:self];
NSInteger index = touchPosition.y / (self.bounds.size.height / [labels count]);
NSLog(#"Touched: %#", [labels objectAtIndex:index]);
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
[self touch:touch];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
[self touch:touch];
}
- (void)dealloc {
[labels release];
[super dealloc];
}
works as expected and looks similar to the index selector of uitableview
as usual, I didn't check for bugs, and this should not be a copy&paste solution.
You can use different UILabels, and set tags to them. Now to detect touches on appropriate label, you can use UITapGestureRecognizer classes
If you are talking about keypad, then that cannot be positioned other than the default position with a reason that apple does not allow to change its position.Hope that help you.Thanks.
I have an UIViewController which contains a UITableView (subclassed) and another UIView (subclassed). They are on the same hierarchy level but the UIView is added last so it is the frontmost.
I overrid touchesBegan/Moved/Ended to intercept the Gestures from the top UIView: my goal is to get the selected UITableViewCell and, if double tapped, create an ImageView to be dragged around.
I appear to get it done but now I cannot scroll the UITableView anymore, even though I forward the touch events.
Here are the methods for the UIView:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"BO");
UITouch * touch = [touches anyObject];
CGPoint tPoint = [touch locationInView:self];
InventoryViewController * invViewCont = self.viewController;
UITableView * invTab = invViewCont.inventoryTableView;
[invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow]
animated:YES];
NSArray * cells = [invTab visibleCells];
BOOL found = NO;
for (UITableViewCell * cell in cells)
{
if (CGRectContainsPoint(cell.frame, tPoint))
{
[cell touchesBegan:touches withEvent:event];
found = YES;
break;
}
}
if (!found)
{
[invViewCont.inventoryTableView touchesBegan:touches withEvent:event];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"Mo");
UITouch * touch = [touches anyObject];
CGPoint tPoint = [touch locationInView:self];
copyObj.center = tPoint;
InventoryViewController * invViewCont = self.viewController;
UITableView * invTab = invViewCont.inventoryTableView;
[invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow]
animated:YES];
NSArray * cells = [invTab visibleCells];
BOOL found = NO;
for (UITableViewCell * cell in cells)
{
if (CGRectContainsPoint(cell.frame, tPoint))
{
[cell touchesMoved:touches withEvent:event];
found = YES;
break;
}
}
if (!found)
{
[invViewCont.inventoryTableView touchesMoved:touches withEvent:event];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
if ([touch tapCount] == 2)
{
[self desubCopyView];
}
CGPoint tPoint = [touch locationInView:self];
copyObj.center = tPoint;
InventoryViewController * invViewCont = self.viewController;
UITableView * invTab = invViewCont.inventoryTableView;
[invTab deselectRowAtIndexPath:[invTab indexPathForSelectedRow]
animated:YES];
NSArray * cells = [invTab visibleCells];
BOOL found = NO;
for (UITableViewCell * cell in cells)
{
if (CGRectContainsPoint(cell.frame, tPoint))
{
[cell touchesEnded:touches withEvent:event];
//[cell.imageView touchesEnded:touches withEvent:event];
found = YES;
break;
}
}
if (!found)
{
[invViewCont.inventoryTableView touchesEnded:touches withEvent:event];
}
}
And here are those in the UITableViewCell
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
if ([touch tapCount] == 2)
{
CGPoint tPoint = [touch locationInView:self];
NSLog(#"CellX %lf CY %lf", tPoint.x, tPoint.y);
UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView * newView = [[UIImageView alloc] initWithImage:viewImage];
[dragArea addSubview:newView];
dragArea.copyObj = newView;
[newView release];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
dragArea.copyObj.transform = CGAffineTransformMakeScale(1.3, 1.3);
[UIView commitAnimations];
tPoint = [self convertPoint:tPoint toView:dragArea];
dragArea.copyObj.center = tPoint;
}
[super touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"MOV %#", self.imageView.image);
[super touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"ENDED");
[super touchesEnded:touches withEvent:event];
}
And in my UITableView I have simply:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"BEGTB");
[super touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"MOVTB");
[super touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"ENDTB");
[super touchesEnded:touches withEvent:event];
}
I am surely missing something but I do not know what
I would highly recommend looking into UITapGestureRecognizer instead of handling the touchesX events yourself.
I found a workaround for this, override the methods for touch gestures in my custom UITableView in order to make it scroll programMatically as I drag upon it an object.
Here is the 'solution'.
I still believe there is another simpler way to do this but I did not find it, so posting this and marking it as an 'answer' might help someone else.
I have a great problem since last 2 days. I'm working with a multiple Touch enabled view. My UIViewController has 8-10 imageview. I want to detect touch on each view separately, but multiple view at a time. Touch is detected on all image view, but problem is here-
Suppose I have Tap on a image view and hold down this image view and now tap another image view, second image view is detected touch successfully but it also trigger to first image view which is previously touched and hold down. But I don't want it. So please any one help me. Code level help is appreciated.
NB. My UIViewController also implemented TouchesMoved Methods for swiping purpose.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *touch in event.allTouches) {
if(CGRectContainsPoint([imView1 frame], [touch locationInView:self.view])){
NSLog(#"imView 1 touched");
}
if(CGRectContainsPoint([imView2 frame], [touch locationInView:self.view])){
NSLog(#"imView 2 touched");
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *touch in event.allTouches) {
if(CGRectContainsPoint([imView1 frame], [touch locationInView:self.view])){
NSLog(#"imView 1 touch moved");
}
if(CGRectContainsPoint([imView2 frame], [touch locationInView:self.view])){
NSLog(#"imView 2 touch moved");
}
}
}
Try subclassing a UIImageView and handle the touches code in that subclass. If you need to pass the touch to the parent for some reason, you can handle the touch then send it on to the parent which would be your view controller.
EDIT:
have your custom class like this
#interface CustomImageView : UIImageView {}#end
#implementation CustomImageView
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"touch began %d",self.tag);
[self.nextResponder touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"touch moved %d",self.tag);
[self.nextResponder touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"touch ended %d",self.tag);
[self.nextResponder touchesEnded:touches withEvent:event];
}
#end
and have your parrent code something like this
#implementation trashmeTouchIpadViewController
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"parent Touch Began");
//do parent stuff
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"parent Touch ended");
//do parent stuff
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.view setMultipleTouchEnabled:YES];
UIImage *i1 = [UIImage imageNamed:#"img1.jpg"];
CustomImageView *v1 = [[CustomImageView alloc] initWithImage:i1];
v1.frame = CGRectMake(100, 100, 200, 200);
v1.userInteractionEnabled = YES;
v1.multipleTouchEnabled = YES;
v1.tag = 111;
[self.view addSubview:v1];
[v1 release];
UIImage *i2 = [UIImage imageNamed:#"img2.jpg"];
CustomImageView *v2 = [[CustomImageView alloc] initWithImage:i2];
v2.frame = CGRectMake(500, 100, 200, 200);
v2.userInteractionEnabled = YES;
v2.multipleTouchEnabled = YES;
v2.tag = 999;
[self.view addSubview:v2];
[v2 release];
}
Fairly common question this, to which I have a few answers and I'm nearly there. I have a button which when pressed, will create an image (code as follows)
(numImages is set on load to ZERO and is used as a count up for the tag numbers of all images created)
UIImage *tmpImage = [[UIImage imageNamed:[NSString stringWithFormat:#"%i.png", sender.tag]] retain];
UIImageView *myImage = [[UIImageView alloc] initWithImage:tmpImage];
numImages += 1;
myImage.userInteractionEnabled = YES;
myImage.tag = numImages;
myImage.opaque = YES;
[self.view addSubview:myImage];
[myImage release];
I then have a touchesBegan method which will detect what's touched. What I need it to do is to allow the user to drag the newly created image. It's nearly working, but the image flickers all over the place when you drag it. I can access the image which you click on as I can get it's TAG, but I just cannot drag it nicely.
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
if (touch.view.tag > 0) {
touch.view.center = location;
}
NSLog(#"tag=%#", [NSString stringWithFormat:#"%i", touch.view.tag]);
}
- (void) touchesMoved:(NSSet *)touches withEvent: (UIEvent *)event {
[self touchesBegan:touches withEvent:event];
}
It works, in that I get an output of the tag for each image as I click on them. But when I drag, it flashes... any ideas?
In answer to my own question - I decided to create a class for handling the images I place on the view.
Code if anyone's interested....
Draggable.h
#import <Foundation/Foundation.h>
#interface Draggable : UIImageView {
CGPoint startLocation;
}
#end
Draggable.m
#import "Draggable.h"
#implementation Draggable
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
// Retrieve the touch point
CGPoint pt = [[touches anyObject] locationInView:self];
startLocation = pt;
[[self superview] bringSubviewToFront:self];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
// Move relative to the original touch point
CGPoint pt = [[touches anyObject] locationInView:self];
CGRect frame = [self frame];
frame.origin.x += pt.x - startLocation.x;
frame.origin.y += pt.y - startLocation.y;
[self setFrame:frame];
}
#end
and to call it
UIImage *tmpImage = [[UIImage imageNamed:"test.png"] retain];
UIImageView *imageView = [[UIImageView alloc] initWithImage:tmpImage];
CGRect cellRectangle;
cellRectangle = CGRectMake(0,0,tmpImage.size.width ,tmpImage.size.height );
UIImageView *dragger = [[Draggable alloc] initWithFrame:cellRectangle];
[dragger setImage:tmpImage];
[dragger setUserInteractionEnabled:YES];
[self.view addSubview:dragger];
[imageView release];
[tmpImage release];
Usually you get an implicit animation when you change center. Are you messing with -contentMode or calling -setNeedsDisplay by any chance?
You can explicitly request animation to avoid the delete and re-draw this way:
if (touch.view.tag > 0) {
[UIView beginAnimations:#"viewMove" context:touch.view];
touch.view.center = location;
[UIView commitAnimations];
}
Do note that NSLog() can be very slow (much slower than you'd expect; it's much more complicated than a simple printf), and that can cause trouble in something called as often as touchesMoved:withEvent:.
BTW, you're leaking tmpImage.
I'm creating an application where I want to let the user move (not pan) an UIImageView around by dragging it on the screen. Additionally, I want the user to be able to zoom the UIImageView in and out.
As such I've been using a custom UIScrollView that forwards single touches to the 'contentView':
#implementation JM_UIScrollView
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
NSSet *allTouches = [event allTouches];
NSLog(#"Checking for touches: %d", [allTouches count]);
if ([allTouches count] == 1) {
return YES;
}
return NO;
}
#end
Along with a custom UIImageView that implements touchesBegan and touchesMoved to determine where to move the UIImageView:
#implementation JM_UIImageView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
if ([allTouches count] == 0)
return;
UITouch *firstTouch = [[allTouches allObjects] objectAtIndex: 0];
CGPoint touchLoc = [firstTouch locationInView: [self superview]];
touchOffset= CGPointMake(touchLoc.x-self.center.x,touchLoc.y-self.center.y);
NSLog(#"Currently at: %3.3f x %3.3f", touchLoc.x, touchLoc.y);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
if ([allTouches count] == 0)
return;
UITouch *firstTouch = [[allTouches allObjects] objectAtIndex: 0];
CGPoint touchLoc = [firstTouch locationInView: [self superview]];
if ([allTouches count] == 1)
{
if ([firstTouch view] == self)
{
touchLoc.x -= touchOffset.x;
touchLoc.y -= touchOffset.y;
NSLog(#"Moved to: %3.3f x %3.3f", touchLoc.x, touchLoc.y);
self.center = touchLoc;
}
}
}
#end
This is then all glued together:
scrollView = [[JM_UIScrollView alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
scrollView.delegate = self;
scrollView.bouncesZoom = YES;
scrollView.scrollEnabled = NO;
scrollView.backgroundColor = [UIColor redColor];
scrollView.clipsToBounds = YES;
UIImage *image = [UIImage imageNamed:#"berg.jpg"];
imageView = [[JM_UIImageView alloc] initWithFrame: CGRectMake(0, 0, 140, 230)];
imageView.image = image;
imageView.center = CGPointMake(200,300);
[imageView setUserInteractionEnabled: YES];
[scrollView addSubview: imageView];
scrollView.contentSize = CGSizeMake(140,230);
scrollView.minimumZoomScale = 0.2;
scrollView.maximumZoomScale = 1.1;
[window addSubview: scrollView];
// Override point for customization after application launch
[window makeKeyAndVisible];
The problem:
When I start the application, I can move the UIImageView just fine and fluently. I can zoom-in and still be able to move it around.
However, it seems that whenever I zoom back out to the maximum level I seem then unable to move the UIImageView around anymore. It will jump at times, but by a maximum of 10 pixels. Use of NSLog() shows the touchesBegan/touchesMoved methods on the JM_UIImageView are no longer called.
Does anyone have any idea on what I might be missing here?
EDIT:
Would also accept an answer for wether or not this is the only way of implementing pinch-zooming with the zoombounce animation.