override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touchesSet = touches as NSSet
let touch = touchesSet.anyObject() as? UITouch
let location = touch?.location(in: self.view)
if touch!.view == bee1 {
bee1?.center = location!
} else if touch!.view == bee2 {
bee2?.center = location!
}
}
I need code this game for iOS, using Swift; but I don't know how to apply touches to images, using Swift. My attempts thus far have failed; touch!.view != image
If this images are indiviudal image views, then you can simply put tap recognizer and call action when you touch it.
How to assign an action for UIImageView object in Swift
I think that you need to use gesture and set the image userInteractionEnabled = true
OBJ-C:
self.imageView.userInteractionEnabled = YES;
UITapGestureRecognizer * tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapImageView:)];
tap.delegate= self;
[self.imageView addGestureRecognizer:tap];
Related
I have been unable to make it work the gesture recognizer in my app.
Under viewDidLoad I added these
let orangeIndicatorTap = UITapGestureRecognizer(target: self, action: #selector(self.orangeIndicatorClick(_:)))
orangeIndicatorTap.numberOfTapsRequired = 1
orangeIndicatorTap.delegate = self
conceptMiddleOrangeIndicator.tag = 1
conceptMiddleOrangeIndicator.isUserInteractionEnabled = true
conceptMiddleOrangeIndicator.addGestureRecognizer(orangeIndicatorTap)
let greenIndicatorTap = UITapGestureRecognizer(target: self, action: #selector(self.greenIndicatorClick(_:)))
greenIndicatorTap.numberOfTapsRequired = 1
conceptMiddleGreenIndicator.isUserInteractionEnabled = true
conceptMiddleGreenIndicator.addGestureRecognizer(greenIndicatorTap)
let purpleIndicatorTap = UITapGestureRecognizer(target: self, action: #selector(self.purpleIndicatorClick(_:)))
greenIndicatorTap.numberOfTapsRequired = 1
conceptMiddlePurpleColorIndicator.isUserInteractionEnabled = true
conceptMiddlePurpleColorIndicator.addGestureRecognizer(purpleIndicatorTap)
Is there any other way i could add a click event to my overlapping custom uitextviews?
you can use touchesBegan to identify which view has been touched.
use this code hope this help.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if touch.view == yourView_outlet {
// add your code here
} else if touch.view == yourView_outlet {
// add your code here
}
}
I fixed it, It was because of an overlay that wasnt being removed correctly.
It seems that, it visibly is removed but logically underlying overlay views were not removed. That's why the gesture doesnt work.
Hopefully this will help someone in the future.
I was implementing this function.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.location(in: self.view) else { return }
for i in 0..<paths.count {
if paths[i].contains(point) { addViews(selectedView: i); break }
}
}
My designers decided they want to make a small part of the views I add to overlay the navigationBar. The problem is that after I add the views to the navigationController.view instead, I am no longer able to detect the touches. I have tried location(in: self.navigationController.view) and that didn't work. Before I go down the rabbit hole of endless different things that might work, does anyone have an easy answer for me?
While navigationController is nominally a ViewController, it's 'view' outlet is usually not used, and probably not put in the responder chain.
My solution was to create a custom view (in the storyboard) as outlet for navigationItem.titleView for the UIViewController.
You can set up the custom view in viewDidLoad() (instead of storyboard)
self.navigationItem.titleView = myCustomView;
In viewDidLoad I set up a gesture like:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleStatusTap:)];
[chatTitleView addGestureRecognizer:singleTap];
I have tried too many equations to get the right answer, maybe something wrong with the code or my understanding of the idea. However, here is my code:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let coord = touch.location(in:view)
self.linegu.transform = CGAffineTransform.init(rotationAngle: atan((coord.y - (self.view.center.y + (self.view.center.y)/2.5)) / (coord.x - self.view.center.x)))
}
}
linegu is the UIImageView I'm using and I position it in the middle of the view by using this code:
let Ypos = (self.view.center.y/2.5);
self.linegu.center = self.view.center
self.linegu.center.y = (self.view.center.y + Ypos)
It doesn't matter where the image view is located. And you should throw away your "magic number" 2.5. You are way overthinking this.
Assume arrow is the image view, and that it starts out life horizontal with the arrow pointing to the right. And assume that the background view has a tap gesture recognizer on it. (We use a tap gesture recognizer for simplicity; it looks like you might eventually want to use a pan gesture recognizer. But for now, let's just get this thing working.)
Then here is how the tap gesture's action handler would look:
let c = self.arrow.center
let p = t.location(in: self.arrow.superview)
let angle = atan2(p.y - c.y, p.x - c.x)
self.arrow.transform = CGAffineTransform(rotationAngle:angle)
It's as simple as that.
Why do you use this weird formula?
CGAffineTransform.init(rotationAngle: atan((coord.y - (self.view.center.y + (self.view.center.y)/2.5)) / (coord.x - self.view.center.x)))
And where does this 2.5 divider come from?
What about just using .center or .frame to position the UIImageView?
Like:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: view)
imageView.center = location // may need to apply some offset here, depending on where exactly the arrow points in the arrow image
}
}
I have 2 custom-drawn subviews on a superview and 2 gesture recognisers to call 2 different methods. Problem is, when I tap on any of the views, tap on the second subview still fires the first method! Here's my code:
- (void) addTapGestures{
self.firstTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(firstSelector)];
self.firstTap.numberOfTapsRequired = 1;
[self.firstSubview addGestureRecognizer:self.firstTap];
self.secondTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(secondSelector)];
self.secondTap.numberOfTapsRequired = 1;
[self.secondSubview addGestureRecognizer:self.secondTap];
Will appreciate any hints!
You can get the tapped view by using hitTest method of UIView. Based on that you can decide which method should be called. Put this method in your superview containing both of your subviews.
Here is an example.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
if ([self.firstSubView isEqual:hitView])
{
// You clicked on firstSubView, by returning firstSubView it will call its respective selector method
return self.firstSubView;
}
else if ([self.secondSubView isEqual:hitView])
{
return self.secondSubView;
}
return hitView;
}
Answer from my comments. Common problems I can think of:
1) self.firstSubview is equal to self.secondSubview
2) Views are overlapping and/or user interaction is disabled on one of them.
Second one turned out to be a problem.
Swift 2.0:
Try: -
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
//make condition here
}
OR
Use a UIPanGestureRecognizer. In the ViewController, install the recognizer on the “parent” view.
var pan = UIPanGestureRecognizer(target:self, action:"pan:")
pan.maximumNumberOfTouches = 1
pan.minimumNumberOfTouches = 1
self.view.addGestureRecognizer(pan)
In the recognizer action, first grab the location of the event. Then, depending on the state of the recogniser, implement the different parts of the drag functionality.
func pan(rec:UIPanGestureRecognizer) {
var p:CGPoint = rec.locationInView(self.view)
var center:CGPoint = CGPointZero
switch rec.state {
case .Began:
println("began")
self.selectedView = view.hitTest(p, withEvent: nil)
if self.selectedView != nil {
self.view.bringSubviewToFront(self.selectedView!)
}
case .Changed:
if let subview = selectedView {
center = subview.center
var distance = sqrt(pow((center.x - p.x), 2.0) + pow((center.y - p.y), 2.0))
println("distance \(distance)")
if subview is MyView {
if distance > threshold {
if shouldDragX {
subview.center.x = p.x - (p.x % snapX)
}
if shouldDragY {
subview.center.y = p.y - (p.y % snapY)
}
}
}
}
case .Ended:
if let subview = selectedView {
if subview is MyView {
// do whatever
}
}
// must do this of course
selectedView = nil
}
In AcaniUsers, I've created a grid of ThumbView : UIView instances inside of a UITableView. All thumbViews have a width of kThumbSize. How do I detect if touches ended inside the same view in which they began?
In the view extension you use;
Swift 4:
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
guard let touchPoint = touches.first?.location(in: self) else { return }
guard self.bounds.contains(touchPoint) else { return }
// Do items for successful touch inside the view
}
The following works, but I'm not sure if it's the best way to go about it. I think so though.
Since all thumbViews have a width of kThumbSize, just check in touchesEnded that the x-coordinate of the locationInView of the UITouch instance (assuming self.multipleTouchEnabled = NO) is less than or equal to kThumbSize. This means the touches ended inside the thumbView. No need to check the y-coordinate because if the touches move vertically, the tableView, which contains the thumbViews, scrolls and the touches are cancelled.
Do the following in ThumbView : UIView (whose instances are subviews of a UITableView):
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touchesEnded %#", touches);
CGPoint touchPoint = [[touches anyObject] /* only one */ locationInView:self];
if (touchPoint.x >= 0.0f && touchPoint.x <= kThumbSize) {
[(ThumbsTableViewCell *)self.superview.superview thumbTouched:self];
}
}
To only register touches on one thumbView at a time, you also probably want to set self.exclusiveTouch = YES; in the init instance method of ThumbView.