I have subclass of UIView
#interface TBL_CardView : UIView
It it internally have UIImageView for card image.
I need to handle touching of card in following way:
When I touch (and still hold) TBL_CardView I need to set orange borderColor.
If I am stil on top of TBL_CardView I need to set red borderColor.
If I am not on top of TBL_CardView, I have moved my finger, because I want to cancel touch, then borderColor is removed.
I know how to handle setting of borderColor:
self.layer.borderColor = [UIColor redColor].CGColor;
self.layer.borderWidth = 3.0f;
But I do not know what is the easiest way to implement thin button like behavior ?
Should I make it just as button, or use UIResponder or something else ?
What are pros and cons for each case ?
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"%s", __PRETTY_FUNCTION__);
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView: self];
BOOL isInside = [self pointInside: touchLocation withEvent: event];
if (isInside)
{
//if logic
NSLog(#"INSIDE");
}
else
{
//else logic
NSLog(#"OUTSIDE");
}
}
You could check out this post for information on how to implement button-like behaviour and respond to touches on a UIView or a subclass.
Touch Event on UIView
What I usually do myself, however, is put a transparent (clear color and no title, not alpha = 0.0) UIButton on top of my UIView matching it s size and responding to the events I need instead. Check if it fits your needs.
Related
I want to scroll the image that is inside my UIImageView in case my finger is inside the UIImageView area and i'm moving my finger. I'm trying to do that using objective c. I got it moving, but it act weird and dont work right. Can you please show me how to do that please???
This is what i'm doing:
- (void)touchesMoved :(NSSet *)touches withEvent:(UIEvent *)event{
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self];
for (id sublayer in view_shape.sublayers) {
if (sublayer ==imageView.layer) {
if (CGRectContainsPoint(imageView.frame, touchLocation)) {
imageView.layer.contentsRect = CGRectMake( touchLocation.x/1000,
touchLocation.y/1000,
imageView.layer.contentsRect.size.width,
imageView.layer.contentsRect.size.height);
}
}
}
}
}
Why not use a scrollView and just add the imageView to it
You can't do this with just an instance of UIImageView. An image view will just hold on to an image and draw that.
Either add that inside a scrollview if you want a simple scroll/paging interface.
(or)
Add that to a UIView, and declare a UIPanGestureRecognizer to the UIView, and check the actions you get. Based on the translation, you can set the frame for the UIImageView.
I have looked at UIButton can't be touched while animated with UIView animateWithDuration and the answer doesn't help me.
for (UIButton *button in self.buttonsOutletCollection)
This part is the one that is confusing. My button isn't part of a IBOutletCollection so this doesn't work. I use this to move the button:
- (void) squareOneMover {
CGRect oldFrame = _squareOne.frame;
[UIView animateWithDuration:2
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
CGRect newFrame = CGRectMake(oldFrame.origin.x , oldFrame.origin.y + 500, oldFrame.size.width, oldFrame.size.height);
_squareOne.frame = newFrame;
}
completion:nil
];
}
I don't want to have to move the Button in small amounts because I need five buttons and it would be inefficient.
Can someone provide me with an answer similar to the question above that is for UIButtons not include in any array?
Edit:
The UIButton is defined in the interface file and connected to Interface Builder, and is strong and nonamatic
Edit 2: I am now using animateWithDuration:delay:options:animations:completion: but it still doesn't work.
I use this code to detect if the button is being pressed.
- (void)squareOnePressed:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if ([self.squareOne.layer.presentationLayer hitTest:touchLocation])
{
NSLog(#"YO");
}
}
But when the button is pressed nothing still happens... So how do I program that ^^^^
Try calling animateWithDuration:delay:options:animations:completion: with UIViewAnimationOptionAllowUserInteraction in the options parameter.
Add an IBAction to your view controller and connect your button to that. Put your NSLog in the IBAction method. (Do you know how to do this?)
Why is your method named squareOneTouched:? Is your IBAction triggering that?
If you're subclassing a UIViewController, you should just override the touchesBegan: method.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if ([self.squareOne.layer.presentationLayer hitTest:touchLocation])
{
// This button was hit whilst moving - do something with it here
NSLog(#"YO");
}
}
I found the problem. The constraints are preventing me from interacting with the button. When I remove the programmatically written constraints from the button, it works fine.
I'm working on an iOS app.
I have a UIView that is being animated. It keeps moving from left to right.
This view has several UIView children. They move within their parent when this is being animated.
When I try to capture user touches on the children (by using a UITapGestureRecognizer), it doens't work as expected. It sort of detect some touches on the children, but not in the position where they currently are.
I've been struggling with this for a while now. Any ideas about how to solve this? I really need to detect which children the user is touching.
Thanks!
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self];
// Check every child subview
for (UIView *tickerItem in self.subviews)
{
// Check collision
if ([tickerItem.layer.presentationLayer hitTest:touchLocation])
{
MKTickerItemView *v = (MKTickerItemView*)tickerItem;
NSLog(#"Selected: %#", v.title);
// This button was hit whilst moving - do something with it here
break;
}
}
}
There is a UIViewAnimationOptions value...
UIViewAnimationOptionAllowUserInteraction
You can use this in the [UIView animateWithDuration... code.
This will enable the touch.
Just like the title ,when I touch the UIView I want the touch point to be glow, I came up with a idea that to show a glow image on the touch point ,but if by code?any example or idea?thanks for sharing!!
You can try touchesBegan event below Code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if([touch view] ==self.my_view)//Check click your uiview or not
{
CGRect frame = [your_image_view frame];
CGPoint touchLocation = [touch locationInView:touch.view];
frame.origin.x=touchLocation.x;
frame.origin.y=touchLocation.y;
[your_image_view setFrame:frame];
[self.my_view addSubview:your_image_view];
}
}
Thanks..!
Well the first step would be to detect the touch on your UIView for that I would recommend using the high level API UIGestureRecognizer andd add to your view. Then you can use the call back to do whatever you want, perhaps some sort of animation?. If so you can use an animation block to animate your changes.
I am implementing a simple iOS solitaire game that allows the user to drag the cards around in the usual way. The cards are represented with the UIView subclass CardView. All the card view's are siblings which are subviews of SolitaireView. The following snippet tries to "bring a card to the front" so that it is above all the other views as it is being dragged:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if (touch.view.tag == CARD_TAG) {
CardView *cardView = (CardView*) touch.view;
...
[self bringSubviewToFront:cardView];
...
}
}
Unfortunately, the card's z-order remains unchanged during the drag. In the images below, I am dragging the King. Notice how it is correctly on top the Nine in the left image, but is incorrectly under the Two (under the entire stack actually) in the right image:
I also tried alter the layer.zPosition property as well to no avail.
How can I bring the card view to the front during the drag? I am mystified.
Confirmed. bringSubviewToFront: causes layoutSubview to be invoked. Since my version of layoutSubviews sets the z-orders on all the views, this was undoing the z-order I was setting in the touchesBegan:withEvent code above. Apple should mention this side effect in the bringSubviewToFront documentation.
Instead of using a UIView subclass, I created a CALayer subclass named CardLayer. I handle the touch in my KlondikeView subclass as listed below. topZPosition is an instance var that tracks the highest zPosition of all cards. Note that modifying the zPosition is usually animated -- I turn this off in the code below:
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
CGPoint hitTestPoint = [self.layer convertPoint:touchPoint
toLayer:self.layer.superlayer];
CALayer *layer = [self.layer hitTest:hitTestPoint];
if (layer == nil) return;
if ([layer.name isEqual:#"card"]) {
CardLayer *cardLayer = (CardLayer*) layer;
Card *card = cardLayer.card;
if ([self.solitaire isCardFaceUp:card]) {
//...
[CATransaction begin]; // disable animation of z change
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
cardLayer.zPosition = topZPosition++; // bring to highest z
// ... if card fan, bring whole fan to top
[CATransaction commit];
//...
}
// ...
}
}