It is estimated that many code friends have encountered this situation:
UIButton cannot immediately respond to touchdown events in some cases, in other words, you will never see the highlighted state of this button when you click the button quickly .
and you'll find that when this happens, these buttons are on Uiscrollview (UITableView).
for this I used an afternoon to check the post-finishing, and got the perfect solution.
before introducing the solution, we must first popularize some facts to help you understand:
Uiscrollview:
1. Propertiesdelayscontenttouches, the Boolean type, and the default value is yes. When the value is yes, the Uiscrollview will delay 150ms when the gesture is received to determine whether the gesture is capable of uiscrollview sliding events, or no, Uiscrollview will immediately distribute the received gesture to the child view.
(Note: Just setting this is not enough, you will find that if you want to drag the ScrollView and the starting point falls on other gesture-aware views, it will not drag)
2. Methods -(BOOL) Touchesshouldcancelincontentview: (UIView *) View , the overloading of this method is the key to helping us to solve the problem perfectly, deciding whether the gesture is canceled on the view and triggered when the ScrollView is dragged. When no is returned, the drag gesture is left on the ScrollView and returns Yes to the view. (If view is Uicontrol, return Yes by default)
UITableView:
It must be said that UITableView (including UITableViewCell) in IOS7 and IOS8The view structure is different, and there are a lot of views that we never touch when we encode, but we can subviews it one by one by Debug. This is related to the deep level of the pit of our problem.
There are n+1 Uiscrollview in Ios7:uitableview, one is UITableView itself, and the other n exists in Between the UITableViewCell and the contentview of the cell , the class name is Uitableviewcellscrollview, Live soon, only exists in iOS7, and has been removed in iOS8.
There are 2 uiscrollview in Ios8:uitableview, one is UITableView itself, the other one exists between UITableView and UITableViewCell , The class name is Uitableviewwrapperview. It is important to note that Uitableviewwrapperview is not a uiscrollview in iOS7.
Science knowledge is complete, then we have the following solutions to the problem:
1. UIButton all the parent views that belong to Uiscrollviewdelayscontenttouchesproperty is set to No.
2. Inherit Uiscrollview or UITableView, and rewrite- (BOOL) Touchesshouldcancelincontentview: (UIView*) Viewmethod so that it responds to the drag method.
The following is the reference code:
for simplicity I write the subclass of two classes in the same file
NoDelayButtonScrollView.h:
#import <UIKit/UIKit.h> @interface Nodelaybuttonscrollview:uiscrollview@end@interface Nodelaybuttontableview : Uitableview@end
NODELAYBUTTONSCROLLVIEW.M (1):
#import "NoDelayButtonScrollView.h" @implementation nodelaybuttonscrollview-(ID) Initwithcoder: (Nscoder *) adecoder{ Self = [Super Initwithcoder:adecoder]; if (self) { self.delayscontenttouches = NO; } return self;} -(BOOL) Touchesshouldcancelincontentview: (UIView *) view{ if ([View Iskindofclass:[uibutton class]]) { return YES; } return [Super Touchesshouldcancelincontentview:view];} @end
NODELAYBUTTONSCROLLVIEW.M (2):
@implementation nodelaybuttontableview-(ID) Initwithcoder: (Nscoder *) adecoder{self = [super Initwithcoder:adecoder]; if (self) {self.delayscontenttouches = NO; Iterate over all the UITableView's subviews for (ID view on self.subviews) {//looking for a Uitableviewwrapperview if ([Nsstringfromclass ([view class]) isequaltostring:@ "Uitableviewwrapperview"]) {//This test was necessary for safety and because a ' uitableviewwrapperview ' is ' not ' a uiscrollview in IOS7 if ([View Iskindofclass:[uiscrollview class]]) {//Turn OFF Delaysco Ntenttouches in the hidden subview uiscrollview *scroll = (Uiscrollview *) view; Scroll.delayscontenttouches = NO; } break; }}} return self;} -(BOOL) Touchesshouldcancelincontentview: (UIView *) view{if ([View Iskindofclass:[uibutton class]]) {return YES; } return [Super Touchesshouldcancelincontentview:view];} @end
The above Uiscrollview and UITableView inheritance, rewrite Initwithcoder: Method can guarantee the use of nib file can also take effect
ScrollView and TableView, which are written using these two classes, can quickly respond to the touchdown event of a child button and display a highlighted
However, the above code still does not solve the iOS7 uitableview the child button highlighting delay problem.
The following code can be added to resolve:
for (id obj in cell.subviews) { if ([Nsstringfromclass ([obj class]) isequaltostring:@ "Uitableviewcellscrollview"]) { Uiscrollview *scroll = (Uiscrollview *) obj; Scroll.delayscontenttouches = NO; break; }}
This code can be added to the custom UITableViewCell Initwithcoder: Method, also can be placed in Uitableviewdelegate Cellforrowatindexpath: method to set the Uitableviewcellscrollview in the corresponding cell.
above, is all the way to help you solve the button delay highlighting problem.
IOS7/8 UIButton Highlight State delay problem full solution