UIPickerView inside UIScrollView hitTest to disable Scrollview? - objective-c

I am currently building an application which has a resized UIPickerView on a scrollview the problem I am facing is that when you try to scroll the picker the scrollview is moving instead.
For the past few hours I have tried to fix this by disabling the scrollview when the picker is selected by creating a UIScrollView sub class which performs the following hitTest:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if ([result.superview isKindOfClass:[UIPickerView class]])
{
NSLog(#"Cancel touch");
self.canCancelContentTouches = NO;
self.delaysContentTouches = NO;
self.scrollEnabled = NO;
}
else
{
self.canCancelContentTouches = YES;
self.delaysContentTouches = YES;
self.scrollEnabled = YES;
}
return result;
}
With this above code I find that when I click and hold certain sections of the UIPickerView it cancels the touch and disables the UIScrollview OK and I can move the UIPicker to select a new value, however when I certain areas on the PickerView and do an NSLog on the reported class like below
NSLog(#"%#", [result.superview class]);
It outputs UIPickerTableViewWrapperCell to the console and the isKindOfClass[UIPickerView class] never gets entered.
I have also tried isMemberOfClass which also does not work.
Any help would be appreciated.
Thanks Aaron

I think I have figured this out, by searching the class description to see if it contains #"UIPicker*"
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
NSString *viewDescription = [result.superview class].description;
NSRange range = [viewDescription rangeOfString : #"UIPicker"];
if (range.location != NSNotFound)
{
NSLog(#"Cancel touch on ScrollView");
self.canCancelContentTouches = NO;
self.delaysContentTouches = NO;
self.scrollEnabled = NO;
}
else
{
self.canCancelContentTouches = YES;
self.delaysContentTouches = YES;
self.scrollEnabled = YES;
}
return result;
}
Now when I drag the UIPicker it works perfectly and the scrollview does not move at all, unless I am clicking on that and dragging it.
Aaron

Related

cocos2d self.touchEnabled = YES not found

-(id)init
{
if ((self = [super init]))
{
[self setupTitle];
self.touchEnabeled = YES;
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[[CCDirector sharedDirector]
replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[GameScene node]]];
CCSprite *start = (CCSprite *)
[self getChildByTag:1]; [start stopAllActions];
start.visible = NO;
}
Cant Get self.touchEnabled = YES; working it gives an error ;
touchEnabled Not found on object type of 'TitleLayer'
In older versions, the code is:
self.touchEnabled = YES;
Try just copying this and putting it in.
This property is called userInteractionEnabled since cocos2d v3.0.
If you're using older version of cocos2d try to fix the typo in your code. The right name for property is touchEnabled.

pan gesture recognise button issue

I set a pan gesture recogniser to recognise my touch on some buttons and am running into the following issue. I am trying to add an action to each of the buttons. I'm testing this by telling each different button to become highlighted when I touch them. So far when I keep my finger pressed on the screen en slide around only button1 and button2 show up (as written in the code).
But for some reason I can still see other buttons highlight the same way when I press them individually. Any idea how to solve this so that they only respond to. If button.tag == 3 etc.. Then respond? Here is the code. (This is all the code in the project and a few buttons in the interface builder.)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Add Gesture to track the finger
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[self.view addGestureRecognizer:pan];
}
- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateChanged) {
CGPoint point = [gesture locationInView:self.view];
for (UIButton *button in [self.view subviews]) {
if ([button isKindOfClass:[UIButton class]]) {
if (button.tag == 1) {
button.highlighted = CGRectContainsPoint(button.frame, point);
} else if (button.tag == 2) {
button.highlighted = CGRectContainsPoint(button.frame, point);
} //
}
}
}
else if (gesture.state == UIGestureRecognizerStateEnded)
{
for (UIButton *button in [self.view subviews]) {
if ([button isKindOfClass:[UIButton class]]) {
button.highlighted = NO;
}
}
}
}
EDIT :
[[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanned:)];
- (void)handlePanned:(UIPanGestureRecognizer*)thePanner{
if (thePanner.state == UIGestureRecognizerStateChanged ){
//disable button
}else if (thePanner.state == UIGestureRecognizerStateEnded) {
//enable button
}else if ( thePanner.state == UIGestureRecognizerStateFailed ){
//enable button
}
}
You aren't checking to see if where you are touching is where a button is located.
Quickest solution I see is:
Create properties for each of your buttons, we'll call them button1, button2 and button3.
Create your panGestureRecognizer
- (void)viewDidLoad
{
[super viewDidLoad];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[self.view addGestureRecognizer:pan];
}
Your method to handle the pan:
-(void)handlePanGesture:(UIPanGestureRecognizer *)gesture
{
//create a CGpoint so you know where you are touching
CGPoint touchPoint = [gesture locationInView:self.view];
//just to show you where you are touching...
NSLog(#"%#", NSStringFromCGPoint(touchPoint));
//check your button frame's individually to see if you are touching inside it
if (CGRectContainsPoint(self.button1.frame, touchPoint))
{
NSLog(#"you're panning button1");
}
else if(CGRectContainsPoint(self.button2.frame, touchPoint))
{
NSLog(#"you're panning button2");
}
else if (CGRectContainsPoint(self.button3.frame, touchPoint))
{
NSLog(#"you're panning button3");
}
And that should be it.

Dynamic textView resize broken after update to iOS 7.1

I have a tableview that requires a subview that's used to add content. The subview contains a UITextView that's used to enter text. Prior to 7.1 The following would happen:
The subview is glued to the bottom of the tableview via scrollViewDidScroll
When activated, the keyboard would show, the view animates up with the keyboard
When text is typed in, the textView would expand upwards if required, with the bottom of the textView remaining in place.
NOW after 7.1, the following behavior takes place:
The subview animates upwards with the keyboard fine
If the text forces a new line, instead of expanding, textViewDidEndEditing get's triggered and the keyboard dismisses.
No further editing is allowed in the textview, any edits makes the keyboard immediately dismiss.
Any suggestions on what changed with 7.1 that would make existing, working code break? Here is all the relevant code. I'll be happy to provide any additional details. I've been at this a while now and it's driving me mental.
tableViewController.m - The code that adds in the subview. The subview has it's own xib. The xib was created in IB. I stripped out the parts that pertain to other components.
- (void)viewDidLoad {
//Setup contentBar
if (self.contentBar == nil) {
//Add subView to View
NSArray *subviewArray = [[NSArray alloc] init];
subviewArray = [[NSBundle mainBundle] loadNibNamed:contentIdentifier owner:self options:nil];
self.contentBar = [subviewArray objectAtIndex:0];
[self.view addSubview:self.contentBar];
//Setup textView
UITextView *addContentTextView = (UITextView *)[self.contentBar viewWithTag:2];
addContentTextView.text = [NSString stringWithFormat:#"text (optional)"];
addContentTextView.delegate = self;
}
}
My textView delegates
#pragma mark - TextView Delegate
- (void)textViewDidEndEditing:(UITextView *)textView{
NSLog(#"textViewDidEndEditing:");
if ([textView.text isEqualToString:#""]) {
textView.text = #"text (optional)";
textView.textColor = [UIColor lightGrayColor]; //optional
}
[textView resignFirstResponder];
}
- (void)textViewDidBeginEditing:(UITextView *)textView {
NSLog(#"textViewDidBeginEditing:");
if ([textView.text isEqualToString:#"text (optional)"]) {
textView.text = #"";
textView.textColor = [UIColor blackColor]; //optional
}
[textView becomeFirstResponder];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
NSString *newText = [textView.text stringByReplacingCharactersInRange:range withString:text];
if ([newText length] > 0 || _image) {
_addContentButton.enabled = YES;
} else {
_addContentButton.enabled = NO;
}
if([text isEqualToString:[text stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]]) {
return YES;
} else {
NSLog(#"return pressed");
[textView resignFirstResponder];
[self addedContent:nil];
}
return YES;
}
- (void)textViewDidChange:(UITextView *)textView
{
NSLog(#"textViewDidChange");
[self sizeTextView];
}
- (void)sizeTextView
{
NSLog(#"sizeTextView");
UIImageView *barImage = (UIImageView *)[self.contentBar viewWithTag:87];
UITextView *textView = (UITextView *)[self.contentBar viewWithTag:2];
CGSize sizeThatShouldFitTheContent = [textView sizeThatFits:textView.frame.size];
CGRect newTextViewFrame = textView.frame;
newTextViewFrame.size.height = sizeThatShouldFitTheContent.height;
CGFloat adjustment = sizeThatShouldFitTheContent.height - textView.frame.size.height;
newTextViewFrame.origin.y = textView.frame.origin.y - adjustment;
textView.frame = newTextViewFrame;
CGRect newImageViewFrame = barImage.frame;
newImageViewFrame.size.height = barImage.frame.size.height + adjustment;
newImageViewFrame.origin.y = barImage.frame.origin.y - adjustment;
barImage.frame = newImageViewFrame;
}
If you want to see anything else, I'll be glad to post it.
I have solved this issue by implementing the following:
Rewrote my tableview controller as a standard ViewController, not a TableViewController
Added a tableview to the ViewController and a separate "contentWrapper" view.
The content wrapper consists of the example shown here: https://github.com/datwelk/RDRStickyKeyboardView
I'm still not sure what in iOS 7.1 caused this issue, but using the RDRStickyKeyboardView works great and solved all of my issues.
I've read that tableviews shouldn't be parents of other views, so this solution also works well for good coding practice.

Custom InputView for UISearchBar doesn't work after tap cancel button in iOS7

In my iOS App , i need to set custom inputView for UISearchBar in iOS7.
So i wrote following codes.
NSArray *searchBarSubViews = [[self.sBar.subviews objectAtIndex:0] subviews];
for(int i =0; i<[searchBarSubViews count]; i++) {
if([[searchBarSubViews objectAtIndex:i] isKindOfClass:[UITextField class]])
{
UITextField* search=(UITextField*)[searchBarSubViews objectAtIndex:i];
[search setFont:[UIFont fontWithName:#"CustomFont" size:15]];
search.delegate = self;
[search setInputView:self.customKeyboard];
[self.customKeyboard setTextView:search];
}
}
It is working fine. However when i type with my custom keyboard and tap Cancel Button to resignFirstResponder.
And i tap UISearchBar again, i can't type any text in UISearchBar , including native english keyboard.
And also Cancel Button is hiding and UISearchBar is not working anymore.
I don't know why is happening?
How can i solve it?
I tried your code and it's working fine with my app. In fact thanks and congratulations seem to be in order, because for one reason or other you seem to have solved a problem others on this site had to built more elaborate workarounds for.
In my app the keyboard changes according to the selected scope of the searchbar:
scope == 0 presents my CustomKeyboard
scope != 0 presents the usual iPhone Keyboard.
My implementation of your code looks like this:
-(UITextField *)textFieldFormSearchBar{
NSArray *searchBarSubViews = [[self.searchBar.subviews objectAtIndex:0] subviews];
for(int i =0; i<[searchBarSubViews count]; i++) {
if([[searchBarSubViews objectAtIndex:i] isKindOfClass:[UITextField class]])
{
UITextField* search=(UITextField*)[searchBarSubViews objectAtIndex:i];
return search;
}
}
return nil;
}
-(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar{
if (searchBar.selectedScopeButtonIndex==0) {
self.textFieldFormSearchBar.delegate = self;
self.textFieldFormSearchBar.inputView=self.customKeyboard;
self.customKeyboard.field=self.textFieldFormSearchBar;
}
else{
if (self.customKeyboard.superview!=nil) [self.customKeyboard removeFromSuperview];
self.textFieldFormSearchBar.delegate = self;
self.textFieldFormSearchBar.inputView=nil;
self.customKeyboard.field=nil;
}
return YES;
}
-(void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope{
if (selectedScope==0) {
self.textFieldFormSearchBar.delegate = self;
self.textFieldFormSearchBar.inputView=self.customKeyboard;
self.customKeyboard.field=self.textFieldFormSearchBar;
}
else{
if (self.customKeyboard.superview!=nil) [self.customKeyboard removeFromSuperview];
self.textFieldFormSearchBar.delegate = self;
self.textFieldFormSearchBar.inputView=nil;
self.customKeyboard.field=nil;
}
[self.textFieldFormSearchBar reloadInputViews];
}
-(BOOL)searchBarShouldEndEditing:(HDLSearchBar *)searchBar{
if (self.customKeyboard) {
[self.customKeyboard removeFromSuperview];
}
return [self.textFieldFormSearchBar resignFirstResponder];
}
Probably not the most efficient way to do it, but it does the trick. I hope you'll find something that helps you solve your problem.

Paging a TableView, but DataSource/Delegates not executing

I am having problems with getting the datasource or delegate methods to execute.
I am using a Paging View in my MainViewController and it pages just fine, but when it comes to the tableview is blank and when I put a breakpoint where the datasource methods are, it never gets called.
MainViewController to Load the View
if ((NSNull *)controller2 == [NSNull null])
{
if(page == 2)
{
controller2 = [[requestDetailThreeViewController alloc] initWithRequestNumber:[request objectForKey:#"RequestID"]];
[viewControllers replaceObjectAtIndex:page withObject:controller2];
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * 2;
frame.origin.y = 0;
controller2.view.frame = frame;
[scrollView addSubview:controller2.view];
}
}
The TableViewController (requestDetailThreeViewController)
- (void)viewDidLoad
{
[super viewDidLoad];
[History fullHistoryWithBlock:^(NSArray *netMessages, NSError *error) {
if (error) {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error", nil) message: [error localizedDescription] delegate:nil cancelButtonTitle:nil otherButtonTitles:NSLocalizedString(#"OK", nil), nil] show];
} else {
NSLog(#"Number of Historical Entries: %d", [netMessages count]);
self.historyFromNet = [NSMutableArray arrayWithArray:netMessages];
}
} forID:requestNum];
}
- (id) initWithRequestNumber:(NSString *)requestID
{
if (self = [super initWithNibName:#"View" bundle:nil])
{
self.requestNum = requestID;
}
return self;
}
(Apologize for the spacing on the 2nd block of code, hard time getting it into code mode.
It executes these two methods, but it doesn't execute the datasource methods I also have in the class.
In the XIB file I have the owner of the xib set to the requestDetailThreeViewController
The tableView is set to datasource/delegate and view
If I set the tableview to hidden in the ViewDidLoad, it does disappear.
I just can't get it to execute the methods to populate the table.
Update:
Some more information-
The View XIB only has a TableView in it, no controllers.
Thanks!
Alan
You are adding a child view controller so you will need to use the UIViewController containment methods.
Something like:
controller2 = [[requestDetailThreeViewController alloc] initWithRequestNumber:[request objectForKey:#"RequestID"]];
[viewControllers replaceObjectAtIndex:page withObject:controller2];
[self addChildViewController:controller2];
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * 2;
frame.origin.y = 0;
controller2.view.frame = frame;
[scrollView addSubview:controller2.view];
[controller didMoveToParentViewController:self];
}
Also consider using a UIPageViewController for a paging view rather than doing it manually via a scroll view
You can try to set self.tableView.delegate = self in -(void)viewDidLoad
that is
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
}