I have a UIButton inside a custom cell. Upon selecting the cell, the button changes it state to "highlighted" as well.
I'd like to prevent that behaviour. The button should change its state only when it's specifically touched (I take care of that in my IBAction).
Is it possible?
You can subclass UIButton and override the setSelected: method and not call [super setSelected:] or call it with [super setSelected:NO];
If you want to select it yourself, call [super setSelected:YES];
This is what I used eventually (inside my Custom cell implementation):
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
BOOL highlightState = self.btn.highlighted;
BOOL selectedState = self.btn.selected;
[super setSelected:selected animated:animated];
self.btn.selected = selectedState;
self.btn.highlighted = highlightState;
}
- (void) setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
BOOL highlightState = self.btn.highlighted;
BOOL selectedState = self.btn.selected;
[super setHighlighted:highlighted animated:animated];
self.btn.selected = selectedState;
self.btn.highlighted = highlightState;
}
In your cell's class override:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
self.button.highlighted = NO;
}
Related
i am subclassing UIButton to create a simple Checkbox behavior. here is the code :
#import "RadioButton.h"
#implementation RadioButton
#synthesize isSelected;
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[self ChangeButtonState];
}
-(void)ChangeButtonState{
if (!isSelected) {
isSelected = YES;
[self setBackgroundImage:[UIImage imageNamed:#"radiobtn_on.png"] forState:UIControlStateNormal];
}
else{
isSelected = NO;
[self setBackgroundImage:[UIImage imageNamed:#"radiobtn_off.png"] forState:UIControlStateNormal];
}
}
-(id)init{
self.adjustsImageWhenHighlighted=YES;
self.alpha = 1;
[self ChangeButtonState];
isSelected = NO;
[self setBackgroundImage:[UIImage imageNamed:#"radiobtn_off.png"] forState:UIControlStateNormal];
return self;
}
- (id)initWithFrame:(CGRect)frame
{
[self setBackgroundImage:[UIImage imageNamed:#"radiobtn_off.png"] forState:UIControlStateNormal];
isSelected = NO;
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
first, when i set the class in the interface builder to a button when i launch the app i dont see anything until i hit this invisible button.
the seconed thing is the images looks dark then the original
help would be great!
thanks!
try your stuff in - (void)awakeFromNib. define this method in your subclass. When you assign your custom class in xib then this method will be called and apply your logic there.
I've setup a tap gesture recognizer and add the recognizer to the uibutton. The button has a background image. When I tap the button it doesn't highlight at all, the only thing I've been able to get it to do is change it's alpha value.
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured:)];
singleTap.cancelsTouchesInView = NO;
[btnNext addGestureRecognizer:singleTap];
- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
UIView *tappedView = [gesture.view hitTest:[gesture locationInView:gesture.view] withEvent:nil];
NSLog(#"Touch event view: %#",[tappedView class]);
UIButton *myButton = (UIButton *) tappedView;
[self highlightButton:myButton];
tappedView.alpha = 0.5f;
}
Any would be appreciated. Thanks
You can intercept the touches events with a gesture recognizer, and then programmatically add the recognizer to all your uibuttons. For instance:
//
// HighlighterGestureRecognizer.h
// Copyright 2011 PathwaySP. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface HighlightGestureRecognizer : UIGestureRecognizer {
id *beganButton;
}
#property(nonatomic, assign) id *beganButton;
#end
and the implementation:
//
// HighlightGestureRecognizer.m
// Copyright 2011 PathwaySP. All rights reserved.
//
#import "HighlightGestureRecognizer.h"
#implementation HighlightGestureRecognizer
#synthesize beganButton;
-(id) init{
if (self = [super init])
{
self.cancelsTouchesInView = NO;
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.beganButton = [[[event allTouches] anyObject] view];
if ([beganButton isKindOfClass: [UIButton class]]) {
[beganButton setBackgroundImage:[UIImage imageNamed:#"grey_screen"] forState:UIControlStateNormal];
[self performSelector:#selector(resetImage) withObject:nil afterDelay:0.2];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)reset
{
}
- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event
{
}
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer
{
return NO;
}
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
{
return NO;
}
- (void)resetImage
{
[beganButton setBackgroundImage: nil forState:UIControlStateNormal];
}
#end
The way you'd add the gesture recognizer to your button would be like so:
HighlighterGestureRecognizer * tapHighlighter = [[HighlighterGestureRecognizer alloc] init];
[myButton addGestureRecognizer:tapHighlighter];
[tapHighlighter release];
So basically you're declaring it, initializing it, and then adding it. After that, you'll want to release it, since the addGestureRecognizer retains it.
Also simply try
adjustsImageWhenHighlighted = YES set on your buttons? The default is YES, but maybe you changed it in the xib. It's the "Highlighted Adjusts Image" checkbox in the attributes inspector:
First of all, this problem did not exist in iOS 4.3. I can still run the program in iOS 4.3 and won't see any problem. Secondly, this is an iPad app.
The problem is that when I hold down an image and drag it, it won't be dragged. It worked in iOS 4.3 but not iOS 5.
I created new testing project and cleared everything that's not needed. The project I chose is a Single View Application and did not alter any of the AppDelegate files.
Here is the code.
myUIScrollViewClass.h
#import <UIKit/UIKit.h>
#interface myUIScrollViewClass : UIScrollView
{
}
#end
myUIScrollViewClass.m
#import "myUIScrollViewClass.h"
#implementation myUIScrollViewClass
- (id)init
{
self = [super init];
if (self)
{
}
return self;
}
- (void)didReceiveMemoryWarning
{
[self didReceiveMemoryWarning];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesBegan: touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesMoved: touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesEnded: touches withEvent:event];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.nextResponder touchesCancelled: touches withEvent:event];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "myUIScrollViewClass.h"
#interface ViewController : UIViewController <UIScrollViewDelegate>
{
myUIScrollViewClass *mainScrollView_;
UIImageView *aTouchedImage_;
}
#property (retain, nonatomic) myUIScrollViewClass *mainScrollView_;
#property (retain, nonatomic) UIImageView *aTouchedImage_;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize mainScrollView_;
#synthesize aTouchedImage_;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
mainScrollView_ = [[myUIScrollViewClass alloc] initWithFrame:self.view.frame];
[self.view addSubview:mainScrollView_];
mainScrollView_.delegate = self;
mainScrollView_.contentSize = CGSizeMake(1024, 768);
mainScrollView_.clipsToBounds = YES;
mainScrollView_.bounces = NO;
mainScrollView_.bouncesZoom = NO;
mainScrollView_.showsVerticalScrollIndicator = NO;
mainScrollView_.showsHorizontalScrollIndicator = NO;
mainScrollView_.backgroundColor = [UIColor whiteColor];
mainScrollView_.userInteractionEnabled = YES;
aTouchedImage_ = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"image1.png"]];
[aTouchedImage_ setFrame:CGRectMake(0, 0, 80, 80)];
[mainScrollView_ addSubview:aTouchedImage_];
[aTouchedImage_ setCenter:CGPointMake(512, 334)];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = NO;
for (UITouch *touch in touches)
{
[aTouchedImage_ setCenter:[touch locationInView:self.view]];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = NO;
for (UITouch *touch in touches)
{
[aTouchedImage_ setCenter:[touch locationInView:self.view]];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = YES;
for (UITouch *touch in touches)
{
}
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)anEvent
{
mainScrollView_.scrollEnabled = YES;
for (UITouch *touch in touches)
{
}
}
#end
It seems I will answer my own question.
I have requested a support from Apple Developer Technical Support, and they told me to place my code in the UIScrollView rather than passing the touch events to another view. Apple themselves admitting that there is a problem with passing touch events.
Here is an extract of their reply:
"It looks like not all touch events are getting through to your view controller. Your UIScrollView is blocking touch events from getting through, even though is forwards those events to the next responder. The behaviour is very erratic, some touch events are being forwarded to your view controller, but not all of them."
"Looks like a behaviour change in iOS 5.0.x. My guess it's because of the view controller containment feature that was introduced."
The other way to do it is to use UIGestureRecognizer to implement dragging of views. Something like the code below:
- (void)viewDidLoad
{
// ... other initialization code here
UILongPressGestureRecognizer *longPress = [[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(dragChild:)] autorelease];
[longPress setMinimumPressDuration:0]; // recognize immediately when a finger comes down
[draggableView addGestureRecognizer:longPress];
}
- (void)dragChild:(UILongPressGestureRecognizer *)longPress
{
[[longPress view] setCenter:[longPress locationInView:[[longPress view] superview]];
}
Is it possible to always show text cursor in UISearchBar (not only after touch)?
add this
- (void)viewDidAppear:(BOOL)animated {
[mySearchBar becomeFirstResponder];
[super viewDidAppear:animated];
}
Also try this...
- (void)viewDidAppear:(BOOL)animated {
[mySearchBar becomeFirstResponder];
[super viewDidAppear:animated];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[mySearchBar becomeFirstResponder];
}
How can I hide the keyboard on ScrollView touch event...
Scenario is like that...
->View ->ScrollView ->Textfield
I want to hide the keyboard on touch of scrollView. I tried to override the class for scrollview but still i can't do it.
Doing like this will help:
#interface MyClass <UIScrollViewDelegate> {
}
#implementation
- (void)viewDidLoad {
yourScrollView.delegate = self;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[myTextField resignFirstResponder];
}
If you really want to handle the touch event, then you need to subclass the UIScrollView and override the method:
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
}
More about UIScrollView touch
This is what worked for me
in your viewController's viewDidLoad-method
UITapGestureRecognizer *tapScroll = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapped)];
tapScroll.cancelsTouchesInView = NO;
[viewScroller addGestureRecognizer:tapScroll];
where viewScroller is your scroller. In the tapped-method we have
- (void) tapped {
[self.view endEditing:YES];
}
Don't know why but the above did not work for me...even though it should
Try this:
Add gesturerecognizer for scrollview,
UITapGestureRecognizer *tapScroll = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped)];
tapScroll.cancelsTouchesInView = NO;
[yourScrollview addGestureRecognizer:tapScroll];
[tapScroll release];
Resign your keyboard in (tapped:) method.
Please, take a look at this answer, This is the easiest one I found.
UitextField resignFirstResponder does not work in scroll view
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
[self.view endEditing:YES];
return YES;
}