it-swarm.com.ru

UIButton не показывает подсветку при нажатии в iOS7

Я просмотрел тонну постов о похожих вещах, но ни одно из них не совпало и не решило эту проблему. Начиная с iOS 7, всякий раз, когда я добавляю UIButton к UITableViewCell или даже в нижний колонтитул, он работает "нормально", то есть получает целевое действие, но не показывает небольшую подсветку, которая обычно происходит при нажатии UIButton. Это заставляет пользовательский интерфейс выглядеть фанк, не показывая, что кнопка реагирует на прикосновение.

Я почти уверен, что это считается ошибкой в ​​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;
68
Eric

В этом табличном представлении вы просто добавляете это свойство.

tableview.delaysContentTouches = NO;

И добавьте cellForRowAtIndexPath после того, как вы инициируете ячейку, которую вы только что добавили ниже кода. Структура ячейки явно отличается в iOS 6 и iOS 7.
iOS 7 у нас есть один элемент управления UITableViewCellScrollView Между UITableViewCell и представлением содержимого.

for (id obj in cell.subviews)
{
    if ([NSStringFromClass([obj class]) isEqualToString:@"UITableViewCellScrollView"])
    {
        UIScrollView *scroll = (UIScrollView *) obj;
        scroll.delaysContentTouches = NO;
        break;
    }
}
87
subramani

Начиная с iOS 8, мы должны применять ту же технику к подпредставлениям UITableView (таблица содержит скрытое представление прокрутки UITableViewWrapperView). Больше нет необходимости повторять подпредставления UITableViewCell.

for (UIView *currentView in tableView.subviews) {
    if ([currentView isKindOfClass:[UIScrollView class]]) {
        ((UIScrollView *)currentView).delaysContentTouches = NO;
        break;
    }
}

Этот ответ должен быть связан с этим вопросом.

40
Roman B.

Я пытался добавить это к принятому ответу, но он так и не прошел. Это гораздо более безопасный способ отключения свойства delaysContentTouches для ячеек, поскольку он не ищет определенный класс, а скорее всего, что отвечает на селектор.

В клетке:

for (id obj in self.subviews) {
     if ([obj respondsToSelector:@selector(setDelaysContentTouches:)]) {
          [obj setDelaysContentTouches:NO];
     }
}

В TableView:

self.tableView.delaysContentTouches = NO;
27
Eric

Для решения, которое работает как в iOS7, так и в iOS8, создайте пользовательский подкласс UITableView и собственный подкласс UITableViewCell.

Используйте этот пример UITableView's 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's 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;
}
18
Quentin

Для решения этой проблемы я создал категорию 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 не является принудительным.

16
Raphaël Pinto

Вот ответ Романа Б в Swift 2:

for view in tableView.subviews {
    if view is UIScrollView {
        (view as? UIScrollView)!.delaysContentTouches = false
        break
    }
}
10
brandonscript
    - (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;
        }
    }
}

enter image description here

5
Gank

У меня были подобные проблемы с текстовой UIButton в UITableViewCell, не выделяющейся при прикосновении. Для меня это исправило изменение buttonType с Custom на System.

Установка delaysContentTouches в NO сделала трюк для UIButton только для изображения в том же UITableViewCell.

self.tableView.delaysContentTouches = NO;

 enter image description here

4
skg

Решение в 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 в ячейке, теперь выделяются мгновенно.

3
Chris

Это 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 }
}
3
Chris Harrison

Слегка измененная версия ответ Криса Харрисона . Swift 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 }
        }
    }
}
2
SoftDesigner

Я написал расширение категории на UITableViewCell, чтобы упростить решение этой проблемы. Он делает то же самое, что и принятый ответ, за исключением того, что я поднимаюсь вверх по иерархии представлений (в отличие от вниз) из UITableViewCell contentView.

Я рассмотрел полностью «автоматическое» решение, которое заставило бы все ячейки, добавленные к UITableView, установить их состояние delaysContentTouches в соответствии с состоянием UITableView's delaysContentTouches. Чтобы это работало, мне нужно было бы либо прокрутить 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
0
TomSwift

Так как objc является динамическим, а scrollView является единственным классом, который отвечает на delaysContentTouches, это должно работать как для ios 7, так и для 8 (поместите его где-то в начале вашего tableViewController, например awakeFromNib):

for (id view in self.tableView.subviews)
    {
        if ([view respondsToSelector:@selector(delaysContentTouches)]) {
            UIScrollView *scrollView = (UIScrollView *)view;
            scrollView.delaysContentTouches = NO;
            break;
        }
}

Возможно, вам также придется отключить «delaysContentTouches» в вашей раскадровке или перо, выбрав таблицу внутри вашего viewController. Кстати, это может не сработать на ios 7, если вы используете tableView внутри viewController, по крайней мере, я не смог заставить его работать.

0
smileBot

Принятый ответ не сработал для меня.

Наконец, я добавляю нижний код в категорию uibutton (/ подкласс), и он работает на сто процентов.

- (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];

}
0
rotoava

В Swift 3 это расширение UIView можно использовать на UITableViewCell. Предпочтительно в методе cellForRowAt.

func removeTouchDelayForSubviews() {
    for subview in subviews {
        if let scrollView = subview as? UIScrollView {
            scrollView.delaysContentTouches = false
        } else {
            subview.removeTouchDelayForSubviews()
        }
    }
}
0
Sunkas

Это решение для меня не работает, я исправил создал подкласс TableView и реализовал эти два метода

- (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;
}
0
Serluca

Решение в Swift для iOS 7 и 8:

Сначала я написал полезную функцию:

class func classNameAsString(obj: AnyObject) -> String {
    return _stdlib_getDemangledTypeName(obj).componentsSeparatedByString(".").last!
}

затем я подкласс UITableView и реализовать это:

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
        }
    }
}

Я также подкласс UITableViewCell и реализовать это:

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 (кодер :) будет работать. Пожалуйста, поместите точку отладки в ваши функции инициализации, чтобы узнать, какая функция инициализации будет запускаться, а затем используйте приведенный выше код, чтобы заставить ее работать. Надеюсь помочь кому-нибудь.

0
grandagile