I have pickerview in my view controller. I am displaying it by adding into subview and then changing frame of subview. When my pickerview displayed I have one button behind it. When I click on those area after dispalying pickerview still that button action is called. How to set pickerview proper?
U subclass the PickerView like below will help u to fix this issue.
//
// WPCustomPickerView.h
// test
//
// Created by VASANTH K on 08/01/14.
//
//
#import <UIKit/UIKit.h>
#interface WPCustomPickerView : UIDatePicker
#end
implementation file
//
// WPCustomPickerView.m
// test
//
// Created by VASANTH K on 08/01/14.
//
//
#import "WPCustomPickerView.h"
#implementation WPCustomPickerView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
id hitview=[super hitTest:point withEvent:event];
if(!hitview)
{
if(point.y<=self.frame.size.height&&point.y>=0)
return self;
}
return hitview;
}
#end
Here i override the hitTest to make UIPickerView response for the user interaction. This is the way how apple make main picker view transparent for user touch by return nil when user directly touch on the main view instead of picker content.
Related
the buttons in my iOS8+ app should react by painting an outline around the buttons as long as the user presses the finger on it. The goal is to encapsulate this behaviour into the OutlineButton class (cp. below class hierarchy). When releasing the finger, the app should execute the defined action (mostly perform a segue to another view controller). Here's my current class hierarchy for this purpose:
- UIButton
|_ OutlineButton
|_ FlipButton
The FlipButton class perform some fancy flip effect and additionally I have a category on UIView for drop shadow, rounded corners and the outlines.
Currently I have the following additional class:
#import <UIKit/UIKit.h>
#interface TouchDownGestureRecognizer : UIGestureRecognizer
#end
... and the corresponding implementation:
#import "UIView+Extension.h"
#import "TouchDownGestureRecognizer.h"
#implementation TouchDownGestureRecognizer
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view showOutline]; // this is a function in the UIView category (cp. next code section)
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view hideOutline]; // this is a function in the UIView category (cp. next code section)
}
#end
... this is the relevant snippet of the UIView+Extension.m category for painting the outline on the buttons:
- (void)showOutline {
self.layer.borderColor = [UIColor whiteColor].CGColor;
self.layer.borderWidth = 1.0f;
}
- (void)hideOutline {
self.layer.borderColor = [UIColor clearColor].CGColor;
}
... and in the OutlineButton.m file I have the following so far:
#import "OutlineButton.h"
#implementation OutlineButton
- (id)initWithCoder:(NSCoder*)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self addGestureRecognizer:[[TouchDownGestureRecognizer alloc] init]];
}
return self;
}
#end
Visually, this works fine, as soon as a button is touched an outline is drawn and hidden again as soon as the finger is released. But the IBAction's and segues that are connected to these buttons via storyboard are performed after a huge delay (around 2 seconds) if at all. The actions are also performed multiple times if the button was pressed more than once (...after a long delay). Really strange behaviour...
Somebody any ideas how to solve this issue?
SOLUTION (based on matt's answer, thanks):
#import "OutlineButton.h"
#import "UIView+Extension.h"
#implementation OutlineButton
- (id)initWithCoder:(NSCoder*)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self addTarget:self action:#selector(showOutline) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:#selector(hideOutline) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
}
return self;
}
#end
the buttons in my iOS8+ app should react by painting an outline around the buttons as long as the user presses the finger on it
The most framework-compliant way to implement that is to assign to the button, for the highlighted state, an image that has the outline. It is while the button is being pressed that it is being highlighted; therefore, it is while the button is being pressed that it will display the outline.
I had custom view set as background view to UITableview.Which is utilise to perform some actions when tableview is blank.
I had some buttons on view & a action is associated with each button
For iOS < 7 , action are called properly on buttons inside background view
But for iOS > 7 , actions set on buttons in backgroundView arent getting called.This seems interaction is disabled on backgroundView
Is this an issue with iOS 7.Anyone else face same issue?
There is a UITableViewWrapperView view sitting in front of the background view intercepting interactions. Can you not just use the table's tableHeaderView property instead?
Firstly this is a bad approach to add touchable items to tableView background view.
Secondly I'm not sure my fix will work for your case.
Try to implement following methods in your BackgroundView class:
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* hitView = [super hitTest:point withEvent:event];
if (hitView != nil)
{
[self.superview bringSubviewToFront:self];
}
return hitView;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
CGRect rect = self.bounds;
BOOL isInside = CGRectContainsPoint(rect, point);
if(!isInside)
{
for (UIView *view in self.subviews)
{
isInside = CGRectContainsPoint(view.frame, point);
if(isInside)
break;
}
}
return isInside;
}
By overriding those methods you are making all subviews of backgroundView as well as backgroundView itself touch sensitive.
Cheers!
UPDATE:
Sorry, this will not work. BackgroundView is located behind view with cells itself, so it will not receive touch.
As specified in my comment, this is a known issue in iOS7, see the radar (http://openradar.appspot.com/14707569).
But my solution or workaround to this was to implement a 'proxy' view on top of the table which offers a protocol to forward the hitTest to a Delegate who implements that protocol.
EventFixBackrgoundView.h
#protocol EventFixBackrgoundViewDelegate <NSObject>
- (UIView *)eventFixHitTest:(CGPoint)point withEvent:(UIEvent *)event;
#end
#interface EventFixBackrgoundView:UIView
#property (nonatomic, weak) id <EventFixBackrgoundViewDelegate> delegate;
#end
EventFixBackrgoundView.m
#import "EventFixBackrgoundView.h"
#implementation EventFixBackrgoundView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (self.delegate && [self.delegate respondsToSelector:#selector(eventFixHitTest:withEvent:)])
{
return [self.delegate eventFixHitTest:point withEvent:event];
}
return [super hitTest:point withEvent:event];
}
#end
I have an UITextField to search the word that typed there. I set the returnKeyType as UIReturnKeySearch. But I couldn't figure how to bind a function that I created, to the "Search" button at the keyboard.
self.searchWord.returnKeyType=UIReturnKeySearch;
How can I do that? Thanks.
If I'm understanding correctly you need to implement the UITextfield delegate:
In your header file
#interface MyViewController : UIViewController <UITextFieldDelegate>
in viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
self.searchTextField.delegate = self;
}
Then implement the delegate method.
- (BOOL)textFieldShouldReturn:(UITextField *)aTextfield {
// Only do search when user hits return key on the search textfield.
if ([aTextfield isEqual:self.searchTextField]) {
// Method that does the search.
[self doSearch];
}
return YES;
}
Problem: Using NIAttributedLabel in UITableViewCell with Action(tap, navigate)
adding a link in label
adding label to cell
adding cell to model with action tap
Here is the problem, if I touch the label on the link, it actually does not show the link but act the tap action.
But if I add a UIButton in UITableViewCell in the same way, the action does not happen and the button response when I touch on the button.
So I guess it is the problem with the label.
How can I solve it?
I figured out this finally;
adding function to file NIAttributedLabel.m
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// never return self. always return the result of [super hitTest..].
// this takes userInteraction state, enabled, alpha values etc. into account
UIView *hitResult = [super hitTest:point withEvent:event];
// don't check for links if the event was handled by one of the subviews
if (hitResult != self) {
return hitResult;
}
if (self.explicitLinkLocations || self.detectedlinkLocations) {
BOOL didHitLink = ([self linkAtPoint:point] != nil);
if (!didHitLink) {
// not catch the touch if it didn't hit a link
return nil;
}
}
return hitResult;
}
remove all [super touch XXXX] functions in all touchXXX;
then, it works!
I would like to know if a cell is being dragged (via the grip on the right side when a UITableView is in editing mode). I would like to change the background while it is in that state.
There is no callback unfortunately, but since the default behaviour is to adjust the 'alpha' value of the UITableViewCell you can check for that in '- (void)layoutSubview' of your UITableViewCell subclass.
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.alpha < 0.99) {
// we are most likely being dragged
} else {
// restore for not being dragged
}
}
Note that this is a bit of a hack. I noticed that this doesn't work when the table view's separatorStyle is set to 'UITableViewCellSeparatorStyleNone'.
I don't know if this is possible in the framework. But if it's not, you can try to override touchedMoved method in an UITableViewCell subclass?
You might then be able to also retrieve the state of your tableView (editing or not) in your UItableViewCell's custom subclass.
It is possible, yes!
In ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIScrollViewDelegate>
{
IBOutlet UITableView * myTable;
IBOutlet UIScrollView * myScroll;
}
In ViewController.m
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
myScroll = myTable;
myScroll.delegate = self;
}
#pragma Mark UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(#"%f",scrollView.contentOffset.y);
}
That is it.
It's possible yes! But you have to keep track on the states yourself in the view controller. Define a member
BOOL tableDrag = NO;
In the method
scrollViewWillBeginDragging
you set tableDrag = YES; And in the method
scrollViewDidEndDragging
you set tableDraw = NO;
Now in the scrollViewDidScroll delegate method you can set the background.
If you have several scrollers then tag the scroll view so that you know which one is dragging.
Hope it helps!