Добавляем кнопку для UIKeyboardTypeNumberPad

Многие разработчики сталкивались с тем, что если в iOS для iPhone выбрать у UITextField тип UIKeyboardTypeNumberPad, то слева внизу будет пустое место вместо кнопки.

У этого типа клавиатуры не работает свойство returnKeyType и её возможно убрать с экрана только повесив обработчик на касание в пустом месте (например UIView)

Осторожно трафик

Интернете можно найти массу примеров, как добавить свою кнопку на такую клавиатуру, но у меня возникла задача добавить кнопку скрытия на полупрозрачную клавиатуру (UIKeyboardAppearanceAlert), чтобы получился вот так вот вид:



Вначале я планировал описать как решил эту задачу, но допилив до универсального состояния понял, что описывать будет долго и путано. В итоге сделав всё как отдельный класс, опишу как запустить.

Первым делом скачиваем сам класс.

В архиве будут три файла и папка с демо проектом. Нам нужны только эти три файла:
AMTextFieldNumberPad.h
AMTextFieldNumberPad.m
AMTextFieldNumberPad.bundle (в нем хранятся необходимые изображения)

Подключаем их к проекту.

Потом в нужном контролере в хидере подключаем класс:


В Interface Builder добавляем UITextField и прописываем у него класс


И делаем связь между объектами


Вот, собственно, и всё.

Так же можно вызывать программно


Теперь расскажу о возможностях класса.
Класс поддерживает обычную и прозрачную клавиатуру

На кнопку можно добавить свой текст:


Если текст не указывать, тогда он подставится автоматически из returnKeyType:


Можно сделать кнопку с иконкой клавиатуры (как в iPad):


Или же указать любую свою:


Ну и поддержка горизонтальной ориентации:


Я, естественно, не претендую на идеальное решение, если кто знает лучшие способы — буду очень признателен.

Так же прикладываю ссылку на репозиторий
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 28

    +4
    Зачем добавили в репозиторий кучу мусора, например нужно убрать оттуда совсем папку build.
    Судя по вашим предыдущим работам делаете успехи.
    уже и CGFloat вместо float исползуете и управление памятью тоже с первого взгляда нормальное, но есть много мелких замечаний и пару серьезных, например:

    - (id)initWithFrame:(CGRect)frame {
    if ((self == [super initWithFrame:frame])) {
    [self setup];
    }
    return self;
    }

    - (id)init {
    if ((self == [super init])) {
    [self setup];
    }
    return self;
    }


    Там нужно ставить «self =», надеюсь понятно почему и объяснять не нужно.

    Далее, зачем городить такие конструкции ???
    [NSStringFromClass([v class]) isEqualToString:@"UIButton"]

    проще и быстрее сделать так:
    [v isKindOfClass:[UIButton class]];
    Быстрее, и универсальней, так как еще и наследников покрывает, а если нужен точный класс то для этого есть другой метод.

    Ну и еще несколько замечаний, который постарайтесь найти сами.
      0
      Метод «getKeyboardWindow» заставил меня заплакать, неужели вы считаете это хорошей реализацией?
        0
        Не могли бы вы объяснить а что именно смутило вас?
          0
          есть более изящные и элегантные решения работы с NSArray и элементами в нем.
            0
            Я надеюсь вы не про [arr objectAtIndex:1]?
              +1
              нет, конечно не в этом дело.
              Там в общем целых нцать замечаний,
              Почему не использовать indexOfObjectPassingTest?
              если хотите поддержать 2 платформу, то почему бы не использовать предикат?

              Ну раз решили «влоб» перебором, то зачем плодить дополнительные ветвления в коде, лучше было бы сделать как-нибудь так:

              for (UIWindow *w in [[UIApplication sharedApplication] windows])
              if ([NSStringFromClass([w class]) isEqualToString:@"UITextEffectsWindow"]) return w;
              return nil;


              Ну и наконец — это PrivateAPI.
                +1
                вернее класс UITextEffectsWindow — не из публичного API, что делает код не стабильным — может поломаться с выходом новой версии (хотя в данном случае разве что с выходом IOS5)
                  0
                  Скажу честно, это единственный способ который я нашел чтобы получить доступ к нужной view.
                  По поводу поломаться с новой версией согласен.
                  На 5.0 протестировал, работает, думаю со временем найду более лучшее решение
                    0
                    я думаю там окон в sharedApplication не так и много(по идее должно быть 3 если я не ошибаюсь — статусная панель, окно прилоежния и вот всплывшая клава), нужно найти между ними другое различие (не по имени класса).
                    Это как вариант.
                      0
                      Спасибо, поломаю голову на досуге
        +1
        Документацию по языку хороши читали, что вот это такое?:
        [v setHidden:FALSE];
        Булевые значения: YES/NO.
          +3
          Для тех, кто считает, что я придираюсь на ровном месте.
          В первую очередь — это нарушение стиля кода для платформы.
          А вообще BOOL в Objective-C содержит в себе подводные камни, на которые некоторые новички спотыкаются, и придерживаться документации в данном случае крайне полезно.

          Не многие знают что bool и BOOL — это разные типы — первый это из C99 стандарта, а второе — это занковый char, который был введен в Objective-C для булевого значения, когда в С его не было.
          тоесть:
          typedef signed char BOOL;
          А сами значения определены:
          #define YES (BOOL)1
          #define NO (BOOL)0


          Некоторые спросят, «ну и что» ?, а вот что, вот например такой код:
          BOOL aa = 2;
          if (aa) printf("aa 1\n");
          if (aa != YES) printf("aa 2\n");

          результат:
          >aa 1
          >aa 2


          Поулчается что аа при не отрицательное значение, но при явном сравнении с YES тоже дает отрицательный результат.
          И стоит помнить, что bool!=BOOL и bool может иметь только значения true или false.

          0
          Cпасибо за полезное замечание

          >> [NSStringFromClass([v class]) isEqualToString:@«UIButton»]
          Это на самом деле можно было написать проще
            0
            зачем тут приведение класса?

            buttonDone = [(UIButton *)v retain];


            В 131 строке зачем делать:

            [buttonDone release];
            если мы несколькими строчками выше проверили, что эта переменная нулевая?
              0
              Да, ошибка. Надо было так
              buttonDone = button;
              [button release];

              По поводу приведения класса, ведь мы сначала объявляем объект как UIView
              for (UIView *v in [windowTemp subviews]) {

              Потому перед прививанием явно указываю что это UIButton
                0
                присваиванием конечно же
                  0
                  вообще retain возвращает тип «id», поэтому то что вы написали эквивалентно:
                  buttonDone = [v retain];
            0

            if ([[[UIDevice currentDevice] systemVersion] hasPrefix:@"3"]) {
            [buttonDone setBackgroundImage:[UIImage imageNamed:@"AMTextFieldNumberPad.bundle/button_keyboard3.png"] forState:UIControlStateNormal];
            [buttonDone setBackgroundImage:[UIImage imageNamed:@"AMTextFieldNumberPad.bundle/button_keyboard3_highlighted.png"] forState:UIControlStateHighlighted];
            }
            else {
            [buttonDone setBackgroundImage:[UIImage imageNamed:@"AMTextFieldNumberPad.bundle/button_keyboard4.png"] forState:UIControlStateNormal];
            [buttonDone setBackgroundImage:[UIImage imageNamed:@"AMTextFieldNumberPad.bundle/button_keyboard4_highlighted.png"] forState:UIControlStateHighlighted];


            Не очень хорошее решение, лучше было бы эти текстовые константы вынести в отдельное место и «спрятать» специфичное для каждой версии поведение от рабочей реализации.

              0
              #define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
              #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
              #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
              #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
              #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
            0
            А как вы сделали файл bundle с изображениями? И как с ним работаете в коде.
              0
              Просто создайте папку с расширением bundle, и согласитесь на то что папка будет представлена в виде файла.
              А по поводу работы с ним в коде достаточно просто
              [UIImage imageNamed:@«AMTextFieldNumberPad.bundle/button_keyboard3.png»]
                0
                Хороший вопрос, я и сам не знал. Спасибо
              0
              Вы что-то часто меняете юзера, то вы были seagor c минусами, а теперь воплотились значит в новом виде. Карму и рейтинг беречь надо смолоду!
                0
                Ну а если сливают карму практически не за что, а мне хочется полезные статьи для общества писать.
                Вас что то смущает, или же я как то вам помешал чем то?

                >> что-то часто
                Это скорее всего больше подходит к два раза и более
                +1
                И суровые дяди из аппстора не против, что вот так меняют их классные продуманные нативные контролы? Это проходит аппрув?
                  0
                  Классные не то слово, если бы они в правду сделали классные, то мне бы не пришлось решать задачу как убрать клавиатуру по кнопке, и самое главное в iPad это решено, а iPhone забыли.
                  Апрув это проходит
                    0
                    К слову, у приложения Alfa-Bank такая реализация

                  Only users with full accounts can post comments. Log in, please.