iOS7에서 탭시 UIButton이 강조 표시되지 않음
나는 비슷한 것에 대한 많은 게시물을 보았지만 그 중 어느 것도이 문제와 일치하거나 수정하지 않았습니다. iOS 7부터 UIButton
a UITableViewCell
또는 바닥 글 에 a 를 추가 할 때마다 "괜찮아"작동합니다. 즉, 대상 작업을 수신하지만 일반적으로을 탭할 때 발생하는 작은 하이라이트는 표시되지 않습니다 UIButton
. 버튼이 터치에 반응하지 않고 UI가 펑키하게 보입니다.
나는 이것이 iOS7의 버그로 간주되지만 누군가가 해결책을 찾거나 내가 찾을 수 있도록 도울 수 있다고 확신합니다. :)
편집 : 버튼을 길게 누르면 강조 표시되지만 표준보기에 추가 된 경우처럼 빠른 탭은 아닙니다.
암호:
버튼 만들기 :
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.titleLabel.font = [UIFont systemFontOfSize:14];
button.titleLabel.textColor = [UIColor blueColor];
[button setTitle:@"Testing" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchDown];
button.frame = CGRectMake(0, 0, self.view.frame.size.width/2, 40);
내가 테스트 한 것 :
// 제스처 인식기 UITableView
가 방해가되는 경우 제거 합니다.
for (UIGestureRecognizer *recognizer in self.tableView.gestureRecognizers) {
recognizer.enabled = NO;
}
// 셀에서 제스처 제거
for (UIGestureRecognizer *recognizer in self.contentView.gestureRecognizers) {
recognizer.enabled = NO;
}
// 이것은 약간의 가벼운 터치를 보여 주지만 원하는 모양이 아닙니다.
button.showsTouchWhenHighlighted = YES;
해당 tableview에서이 속성을 추가하기 만하면됩니다.
tableview.delaysContentTouches = NO;
그리고 코드 아래에 추가 한 셀을 시작한 후 cellForRowAtIndexPath를 추가하십시오. 셀의 구조는 iOS 6과 iOS 7에서 분명히 다릅니다.
iOS 7에서는 UITableViewCell과 콘텐츠보기 사이에 하나의 컨트롤 UITableViewCellScrollView가 있습니다.
for (id obj in cell.subviews)
{
if ([NSStringFromClass([obj class]) isEqualToString:@"UITableViewCellScrollView"])
{
UIScrollView *scroll = (UIScrollView *) obj;
scroll.delaysContentTouches = NO;
break;
}
}
iOS 8부터는 UITableView 하위보기에 동일한 기술을 적용해야합니다 (테이블에는 숨겨진 UITableViewWrapperView 스크롤보기가 포함됨). 더 이상 UITableViewCell 서브 뷰를 반복 할 필요가 없습니다.
for (UIView *currentView in tableView.subviews) {
if ([currentView isKindOfClass:[UIScrollView class]]) {
((UIScrollView *)currentView).delaysContentTouches = NO;
break;
}
}
이 답변 은이 질문과 연결되어야합니다.
나는 이것을 받아 들인 대답에 추가하려고했지만 결코 통과하지 못했습니다. 이것은 특정 클래스가 아니라 선택자에 응답하는 모든 것을 찾기 때문에 셀 delaysContentTouches 속성을 끄는 훨씬 안전한 방법입니다.
셀에서 :
for (id obj in self.subviews) {
if ([obj respondsToSelector:@selector(setDelaysContentTouches:)]) {
[obj setDelaysContentTouches:NO];
}
}
TableView에서 :
self.tableView.delaysContentTouches = NO;
iOS7 및 iOS8 모두에서 작동하는 솔루션의 경우 사용자 지정 UITableView
하위 클래스와 사용자 지정 UITableViewCell
하위 클래스를 만듭니다.
이 샘플 사용 UITableView
의를initWithFrame:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// iterate over all the UITableView's subviews
for (id view in self.subviews)
{
// looking for a UITableViewWrapperView
if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewWrapperView"])
{
// this test is necessary for safety and because a "UITableViewWrapperView" is NOT a UIScrollView in iOS7
if([view isKindOfClass:[UIScrollView class]])
{
// turn OFF delaysContentTouches in the hidden subview
UIScrollView *scroll = (UIScrollView *) view;
scroll.delaysContentTouches = NO;
}
break;
}
}
}
return self;
}
이 샘플 사용 UITableViewCell
의를initWithStyle:reuseIdentifier:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// iterate over all the UITableViewCell's subviews
for (id view in self.subviews)
{
// looking for a UITableViewCellScrollView
if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewCellScrollView"])
{
// this test is here for safety only, also there is no UITableViewCellScrollView in iOS8
if([view isKindOfClass:[UIScrollView class]])
{
// turn OFF delaysContentTouches in the hidden subview
UIScrollView *scroll = (UIScrollView *) view;
scroll.delaysContentTouches = NO;
}
break;
}
}
}
return self;
}
문제를 해결하기 위해 내가 한 일은 다음 코드를 사용하는 UIButton의 범주였습니다.
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
[NSOperationQueue.mainQueue addOperationWithBlock:^{ self.highlighted = YES; }];
}
- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
[self performSelector:@selector(setDefault) withObject:nil afterDelay:0.1];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
[self performSelector:@selector(setDefault) withObject:nil afterDelay:0.1];
}
- (void)setDefault
{
[NSOperationQueue.mainQueue addOperationWithBlock:^{ self.highlighted = NO; }];
}
UITableViewCell에서 버튼을 누르면 버튼이 올바르게 반응하고 내 UITableView delaysContentTouches
는 강제 로 작동 하지 않으므로 정상적으로 작동합니다 .
다음은 Swift 2에서 Roman B의 답변입니다.
for view in tableView.subviews {
if view is UIScrollView {
(view as? UIScrollView)!.delaysContentTouches = false
break
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
for (id view in self.tableView.subviews)
{
// looking for a UITableViewWrapperView
if ([NSStringFromClass([view class]) isEqualToString:@"UITableViewWrapperView"])
{
// this test is necessary for safety and because a "UITableViewWrapperView" is NOT a UIScrollView in iOS7
if([view isKindOfClass:[UIScrollView class]])
{
// turn OFF delaysContentTouches in the hidden subview
UIScrollView *scroll = (UIScrollView *) view;
scroll.delaysContentTouches = NO;
}
break;
}
}
}
이것은 위의 Raphaël Pinto의 답변의 Swift 버전입니다. 그를 너무 찬성하는 것을 잊지 마세요 :)
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
super.touchesBegan(touches, withEvent: event)
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in self.highlighted = true }
}
override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesCancelled(touches, withEvent: event)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue()) {
self.setDefault()
}
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
super.touchesEnded(touches, withEvent: event)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue()) {
self.setDefault()
}
}
func setDefault() {
NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in self.highlighted = false }
}
터치시 강조 표시되지 않는 UITableViewCell의 텍스트 전용 UIButton과 유사한 문제가 발생했습니다. 나를 위해 수정 한 것은 buttonType을 Custom에서 System으로 다시 변경하는 것입니다.
delaysContentTouches를 NO로 설정하면 동일한 UITableViewCell에서 이미지 전용 UIButton에 대한 트릭이 수행되었습니다.
self.tableView.delaysContentTouches = NO;
Swift의 솔루션, iOS8 전용 (iOS7의 각 셀에 대한 추가 작업 필요) :
//
// NoDelayTableView.swift
// DivineBiblePhone
//
// Created by Chris Hulbert on 30/03/2015.
// Copyright (c) 2015 Chris Hulbert. All rights reserved.
//
// This solves the delayed-tap issue on buttons on cells.
import UIKit
class NoDelayTableView: UITableView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
delaysContentTouches = false
// This solves the iOS8 delayed-tap issue.
// http://stackoverflow.com/questions/19256996/uibutton-not-showing-highlight-on-tap-in-ios7
for view in subviews {
if let scroll = view as? UIScrollView {
scroll.delaysContentTouches = false
}
}
}
override func touchesShouldCancelInContentView(view: UIView!) -> Bool {
// So that if you tap and drag, it cancels the tap.
return true
}
}
사용하려면 NoDelayTableView
스토리 보드에서 클래스를 로 변경 하기 만하면됩니다.
iOS8에서 셀의 contentView 안에있는 버튼이 이제 즉시 강조 표시됨을 확인할 수 있습니다.
Chris Harrison의 답변을 약간 수정했습니다 . 스위프트 2.3 :
class HighlightButton: UIButton {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesBegan(touches, withEvent: event)
NSOperationQueue.mainQueue().addOperationWithBlock { _ in self.highlighted = true }
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
super.touchesCancelled(touches, withEvent: event)
setDefault()
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesEnded(touches, withEvent: event)
setDefault()
}
private func setDefault() {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
NSOperationQueue.mainQueue().addOperationWithBlock { _ in self.highlighted = false }
}
}
}
받아 들인 대답은 나를 위해 일부 "탭"에서 작동하지 않았습니다.
마지막으로 uibutton 범주 (/ subclass)에 벨로우즈 코드를 추가하면 100 % 작동합니다.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.backgroundColor = [UIColor greenColor];
[UIView animateWithDuration:0.05 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.backgroundColor = [UIColor clearColor];
} completion:^(BOOL finished)
{
}];
[super touchesBegan:touches withEvent:event];
}
UITableViewCell
이 문제를 쉽게 해결할 수 있도록 카테고리 확장을 작성했습니다 . 에서 뷰 계층 구조 위로 올라가는 것을 제외하고는 기본적으로 허용되는 답변과 동일합니다 UITableViewCell contentView
.
나는에 추가 된 모든 세포를 만들 수있는 완전히 "자동으로 자료"솔루션으로 간주 UITableView
세트 자신의 delaysContentTouches
소유에 맞게 상태 UITableView
의 delaysContentTouches
상태를. 이 작업을 수행하려면 swizzle UITableView
또는 개발자에게 UITableView
하위 클래스 를 사용해야합니다 . 어느 쪽도 요구하고 싶지 않은이 솔루션은 더 간단하고 유연하다고 생각합니다.
카테고리 확장 및 샘플 하네스 :
https://github.com/TomSwift/UITableViewCell-TS_delaysContentTouches
사용하기 매우 간단합니다.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// using static cells from storyboard...
UITableViewCell* cell = [super tableView: tableView cellForRowAtIndexPath: indexPath];
cell.ts_delaysContentTouches = NO;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
카테고리에 대한 코드는 다음과 같습니다.
@interface UITableViewCell (TS_delaysContentTouches)
@property (nonatomic, assign) BOOL ts_delaysContentTouches;
@end
@implementation UITableViewCell (TS_delaysContentTouches)
- (UIScrollView*) ts_scrollView
{
id sv = self.contentView.superview;
while ( ![sv isKindOfClass: [UIScrollView class]] && sv != self )
{
sv = [sv superview];
}
return sv == self ? nil : sv;
}
- (void) setTs_delaysContentTouches:(BOOL)delaysContentTouches
{
[self willChangeValueForKey: @"ts_delaysContentTouches"];
[[self ts_scrollView] setDelaysContentTouches: delaysContentTouches];
[self didChangeValueForKey: @"ts_delaysContentTouches"];
}
- (BOOL) ts_delaysContentTouches
{
return [[self ts_scrollView] delaysContentTouches];
}
@end
Since objc is dynamic, and scrollView is the only class that responds to delaysContentTouches, this should work for both ios 7 and 8 (put it somewhere early in your tableViewController, like awakeFromNib):
for (id view in self.tableView.subviews)
{
if ([view respondsToSelector:@selector(delaysContentTouches)]) {
UIScrollView *scrollView = (UIScrollView *)view;
scrollView.delaysContentTouches = NO;
break;
}
}
You may also have to turn off "delaysContentTouches" in your storyboard or nib by selecting the table inside your viewController. BTW, this might not work on ios 7 if you're using a tableView inside a viewController, at least I couldn't get it to work.
That solution for me doesn't work, I fixed subclassing TableView and implementing these two methods
- (instancetype)initWithCoder:(NSCoder *)coder{
self = [super initWithCoder:coder];
if (self) {
for (id obj in self.subviews) {
if ([obj respondsToSelector:@selector(setDelaysContentTouches:)]){
[obj performSelector:@selector(setDelaysContentTouches:) withObject:NO];
}
}
}
return self;
}
- (BOOL)delaysContentTouches{
return NO;
}
Solution in Swift for iOS 7 and 8:
First I wrote a utility function:
class func classNameAsString(obj: AnyObject) -> String {
return _stdlib_getDemangledTypeName(obj).componentsSeparatedByString(".").last!
}
then I subclass UITableView and implement this:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
for view in self.subviews {
if (Utility.classNameAsString(view) == "UITableViewWrapperView") {
if view.isKindOfClass(UIScrollView) {
var scroll = (view as UIScrollView)
scroll.delaysContentTouches = false
}
break
}
}
}
I also subclass UITableViewCell and implement this:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
for view in self.subviews {
if (Utility.classNameAsString(view) == "UITableViewCellScrollView") {
if view.isKindOfClass(UIScrollView) {
var scroll = (view as UIScrollView)
scroll.delaysContentTouches = false
}
}
}
}
제 경우에는 init (coder :)가 실행됩니다. init 함수에 디버그 지점을 넣어 어떤 초기화 함수가 실행되는지 확인한 다음 위의 코드를 사용하여 작동하도록하십시오. 누군가를 돕고 싶습니다.
Swift 3에서는이 UIView 확장을 UITableViewCell에서 사용할 수 있습니다. 바람직하게는 cellForRowAt
방법에서.
func removeTouchDelayForSubviews() {
for subview in subviews {
if let scrollView = subview as? UIScrollView {
scrollView.delaysContentTouches = false
} else {
subview.removeTouchDelayForSubviews()
}
}
}
참고 URL : https://stackoverflow.com/questions/19256996/uibutton-not-showing-highlight-on-tap-in-ios7
'programing' 카테고리의 다른 글
“완전한 바이너리 트리”,“엄격한 바이너리 트리”,“전체 바이너리 트리”의 차이점은 무엇입니까? (0) | 2020.11.06 |
---|---|
IntelliJ IDEA에서 라이브러리 (android-support-v7-appcompat)를 어떻게 추가합니까? (0) | 2020.11.06 |
github wiki 페이지에서 "spoiler"텍스트를 만드는 방법은 무엇입니까? (0) | 2020.11.06 |
WinForms에서 도킹 순서를 제어하는 방법 (0) | 2020.11.06 |
Eclipse에서 메서드를 빠르게 구현 / 재정의하는 방법은 무엇입니까? (0) | 2020.11.06 |