Кнопка отмены iPad (а-ля Keynote и другие приложения) - PullRequest
4 голосов
/ 21 марта 2012

В Keynote (и других приложениях) я заметил, что «стандартный» интерфейс выполнения отмены / повтора заключается в предоставлении кнопки отмены на панели инструментов.

Нажатие кнопки (всегда включеноОтменяет недавнюю операцию.(Если нет недавней операции по отмене, появится меню «Отменить / Повторить».)

Длительное нажатие на кнопку «Отменить» открывает меню «Отменить / Повторить».

Я искал методыреализуя это, и лучший ответ, который я нашел до сих пор, находится по ссылке .

Интересно, кто-нибудь знает более простой способ?

Спасибо!

Ответы [ 4 ]

4 голосов
/ 23 мая 2012

После рассмотрения всех методов и обсуждения с друзьями ниже приводится решение, которое я использовал, для UIBarButtonItem, который отвечает как на нажатие, так и на длительное нажатие (TapOrLongPressBarButtonItem).

Он основан на следующих принципах:

  1. Подкласс UIBarButtonItem
  2. Использование настраиваемого представления (так что обрабатывать длинное нажатие очень просто - поскольку у нашего настраиваемого представления нет проблем с реагированием на обработчик жестов при длинном нажатии ...)

... Пока - этот подход был в другом SO-потоке - и мне не понравился этот подход, так как я не мог найти и легкоДостаточно способа сделать пользовательский вид похожим на кнопку панели навигации на iPad ... Так ...

Использование UIGlossyButton от Water Lou (спасибо, вода!).Это использование заключено в подкласс ...

Полученный код выглядит следующим образом:

@protocol TapOrPressButtonDelegate;
@interface TapOrPressBarButtonItem : UIBarButtonItem {  
    UIGlossyButton* _tapOrPressButton;
    __weak id<TapOrPressButtonDelegate> _delegate;
}
- (id)initWithTitle:(NSString*)title andDelegate:(id<TapOrPressButtonDelegate>)delegate;
@end

@protocol TapOrPressButtonDelegate<NSObject>
- (void)buttonTapped:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem;
- (void)buttonLongPressed:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem;
@end

@implementation TapOrPressBarButtonItem
- (void)buttonLongPressed:(UILongPressGestureRecognizer*)gesture {
    if (gesture.state != UIGestureRecognizerStateBegan)
        return;
    if([_delegate respondsToSelector:@selector(buttonLongPressed:withBarButtonItem:)]) {
        [_delegate buttonLongPressed:_tapOrPressButton withBarButtonItem:self];
    }
}

- (void)buttonTapped:(id)sender {
    if (sender != _tapOrPressButton) {
        return;
    }

    if([_delegate respondsToSelector:@selector(buttonTapped:withBarButtonItem:)]) {
        [_delegate buttonTapped:_tapOrPressButton withBarButtonItem:self];
    }   
}

- (id)initWithTitle:(NSString*)title andDelegate:(id<TapOrPressButtonDelegate>)delegate {
    if (self = [super init]) {
        // Store delegate reference
        _delegate = delegate;

        // Create the customm button that will have the iPad-nav-bar-default appearance 
        _tapOrPressButton = [UIGlossyButton buttonWithType:UIButtonTypeCustom];
        [_tapOrPressButton setTitle:title forState:UIControlStateNormal];
        [_tapOrPressButton setNavigationButtonWithColor:[UIColor colorWithRed:123.0/255 green:130.0/255 blue:139.0/255 alpha:1.0]];
        // Calculate width...
        CGSize labelSize = CGSizeMake(1000, 30);
        labelSize = [title sizeWithFont:_tapOrPressButton.titleLabel.font constrainedToSize:labelSize lineBreakMode:UILineBreakModeMiddleTruncation];
        _tapOrPressButton.frame = CGRectMake(0, 0, labelSize.width+20, 30);

        // Add a handler for a tap
        [_tapOrPressButton addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
        // Add a handler for a long-press
        UILongPressGestureRecognizer* buttonLongPress_ = [[UILongPressGestureRecognizer alloc] initWithTarget:self
                                                                                                       action:@selector(buttonLongPressed:)];
        [_tapOrPressButton addGestureRecognizer:buttonLongPress_];

        // Set this button as the custom view of the bar item...
        self.customView = _tapOrPressButton;
    }
    return self;
}

// Safe guards...
- (id)initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action {
    NSLog(@"%s not supported!", __FUNCTION__);
    return nil;
}

- (id)initWithImage:(UIImage *)image landscapeImagePhone:(UIImage *)landscapeImagePhone style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action {
    NSLog(@"%s not supported!", __FUNCTION__);
    return nil;
}

- (id)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action {
    NSLog(@"%s not supported!", __FUNCTION__);
    return nil;
}
- (id)initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:(id)target action:(SEL)action {
    NSLog(@"%s not supported!", __FUNCTION__);
    return nil;
}

- (id)initWithCustomView:(UIView *)customView {
    NSLog(@"%s not supported!", __FUNCTION__);
    return nil;
}

@end

И все, что вам нужно сделать, это:

1.Это выглядит следующим образом:

TapOrPressBarButtonItem* undoMenuButton = [[TapOrPressBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Undo", @"Undo Menu Title") andDelegate:self];

2.Подключите кнопку к панели навигации:

[self.navigationItem setLeftBarButtonItem:undoMenuButton animated:NO];

3.Реализуйте протокол TapOrPressButtonDelegate, и все готово ...

-(void)buttonTapped:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem {
    [self menuItemUndo:barButtonItem];
}

-(void)buttonLongPressed:(UIButton*)button withBarButtonItem:(UIBarButtonItem*)barButtonItem {
    [self undoMenuClicked:barButtonItem];
}

Надеюсь, это поможет кому-то еще ...

0 голосов
/ 11 мая 2012

Я считаю, что ключ на самом деле находится в самом UINavigationBar. В отличие от UIB-кнопок или других обычных объектов отслеживания касаний, я подозреваю, что UIBarItems не обрабатывают свои собственные касания. Они не наследуют методы UIResponder или UIControl. Однако UINavigationBar, конечно, делает. И я лично добавлял жесты прямо в UINavigationBar много раз.

Я предлагаю вам переопределить обработку касаний в подклассе UINavigationBar и сравнить касания с его дочерними элементами. Если ребенок - ваша специальная кнопка «Отменить», вы можете обращаться с ней соответствующим образом.

0 голосов
/ 16 мая 2012
UIButton* undoButton = [UIButton buttonWithType:UIButtonTypeCustom];
[undoButton addTarget:self action:@selector(undoPressStart:) forControlEvents:UIControlEventTouchDown];
[undoButton addTarget:self action:@selector(undoPressFinish:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* navButton = [[[UIBarButtonItem alloc] initWithCustomView:undoButton] autorelease];
self.navigationItem.rightBarButtonItem = navButton;

Вам необязательно добавлять UIBarButtonItem в качестве rightBarButtonItem, это простой и простой способ показать вам, как создать UIBarButtonItem с пользовательским представлением, которое представляет собой UIButton, для которого вы хотите обрабатывать события.

Вам нужно будет реализовать undoPressStart: и undoPressFinish:, поддерживая состояние.Я бы сказал на старте, сохранить текущую NSDate или какое-то детальное представление времени.По окончании, если проверьте истекшее время и если оно превышает определенный порог, покажите меню - в противном случае (а также если дата начала не была зафиксирована) выполните отмену.

В качестве улучшения вы 'Вероятно, вы захотите наблюдать событие UIControlEventTouchDragExit, чтобы отменить долгое нажатие.

0 голосов
/ 11 мая 2012

Если вы используете IB (или в Xcode4 конструктор ... я думаю, это называется), то вы можете выбрать «Отменить» в первом респонденте и перетащить это действие на кнопку. Я могу дать вам более конкретные инструкции, если это не распространяется.

Вот как это выглядит Undo Interface Builder image

Слева внизу под колонкой "Полученные действия"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...